diff options
author | Vincent Ambo <mail@tazj.in> | 2022-02-07T23·05+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-02-07T23·09+0000 |
commit | 5aa5d282eac56a21e74611c1cdbaa97bb5db2dca (patch) | |
tree | 8cc5dce8157a1470ff76719dd15d65f648a05522 /third_party/abseil_cpp | |
parent | a25675804c4f429fab5ee5201fe25e89865dfd13 (diff) |
chore(3p/abseil_cpp): unvendor abseil_cpp r/3786
we weren't actually using these sources anymore, okay? Change-Id: If701571d9716de308d3512e1eb22c35db0877a66 Reviewed-on: https://cl.tvl.fyi/c/depot/+/5248 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Autosubmit: tazjin <tazjin@tvl.su>
Diffstat (limited to 'third_party/abseil_cpp')
1292 files changed, 0 insertions, 216895 deletions
diff --git a/third_party/abseil_cpp/.clang-format b/third_party/abseil_cpp/.clang-format deleted file mode 100644 index 06ea346a1067..000000000000 --- a/third_party/abseil_cpp/.clang-format +++ /dev/null @@ -1,4 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: Google -... 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 1edf3de0ba47..000000000000 --- 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 84cf349189c3..000000000000 --- 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 9794ae1db8bc..000000000000 --- a/third_party/abseil_cpp/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1 +0,0 @@ -blank_issues_enables: true diff --git a/third_party/abseil_cpp/.gitignore b/third_party/abseil_cpp/.gitignore deleted file mode 100644 index d54fa5a91fe6..000000000000 --- a/third_party/abseil_cpp/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Ignore all bazel-* symlinks. -/bazel-* -# Ignore Bazel verbose explanations ---verbose_explanations -# Ignore CMake usual build directory -build -# Ignore Vim files -*.swp -# Ignore QtCreator Project file -CMakeLists.txt.user -# Ignore VS Code files -.vscode/* -# Ignore generated python artifacts -*.pyc -copts/__pycache__/ diff --git a/third_party/abseil_cpp/.skip-subtree b/third_party/abseil_cpp/.skip-subtree deleted file mode 100644 index d49b47f75a16..000000000000 --- a/third_party/abseil_cpp/.skip-subtree +++ /dev/null @@ -1 +0,0 @@ -Third-party code with non-depot layout. diff --git a/third_party/abseil_cpp/ABSEIL_ISSUE_TEMPLATE.md b/third_party/abseil_cpp/ABSEIL_ISSUE_TEMPLATE.md deleted file mode 100644 index ed5461f166c3..000000000000 --- a/third_party/abseil_cpp/ABSEIL_ISSUE_TEMPLATE.md +++ /dev/null @@ -1,22 +0,0 @@ -Please submit a new Abseil Issue using the template below: - -## [Short title of proposed API change(s)] - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - -## Background - -[Provide the background information that is required in order to evaluate the -proposed API changes. No controversial claims should be made here. If there are -design constraints that need to be considered, they should be presented here -**along with justification for those constraints**. Linking to other docs is -good, but please keep the **pertinent information as self contained** as -possible in this section.] - -## Proposed API Change (s) - -[Please clearly describe the API change(s) being proposed. If multiple changes, -please keep them clearly distinguished. When possible, **use example code -snippets to illustrate before-after API usages**. List pros-n-cons. Highlight -the main questions that you want to be answered. Given the Abseil project compatibility requirements, describe why the API change is safe.] diff --git a/third_party/abseil_cpp/AUTHORS b/third_party/abseil_cpp/AUTHORS deleted file mode 100644 index 976d31defc26..000000000000 --- a/third_party/abseil_cpp/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -# This is the list of Abseil authors for copyright purposes. -# -# This does not necessarily list everyone who has contributed code, since in -# some cases, their employer may be the copyright holder. To see the full list -# of contributors, see the revision history in source control. -Google Inc. diff --git a/third_party/abseil_cpp/BUILD.bazel b/third_party/abseil_cpp/BUILD.bazel deleted file mode 100644 index 79fb0ecd73ef..000000000000 --- 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 deleted file mode 100644 index e0ff2492e7f2..000000000000 --- a/third_party/abseil_cpp/CMake/AbseilDll.cmake +++ /dev/null @@ -1,514 +0,0 @@ -include(CMakeParseArguments) - -set(ABSL_INTERNAL_DLL_FILES - "algorithm/algorithm.h" - "algorithm/container.h" - "base/attributes.h" - "base/call_once.h" - "base/casts.h" - "base/config.h" - "base/const_init.h" - "base/dynamic_annotations.h" - "base/internal/atomic_hook.h" - "base/internal/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/exponential_biased.cc" - "base/internal/exponential_biased.h" - "base/internal/fast_type_id.h" - "base/internal/hide_ptr.h" - "base/internal/identity.h" - "base/internal/invoke.h" - "base/internal/inline_variable.h" - "base/internal/low_level_alloc.cc" - "base/internal/low_level_alloc.h" - "base/internal/low_level_scheduling.h" - "base/internal/per_thread_tls.h" - "base/internal/periodic_sampler.cc" - "base/internal/periodic_sampler.h" - "base/internal/pretty_function.h" - "base/internal/raw_logging.cc" - "base/internal/raw_logging.h" - "base/internal/scheduling_mode.h" - "base/internal/scoped_set_env.cc" - "base/internal/scoped_set_env.h" - "base/internal/strerror.h" - "base/internal/strerror.cc" - "base/internal/spinlock.cc" - "base/internal/spinlock.h" - "base/internal/spinlock_wait.cc" - "base/internal/spinlock_wait.h" - "base/internal/sysinfo.cc" - "base/internal/sysinfo.h" - "base/internal/thread_annotations.h" - "base/internal/thread_identity.cc" - "base/internal/thread_identity.h" - "base/internal/throw_delegate.cc" - "base/internal/throw_delegate.h" - "base/internal/tsan_mutex_interface.h" - "base/internal/unaligned_access.h" - "base/internal/unscaledcycleclock.cc" - "base/internal/unscaledcycleclock.h" - "base/log_severity.cc" - "base/log_severity.h" - "base/macros.h" - "base/optimization.h" - "base/options.h" - "base/policy_checks.h" - "base/port.h" - "base/thread_annotations.h" - "container/btree_map.h" - "container/btree_set.h" - "container/fixed_array.h" - "container/flat_hash_map.h" - "container/flat_hash_set.h" - "container/inlined_vector.h" - "container/internal/btree.h" - "container/internal/btree_container.h" - "container/internal/common.h" - "container/internal/compressed_tuple.h" - "container/internal/container_memory.h" - "container/internal/counting_allocator.h" - "container/internal/hash_function_defaults.h" - "container/internal/hash_policy_traits.h" - "container/internal/hashtable_debug.h" - "container/internal/hashtable_debug_hooks.h" - "container/internal/hashtablez_sampler.cc" - "container/internal/hashtablez_sampler.h" - "container/internal/hashtablez_sampler_force_weak_definition.cc" - "container/internal/have_sse.h" - "container/internal/inlined_vector.h" - "container/internal/layout.h" - "container/internal/node_hash_policy.h" - "container/internal/raw_hash_map.h" - "container/internal/raw_hash_set.cc" - "container/internal/raw_hash_set.h" - "container/internal/tracked.h" - "container/node_hash_map.h" - "container/node_hash_set.h" - "debugging/failure_signal_handler.cc" - "debugging/failure_signal_handler.h" - "debugging/leak_check.h" - "debugging/leak_check_disable.cc" - "debugging/stacktrace.cc" - "debugging/stacktrace.h" - "debugging/symbolize.cc" - "debugging/symbolize.h" - "debugging/internal/address_is_readable.cc" - "debugging/internal/address_is_readable.h" - "debugging/internal/demangle.cc" - "debugging/internal/demangle.h" - "debugging/internal/elf_mem_image.cc" - "debugging/internal/elf_mem_image.h" - "debugging/internal/examine_stack.cc" - "debugging/internal/examine_stack.h" - "debugging/internal/stack_consumption.cc" - "debugging/internal/stack_consumption.h" - "debugging/internal/stacktrace_config.h" - "debugging/internal/symbolize.h" - "debugging/internal/vdso_support.cc" - "debugging/internal/vdso_support.h" - "functional/internal/front_binder.h" - "functional/bind_front.h" - "functional/function_ref.h" - "functional/internal/function_ref.h" - "hash/hash.h" - "hash/internal/city.h" - "hash/internal/city.cc" - "hash/internal/hash.h" - "hash/internal/hash.cc" - "hash/internal/spy_hash_state.h" - "memory/memory.h" - "meta/type_traits.h" - "numeric/int128.cc" - "numeric/int128.h" - "random/bernoulli_distribution.h" - "random/beta_distribution.h" - "random/bit_gen_ref.h" - "random/discrete_distribution.cc" - "random/discrete_distribution.h" - "random/distributions.h" - "random/exponential_distribution.h" - "random/gaussian_distribution.cc" - "random/gaussian_distribution.h" - "random/internal/distribution_caller.h" - "random/internal/fastmath.h" - "random/internal/fast_uniform_bits.h" - "random/internal/generate_real.h" - "random/internal/iostream_state_saver.h" - "random/internal/mock_helpers.h" - "random/internal/nonsecure_base.h" - "random/internal/pcg_engine.h" - "random/internal/platform.h" - "random/internal/pool_urbg.cc" - "random/internal/pool_urbg.h" - "random/internal/randen.cc" - "random/internal/randen.h" - "random/internal/randen_detect.cc" - "random/internal/randen_detect.h" - "random/internal/randen_engine.h" - "random/internal/randen_hwaes.cc" - "random/internal/randen_hwaes.h" - "random/internal/randen_round_keys.cc" - "random/internal/randen_slow.cc" - "random/internal/randen_slow.h" - "random/internal/randen_traits.h" - "random/internal/salted_seed_seq.h" - "random/internal/seed_material.cc" - "random/internal/seed_material.h" - "random/internal/sequence_urbg.h" - "random/internal/traits.h" - "random/internal/uniform_helper.h" - "random/internal/wide_multiply.h" - "random/log_uniform_int_distribution.h" - "random/poisson_distribution.h" - "random/random.h" - "random/seed_gen_exception.cc" - "random/seed_gen_exception.h" - "random/seed_sequences.cc" - "random/seed_sequences.h" - "random/uniform_int_distribution.h" - "random/uniform_real_distribution.h" - "random/zipf_distribution.h" - "status/internal/status_internal.h" - "status/internal/statusor_internal.h" - "status/status.h" - "status/status.cc" - "status/statusor.h" - "status/statusor.cc" - "status/status_payload_printer.h" - "status/status_payload_printer.cc" - "strings/ascii.cc" - "strings/ascii.h" - "strings/charconv.cc" - "strings/charconv.h" - "strings/cord.cc" - "strings/cord.h" - "strings/escaping.cc" - "strings/escaping.h" - "strings/internal/cord_internal.h" - "strings/internal/charconv_bigint.cc" - "strings/internal/charconv_bigint.h" - "strings/internal/charconv_parse.cc" - "strings/internal/charconv_parse.h" - "strings/internal/stl_type_traits.h" - "strings/internal/string_constant.h" - "strings/match.cc" - "strings/match.h" - "strings/numbers.cc" - "strings/numbers.h" - "strings/str_format.h" - "strings/str_cat.cc" - "strings/str_cat.h" - "strings/str_join.h" - "strings/str_replace.cc" - "strings/str_replace.h" - "strings/str_split.cc" - "strings/str_split.h" - "strings/string_view.cc" - "strings/string_view.h" - "strings/strip.h" - "strings/substitute.cc" - "strings/substitute.h" - "strings/internal/char_map.h" - "strings/internal/escaping.h" - "strings/internal/escaping.cc" - "strings/internal/memutil.cc" - "strings/internal/memutil.h" - "strings/internal/ostringstream.cc" - "strings/internal/ostringstream.h" - "strings/internal/pow10_helper.cc" - "strings/internal/pow10_helper.h" - "strings/internal/resize_uninitialized.h" - "strings/internal/str_format/arg.cc" - "strings/internal/str_format/arg.h" - "strings/internal/str_format/bind.cc" - "strings/internal/str_format/bind.h" - "strings/internal/str_format/checker.h" - "strings/internal/str_format/extension.cc" - "strings/internal/str_format/extension.h" - "strings/internal/str_format/float_conversion.cc" - "strings/internal/str_format/float_conversion.h" - "strings/internal/str_format/output.cc" - "strings/internal/str_format/output.h" - "strings/internal/str_format/parser.cc" - "strings/internal/str_format/parser.h" - "strings/internal/str_join_internal.h" - "strings/internal/str_split_internal.h" - "strings/internal/utf8.cc" - "strings/internal/utf8.h" - "synchronization/barrier.cc" - "synchronization/barrier.h" - "synchronization/blocking_counter.cc" - "synchronization/blocking_counter.h" - "synchronization/mutex.cc" - "synchronization/mutex.h" - "synchronization/notification.cc" - "synchronization/notification.h" - "synchronization/internal/create_thread_identity.cc" - "synchronization/internal/create_thread_identity.h" - "synchronization/internal/futex.h" - "synchronization/internal/graphcycles.cc" - "synchronization/internal/graphcycles.h" - "synchronization/internal/kernel_timeout.h" - "synchronization/internal/per_thread_sem.cc" - "synchronization/internal/per_thread_sem.h" - "synchronization/internal/thread_pool.h" - "synchronization/internal/waiter.cc" - "synchronization/internal/waiter.h" - "time/civil_time.cc" - "time/civil_time.h" - "time/clock.cc" - "time/clock.h" - "time/duration.cc" - "time/format.cc" - "time/time.cc" - "time/time.h" - "time/internal/cctz/include/cctz/civil_time.h" - "time/internal/cctz/include/cctz/civil_time_detail.h" - "time/internal/cctz/include/cctz/time_zone.h" - "time/internal/cctz/include/cctz/zone_info_source.h" - "time/internal/cctz/src/civil_time_detail.cc" - "time/internal/cctz/src/time_zone_fixed.cc" - "time/internal/cctz/src/time_zone_fixed.h" - "time/internal/cctz/src/time_zone_format.cc" - "time/internal/cctz/src/time_zone_if.cc" - "time/internal/cctz/src/time_zone_if.h" - "time/internal/cctz/src/time_zone_impl.cc" - "time/internal/cctz/src/time_zone_impl.h" - "time/internal/cctz/src/time_zone_info.cc" - "time/internal/cctz/src/time_zone_info.h" - "time/internal/cctz/src/time_zone_libc.cc" - "time/internal/cctz/src/time_zone_libc.h" - "time/internal/cctz/src/time_zone_lookup.cc" - "time/internal/cctz/src/time_zone_posix.cc" - "time/internal/cctz/src/time_zone_posix.h" - "time/internal/cctz/src/tzfile.h" - "time/internal/cctz/src/zone_info_source.cc" - "types/any.h" - "types/bad_any_cast.cc" - "types/bad_any_cast.h" - "types/bad_optional_access.cc" - "types/bad_optional_access.h" - "types/bad_variant_access.cc" - "types/bad_variant_access.h" - "types/compare.h" - "types/internal/conformance_aliases.h" - "types/internal/conformance_archetype.h" - "types/internal/conformance_profile.h" - "types/internal/parentheses.h" - "types/internal/transform_args.h" - "types/internal/variant.h" - "types/optional.h" - "types/internal/optional.h" - "types/span.h" - "types/internal/span.h" - "types/variant.h" - "utility/utility.h" -) - -set(ABSL_INTERNAL_DLL_TARGETS - "stacktrace" - "symbolize" - "examine_stack" - "failure_signal_handler" - "debugging_internal" - "demangle_internal" - "leak_check" - "leak_check_disable" - "stack_consumption" - "debugging" - "hash" - "spy_hash_state" - "city" - "memory" - "strings" - "strings_internal" - "cord" - "str_format" - "str_format_internal" - "pow10_helper" - "int128" - "numeric" - "utility" - "any" - "bad_any_cast" - "bad_any_cast_impl" - "span" - "optional" - "bad_optional_access" - "bad_variant_access" - "variant" - "compare" - "algorithm" - "algorithm_container" - "graphcycles_internal" - "kernel_timeout_internal" - "synchronization" - "thread_pool" - "bind_front" - "function_ref" - "atomic_hook" - "log_severity" - "raw_logging_internal" - "spinlock_wait" - "config" - "dynamic_annotations" - "core_headers" - "malloc_internal" - "base_internal" - "base" - "throw_delegate" - "pretty_function" - "endian" - "bits" - "exponential_biased" - "periodic_sampler" - "scoped_set_env" - "type_traits" - "meta" - "random_random" - "random_bit_gen_ref" - "random_distributions" - "random_seed_gen_exception" - "random_seed_sequences" - "random_internal_traits" - "random_internal_distribution_caller" - "random_internal_distributions" - "random_internal_fast_uniform_bits" - "random_internal_seed_material" - "random_internal_pool_urbg" - "random_internal_explicit_seed_seq" - "random_internal_sequence_urbg" - "random_internal_salted_seed_seq" - "random_internal_iostream_state_saver" - "random_internal_generate_real" - "random_internal_wide_multiply" - "random_internal_fastmath" - "random_internal_nonsecure_base" - "random_internal_pcg_engine" - "random_internal_randen_engine" - "random_internal_platform" - "random_internal_randen" - "random_internal_randen_slow" - "random_internal_randen_hwaes" - "random_internal_randen_hwaes_impl" - "random_internal_uniform_helper" - "status" - "time" - "civil_time" - "time_zone" - "container" - "btree" - "compressed_tuple" - "fixed_array" - "inlined_vector_internal" - "inlined_vector" - "counting_allocator" - "flat_hash_map" - "flat_hash_set" - "node_hash_map" - "node_hash_set" - "container_memory" - "hash_function_defaults" - "hash_policy_traits" - "hashtablez_sampler" - "hashtable_debug" - "hashtable_debug_hooks" - "have_sse" - "node_hash_policy" - "raw_hash_map" - "container_common" - "raw_hash_set" - "layout" - "tracked" -) - -function(absl_internal_dll_contains) - cmake_parse_arguments(ABSL_INTERNAL_DLL - "" - "OUTPUT;TARGET" - "" - ${ARGN} - ) - - STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET}) - - list(FIND - ABSL_INTERNAL_DLL_TARGETS - "${_target}" - _index) - - if (${_index} GREATER -1) - set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE) - else() - set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE) - endif() -endfunction() - -function(absl_internal_dll_targets) - cmake_parse_arguments(ABSL_INTERNAL_DLL - "" - "OUTPUT" - "DEPS" - ${ARGN} - ) - - set(_deps "") - foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS) - absl_internal_dll_contains(TARGET ${dep} OUTPUT _contains) - if (_contains) - list(APPEND _deps abseil_dll) - else() - list(APPEND _deps ${dep}) - endif() - endforeach() - - # Because we may have added the DLL multiple times - list(REMOVE_DUPLICATES _deps) - set(${ABSL_INTERNAL_DLL_OUTPUT} "${_deps}" PARENT_SCOPE) -endfunction() - -function(absl_make_dll) - add_library( - abseil_dll - SHARED - "${ABSL_INTERNAL_DLL_FILES}" - ) - target_link_libraries( - abseil_dll - PRIVATE - ${ABSL_DEFAULT_LINKOPTS} - ) - set_property(TARGET abseil_dll PROPERTY LINKER_LANGUAGE "CXX") - target_include_directories( - abseil_dll - PUBLIC - "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>" - $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}> - ) - - target_compile_options( - abseil_dll - PRIVATE - ${ABSL_DEFAULT_COPTS} - ) - - target_compile_definitions( - abseil_dll - PRIVATE - ABSL_BUILD_DLL - NOMINMAX - INTERFACE - ${ABSL_CC_LIB_DEFINES} - ) - install(TARGETS abseil_dll EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${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 deleted file mode 100644 index e88507de562c..000000000000 --- a/third_party/abseil_cpp/CMake/AbseilHelpers.cmake +++ /dev/null @@ -1,402 +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(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() - -# absl_cc_library() -# -# CMake function to imitate Bazel's cc_library rule. -# -# Parameters: -# NAME: name of target (see Note) -# HDRS: List of public header files for the library -# SRCS: List of source files for the library -# DEPS: List of other libraries to be linked in to the binary targets -# COPTS: List of private compile options -# DEFINES: List of public defines -# LINKOPTS: List of link options -# PUBLIC: Add this so that this library will be exported under absl:: -# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal. -# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake. -# -# Note: -# By default, absl_cc_library will always create a library named absl_${NAME}, -# and alias target absl::${NAME}. The absl:: form should always be used. -# This is to reduce namespace pollution. -# -# absl_cc_library( -# NAME -# awesome -# HDRS -# "a.h" -# SRCS -# "a.cc" -# ) -# absl_cc_library( -# NAME -# fantastic_lib -# SRCS -# "b.cc" -# DEPS -# absl::awesome # not "awesome" ! -# PUBLIC -# ) -# -# absl_cc_library( -# NAME -# main_lib -# ... -# DEPS -# absl::fantastic_lib -# ) -# -# TODO: Implement "ALWAYSLINK" -function(absl_cc_library) - cmake_parse_arguments(ABSL_CC_LIB - "DISABLE_INSTALL;PUBLIC;TESTONLY" - "NAME" - "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS" - ${ARGN} - ) - - if(ABSL_CC_LIB_TESTONLY AND NOT ABSL_RUN_TESTS) - return() - endif() - - if(ABSL_ENABLE_INSTALL) - set(_NAME "${ABSL_CC_LIB_NAME}") - else() - set(_NAME "absl_${ABSL_CC_LIB_NAME}") - endif() - - # Check if this is a header-only library - # Note that as of February 2019, many popular OS's (for example, Ubuntu - # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't - # use list(FILTER...) - set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}") - foreach(src_file IN LISTS ABSL_CC_SRCS) - if(${src_file} MATCHES ".*\\.(h|inc)") - list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}") - endif() - endforeach() - - if("${ABSL_CC_SRCS}" STREQUAL "") - set(ABSL_CC_LIB_IS_INTERFACE 1) - else() - set(ABSL_CC_LIB_IS_INTERFACE 0) - endif() - - # Determine this build target's relationship to the DLL. It's one of four things: - # 1. "dll" -- This target is part of the DLL - # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL. - # Note that we assume any target not in the DLL depends on the - # DLL. This is not a technical necessity but a convenience - # which happens to be true, because nearly every target is - # part of the DLL. - # 3. "shared" -- This is a shared library, perhaps on a non-windows platform - # where DLL doesn't make sense. - # 4. "static" -- This target does not depend on the DLL and should be built - # statically. - if (${ABSL_BUILD_DLL}) - if(ABSL_ENABLE_INSTALL) - absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) - else() - absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll) - endif() - if (${_in_dll}) - # This target should be replaced by the DLL - set(_build_type "dll") - set(ABSL_CC_LIB_IS_INTERFACE 1) - else() - # Building a DLL, but this target is not part of the DLL - set(_build_type "dll_dep") - endif() - elseif(BUILD_SHARED_LIBS) - set(_build_type "shared") - else() - set(_build_type "static") - endif() - - # Generate a pkg-config file for every library: - if(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared") - if(NOT ABSL_CC_LIB_TESTONLY) - if(absl_VERSION) - set(PC_VERSION "${absl_VERSION}") - else() - set(PC_VERSION "head") - endif() - foreach(dep ${ABSL_CC_LIB_DEPS}) - if(${dep} MATCHES "^absl::(.*)") - set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}") - endif() - endforeach() - foreach(cflag ${ABSL_CC_LIB_COPTS}) - if(${cflag} MATCHES "^(-Wno|/wd)") - # These flags are needed to suppress warnings that might fire in our headers. - set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") - elseif(${cflag} MATCHES "^(-W|/w[1234eo])") - # Don't impose our warnings on others. - else() - set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") - endif() - endforeach() - FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ -prefix=${CMAKE_INSTALL_PREFIX}\n\ -exec_prefix=\${prefix}\n\ -libdir=\${prefix}/lib\n\ -includedir=\${prefix}/include\n\ -\n\ -Name: absl_${_NAME}\n\ -Description: Abseil ${_NAME} library\n\ -URL: https://abseil.io/\n\ -Version: ${PC_VERSION}\n\ -Requires.private:${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_PREFIX}/lib/pkgconfig") - endif() - endif() - - if(NOT ABSL_CC_LIB_IS_INTERFACE) - if(${_build_type} STREQUAL "dll_dep") - # This target depends on the DLL. When adding dependencies to this target, - # any depended-on-target which is contained inside the DLL is replaced - # with a dependency on the DLL. - add_library(${_NAME} STATIC "") - target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) - absl_internal_dll_targets( - DEPS ${ABSL_CC_LIB_DEPS} - OUTPUT _dll_deps - ) - target_link_libraries(${_NAME} - PUBLIC ${_dll_deps} - PRIVATE - ${ABSL_CC_LIB_LINKOPTS} - ${ABSL_DEFAULT_LINKOPTS} - ) - - if (ABSL_CC_LIB_TESTONLY) - set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1") - else() - set(_gtest_link_define) - endif() - - target_compile_definitions(${_NAME} - PUBLIC - ABSL_CONSUME_DLL - "${_gtest_link_define}" - ) - - elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared") - add_library(${_NAME} "") - target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) - target_link_libraries(${_NAME} - PUBLIC ${ABSL_CC_LIB_DEPS} - PRIVATE - ${ABSL_CC_LIB_LINKOPTS} - ${ABSL_DEFAULT_LINKOPTS} - ) - else() - message(FATAL_ERROR "Invalid build type: ${_build_type}") - endif() - - # Linker language can be inferred from sources, but in the case of DLLs we - # don't have any .cc files so it would be ambiguous. We could set it - # explicitly only in the case of DLLs but, because "CXX" is always the - # correct linker language for static or for shared libraries, we set it - # unconditionally. - set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX") - - target_include_directories(${_NAME} - PUBLIC - "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>" - $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}> - ) - target_compile_options(${_NAME} - PRIVATE ${ABSL_CC_LIB_COPTS}) - target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES}) - - # Add all Abseil targets to a a folder in the IDE for organization. - if(ABSL_CC_LIB_PUBLIC) - set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}) - elseif(ABSL_CC_LIB_TESTONLY) - set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) - else() - set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal) - endif() - - # INTERFACE libraries can't have the CXX_STANDARD property set - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) - - # When being installed, we lose the absl_ prefix. We want to put it back - # to have properly named lib files. This is a no-op when we are not being - # installed. - if(ABSL_ENABLE_INSTALL) - set_target_properties(${_NAME} PROPERTIES - OUTPUT_NAME "absl_${_NAME}" - # TODO(b/173696973): Figure out how to set SOVERSION for LTS releases. - SOVERSION 0 - ) - endif() - else() - # Generating header-only library - add_library(${_NAME} INTERFACE) - target_include_directories(${_NAME} - INTERFACE - "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>" - $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}> - ) - - if (${_build_type} STREQUAL "dll") - set(ABSL_CC_LIB_DEPS abseil_dll) - endif() - - target_link_libraries(${_NAME} - INTERFACE - ${ABSL_CC_LIB_DEPS} - ${ABSL_CC_LIB_LINKOPTS} - ${ABSL_DEFAULT_LINKOPTS} - ) - target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) - endif() - - # TODO currently we don't install googletest alongside abseil sources, so - # installed abseil can't be tested. - if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL) - install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR} - LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR} - ) - endif() - - add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) -endfunction() - -# absl_cc_test() -# -# CMake function to imitate Bazel's cc_test rule. -# -# Parameters: -# NAME: name of target (see Usage below) -# SRCS: List of source files for the binary -# DEPS: List of other libraries to be linked in to the binary targets -# COPTS: List of private compile options -# DEFINES: List of public defines -# LINKOPTS: List of link options -# -# Note: -# By default, absl_cc_test will always create a binary named absl_${NAME}. -# This will also add it to ctest list as absl_${NAME}. -# -# Usage: -# absl_cc_library( -# NAME -# awesome -# HDRS -# "a.h" -# SRCS -# "a.cc" -# PUBLIC -# ) -# -# absl_cc_test( -# NAME -# awesome_test -# SRCS -# "awesome_test.cc" -# DEPS -# absl::awesome -# gmock -# gtest_main -# ) -function(absl_cc_test) - if(NOT ABSL_RUN_TESTS) - return() - endif() - - cmake_parse_arguments(ABSL_CC_TEST - "" - "NAME" - "SRCS;COPTS;DEFINES;LINKOPTS;DEPS" - ${ARGN} - ) - - set(_NAME "absl_${ABSL_CC_TEST_NAME}") - - add_executable(${_NAME} "") - target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS}) - target_include_directories(${_NAME} - PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} - PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} - ) - - if (${ABSL_BUILD_DLL}) - target_compile_definitions(${_NAME} - PUBLIC - ${ABSL_CC_TEST_DEFINES} - ABSL_CONSUME_DLL - GTEST_LINKED_AS_SHARED_LIBRARY=1 - ) - - # Replace dependencies on targets inside the DLL with abseil_dll itself. - absl_internal_dll_targets( - DEPS ${ABSL_CC_TEST_DEPS} - OUTPUT ABSL_CC_TEST_DEPS - ) - else() - target_compile_definitions(${_NAME} - PUBLIC - ${ABSL_CC_TEST_DEFINES} - ) - endif() - target_compile_options(${_NAME} - PRIVATE ${ABSL_CC_TEST_COPTS} - ) - - target_link_libraries(${_NAME} - PUBLIC ${ABSL_CC_TEST_DEPS} - PRIVATE ${ABSL_CC_TEST_LINKOPTS} - ) - # Add all Abseil targets to a folder in the IDE for organization. - set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) - - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) - set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) - - add_test(NAME ${_NAME} COMMAND ${_NAME}) -endfunction() - - -function(check_target my_target) - if(NOT TARGET ${my_target}) - message(FATAL_ERROR " ABSL: compiling absl requires a ${my_target} CMake target in your project, - see CMake/README.md for more details") - endif(NOT TARGET ${my_target}) -endfunction() diff --git a/third_party/abseil_cpp/CMake/AbseilInstallDirs.cmake b/third_party/abseil_cpp/CMake/AbseilInstallDirs.cmake deleted file mode 100644 index 6fc914b60f62..000000000000 --- a/third_party/abseil_cpp/CMake/AbseilInstallDirs.cmake +++ /dev/null @@ -1,20 +0,0 @@ -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() diff --git a/third_party/abseil_cpp/CMake/Googletest/CMakeLists.txt.in b/third_party/abseil_cpp/CMake/Googletest/CMakeLists.txt.in deleted file mode 100644 index 5769e3a97b62..000000000000 --- a/third_party/abseil_cpp/CMake/Googletest/CMakeLists.txt.in +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 2.8.2) - -project(googletest-external NONE) - -include(ExternalProject) -ExternalProject_Add(googletest - URL "${absl_gtest_download_url}" # May be empty - SOURCE_DIR "${absl_gtest_src_dir}" - BINARY_DIR "${absl_gtest_build_dir}" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" -) diff --git a/third_party/abseil_cpp/CMake/Googletest/DownloadGTest.cmake b/third_party/abseil_cpp/CMake/Googletest/DownloadGTest.cmake deleted file mode 100644 index 9d071c917011..000000000000 --- a/third_party/abseil_cpp/CMake/Googletest/DownloadGTest.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# Integrates googletest at configure time. Based on the instructions at -# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project - -# Set up the external googletest project, downloading the latest from Github -# master if requested. -configure_file( - ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in - ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt -) - -set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -set(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -if (BUILD_SHARED_LIBS) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1") -endif() - -# Configure and build the googletest source. -execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external ) -if(result) - message(FATAL_ERROR "CMake step for googletest failed: ${result}") -endif() - -execute_process(COMMAND ${CMAKE_COMMAND} --build . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external) -if(result) - message(FATAL_ERROR "Build step for googletest failed: ${result}") -endif() - -set(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - -# Prevent overriding the parent project's compiler/linker settings on Windows -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - -# Add googletest directly to our build. This defines the gtest and gtest_main -# targets. -add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL) diff --git a/third_party/abseil_cpp/CMake/README.md b/third_party/abseil_cpp/CMake/README.md deleted file mode 100644 index 8f73475a1621..000000000000 --- a/third_party/abseil_cpp/CMake/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# Abseil CMake Build Instructions - -Abseil comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt)) -that can be used on a wide range of platforms ("C" stands for cross-platform.). -If you don't have CMake installed already, you can download it for free from -<https://www.cmake.org/>. - -CMake works by generating native makefiles or build projects that can -be used in the compiler environment of your choice. - -For API/ABI compatibility reasons, we strongly recommend building Abseil in a -subdirectory of your project or as an embedded dependency. - -## Incorporating Abseil Into a CMake Project - -The recommendations below are similar to those for using CMake within the -googletest framework -(<https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project>) - -### Step-by-Step Instructions - -1. If you want to build the Abseil tests, integrate the Abseil dependency -[Google Test](https://github.com/google/googletest) into your CMake project. To disable Abseil tests, you have to pass -`-DBUILD_TESTING=OFF` when configuring your project with CMake. - -2. Download Abseil and copy it into a subdirectory in your CMake project or add -Abseil as a [git submodule](https://git-scm.com/docs/git-submodule) in your -CMake project. - -3. You can then use the CMake command -[`add_subdirectory()`](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) -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 a project file using Abseil. - -```cmake -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) - -add_subdirectory(abseil-cpp) - -add_executable(my_exe source.cpp) -target_link_libraries(my_exe absl::base absl::synchronization absl::strings) -``` - -### Running Abseil Tests with CMake - -Use the `-DABSL_RUN_TESTS=ON` flag to run Abseil tests. Note that if the `-DBUILD_TESTING=OFF` flag is passed then Abseil tests will not be run. - -You will need to provide Abseil with a Googletest dependency. There are two -options for how to do this: - -* Use `-DABSL_USE_GOOGLETEST_HEAD`. This will automatically download the latest -Googletest source into the build directory at configure time. Googletest will -then be compiled directly alongside Abseil's tests. -* Manually integrate Googletest with your build. See -https://github.com/google/googletest/blob/master/googletest/README.md#using-cmake -for more information on using Googletest in a CMake project. - -For example, to run just the Abseil tests, you could use this script: - -``` -cd path/to/abseil-cpp -mkdir build -cd build -cmake -DABSL_USE_GOOGLETEST_HEAD=ON -DABSL_RUN_TESTS=ON .. -make -j -ctest -``` - -Currently, we only run our tests with CMake in a Linux environment, but we are -working on the rest of our supported platforms. See -https://github.com/abseil/abseil-cpp/projects/1 and -https://github.com/abseil/abseil-cpp/issues/109 for more information. - -### Available Abseil CMake Public Targets - -Here's a non-exhaustive list of Abseil CMake public targets: - -```cmake -absl::algorithm -absl::base -absl::debugging -absl::flat_hash_map -absl::flags -absl::memory -absl::meta -absl::numeric -absl::random_random -absl::strings -absl::synchronization -absl::time -absl::utility -``` diff --git a/third_party/abseil_cpp/CMake/abslConfig.cmake.in b/third_party/abseil_cpp/CMake/abslConfig.cmake.in deleted file mode 100644 index 62d246d01e00..000000000000 --- a/third_party/abseil_cpp/CMake/abslConfig.cmake.in +++ /dev/null @@ -1,8 +0,0 @@ -# absl CMake configuration file. - -include(CMakeFindDependencyMacro) -find_dependency(Threads) - -@PACKAGE_INIT@ - -include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/third_party/abseil_cpp/CMake/install_test_project/CMakeLists.txt b/third_party/abseil_cpp/CMake/install_test_project/CMakeLists.txt deleted file mode 100644 index 06b797e9eddc..000000000000 --- a/third_party/abseil_cpp/CMake/install_test_project/CMakeLists.txt +++ /dev/null @@ -1,27 +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. - -# A simple CMakeLists.txt for testing cmake installation - -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) diff --git a/third_party/abseil_cpp/CMake/install_test_project/simple.cc b/third_party/abseil_cpp/CMake/install_test_project/simple.cc deleted file mode 100644 index e9e352912bab..000000000000 --- a/third_party/abseil_cpp/CMake/install_test_project/simple.cc +++ /dev/null @@ -1,23 +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 <iostream> -#include "absl/strings/substitute.h" - -int main(int argc, char** argv) { - for (int i = 0; i < argc; ++i) { - std::cout << absl::Substitute("Arg $0: $1\n", i, argv[i]); - } -} diff --git a/third_party/abseil_cpp/CMake/install_test_project/test.sh b/third_party/abseil_cpp/CMake/install_test_project/test.sh deleted file mode 100755 index ddc7726b6c2d..000000000000 --- a/third_party/abseil_cpp/CMake/install_test_project/test.sh +++ /dev/null @@ -1,162 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# "Unit" and integration tests for 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/absl-build -project_dir="${absl_dir}"/CMake/install_test_project -project_build_dir=/buildfs/project-build - -mkdir -p "${absl_build_dir}" -mkdir -p "${project_build_dir}" - -if [[ "${lts_install}" ]]; then - install_dir="/usr/local" -else - install_dir="${project_build_dir}"/install -fi -mkdir -p "${install_dir}" - -# Test build, install, and link against installed abseil -pushd "${project_build_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)" -if [[ "${output}" != *"Arg 1: printme"* ]]; then - echo "Faulty output on simple project:" - echo "${output}" - exit 1 -fi - -popd - -# Test that we haven't accidentally made absl::abslblah -pushd "${install_dir}" - -# 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 [[ "${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 - absl_subdir="absl" -fi - -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 - -pushd "${HOME}" -cat > hello-abseil.cc << EOF -#include <cstdlib> - -#include "absl/strings/str_format.h" - -int main(int argc, char **argv) { - absl::PrintF("Hello Abseil!\n"); - return EXIT_SUCCESS; -} -EOF -export PKG_CONFIG_PATH="${install_dir}/${libdir}/pkgconfig" -pc_args=($(pkg-config --cflags --libs --static absl_str_format)) -g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}" -hello="$(./hello-abseil)" -[[ "${hello}" == "Hello Abseil!" ]] -popd - -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 deleted file mode 100644 index 2120cb0097a3..000000000000 --- a/third_party/abseil_cpp/CMakeLists.txt +++ /dev/null @@ -1,200 +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. -# - -# Most widely used distributions have cmake 3.5 or greater available as of March -# 2019. A notable exception is RHEL-7 (CentOS7). You can install a current -# version of CMake by first installing Extra Packages for Enterprise Linux -# (https://fedoraproject.org/wiki/EPEL#Extra_Packages_for_Enterprise_Linux_.28EPEL.29) -# and then issuing `yum install cmake3` on the command line. -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) - -# if command can use IN_LIST -if (POLICY CMP0057) - cmake_policy(SET CMP0057 NEW) -endif (POLICY CMP0057) - -# Project version variables are the empty string if version is unspecified -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif (POLICY CMP0048) - -# option() honor variables -if (POLICY CMP0077) - cmake_policy(SET CMP0077 NEW) -endif (POLICY CMP0077) - -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 -# directory as the executable using it. Thus, we put all executables in a single -# /bin directory. -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) -else() - option(ABSL_ENABLE_INSTALL "Enable install rule" ON) -endif() - -list(APPEND CMAKE_MODULE_PATH - ${CMAKE_CURRENT_LIST_DIR}/CMake - ${CMAKE_CURRENT_LIST_DIR}/absl/copts -) - -# Linking Abseil to shared libraries (such as Nix) requires PIC. -set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) - -include(AbseilInstallDirs) -include(CMakePackageConfigHelpers) -include(AbseilDll) -include(AbseilHelpers) - - -## -## Using absl targets -## -## all public absl targets are -## exported with the absl:: prefix -## -## e.g absl::base absl::synchronization absl::strings .... -## -## DO NOT rely on the internal targets outside of the prefix - - -# include current path -list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) - -if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(ABSL_USING_CLANG ON) -else() - set(ABSL_USING_CLANG OFF) -endif() - -# find dependencies -## pthread -find_package(Threads REQUIRED) - -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) - -option(ABSL_USE_GOOGLETEST_HEAD - "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") - -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." - ) - -option(ABSL_RUN_TESTS "If ON, Abseil tests will be run." OFF) - -if(${ABSL_RUN_TESTS}) - # enable CTest. This will set BUILD_TESTING to ON unless otherwise specified - # on the command line - include(CTest) - - ## check targets - if (NOT ABSL_USE_EXTERNAL_GOOGLETEST) - 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() - include(CMake/Googletest/DownloadGTest.cmake) - endif() - - check_target(gtest) - check_target(gtest_main) - check_target(gmock) - - list(APPEND ABSL_TEST_COMMON_LIBRARIES - gtest_main - gtest - gmock - ${CMAKE_THREAD_LIBS_INIT} - ) -endif() - -add_subdirectory(absl) - -if(ABSL_ENABLE_INSTALL) - # absl:lts-remove-begin(system installation is supported for LTS releases) - # We don't support system-wide installation - list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") - if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) - message(WARNING "\ - The default and system-level install directories are unsupported except in LTS \ - releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ - source or build tree directly.\ - ") - endif() - # absl:lts-remove-end - - # install as a subdirectory only - install(EXPORT ${PROJECT_NAME}Targets - NAMESPACE absl:: - DESTINATION "${ABSL_INSTALL_CONFIGDIR}" - ) - - configure_package_config_file( - CMake/abslConfig.cmake.in - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION "${ABSL_INSTALL_CONFIGDIR}" - ) - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION "${ABSL_INSTALL_CONFIGDIR}" - ) - - # Abseil only has a version in LTS releases. This mechanism is accomplished - # Abseil's internal Copybara (https://github.com/google/copybara) workflows and - # isn't visible in the CMake buildsystem itself. - if(absl_VERSION) - write_basic_package_version_file( - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - COMPATIBILITY ExactVersion - ) - - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION ${ABSL_INSTALL_CONFIGDIR} - ) - endif() # absl_VERSION - - install(DIRECTORY absl - 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/CONTRIBUTING.md b/third_party/abseil_cpp/CONTRIBUTING.md deleted file mode 100644 index 9dadae937601..000000000000 --- a/third_party/abseil_cpp/CONTRIBUTING.md +++ /dev/null @@ -1,141 +0,0 @@ -# How to Contribute to Abseil - -We'd love to accept your patches and contributions to this project. There are -just a few small guidelines you need to follow. - -NOTE: If you are new to GitHub, please start by reading [Pull Request -howto](https://help.github.com/articles/about-pull-requests/) - -## Contributor License Agreement - -Contributions to this project must be accompanied by a Contributor License -Agreement. You (or your employer) retain the copyright to your contribution, -this simply gives us permission to use and redistribute your contributions as -part of the project. Head over to <https://cla.developers.google.com/> to see -your current agreements on file or to sign a new one. - -You generally only need to submit a CLA once, so if you've already submitted one -(even if it was for a different project), you probably don't need to do it -again. - -## Contribution Guidelines - -Potential contributors sometimes ask us if the Abseil project is the appropriate -home for their utility library code or for specific functions implementing -missing portions of the standard. Often, the answer to this question is "no". -We’d like to articulate our thinking on this issue so that our choices can be -understood by everyone and so that contributors can have a better intuition -about whether Abseil might be interested in adopting a new library. - -### Priorities - -Although our mission is to augment the C++ standard library, our goal is not to -provide a full forward-compatible implementation of the latest standard. For us -to consider a library for inclusion in Abseil, it is not enough that a library -is useful. We generally choose to release a library when it meets at least one -of the following criteria: - -* **Widespread usage** - Using our internal codebase to help gauge usage, most - of the libraries we've released have tens of thousands of users. -* **Anticipated widespread usage** - Pre-adoption of some standard-compliant - APIs may not have broad adoption initially but can be expected to pick up - usage when it replaces legacy APIs. `absl::from_chars`, for example, - replaces existing code that converts strings to numbers and will therefore - likely see usage growth. -* **High impact** - APIs that provide a key solution to a specific problem, - such as `absl::FixedArray`, have higher impact than usage numbers may signal - and are released because of their importance. -* **Direct support for a library that falls under one of the above** - When we - want access to a smaller library as an implementation detail for a - higher-priority library we plan to release, we may release it, as we did - with portions of `absl/meta/type_traits.h`. One consequence of this is that - the presence of a library in Abseil does not necessarily mean that other - similar libraries would be a high priority. - -### API Freeze Consequences - -Via the -[Abseil Compatibility Guidelines](https://abseil.io/about/compatibility), we -have promised a large degree of API stability. In particular, we will not make -backward-incompatible changes to released APIs without also shipping a tool or -process that can upgrade our users' code. We are not yet at the point of easily -releasing such tools. Therefore, at this time, shipping a library establishes an -API contract which is borderline unchangeable. (We can add new functionality, -but we cannot easily change existing behavior.) This constraint forces us to -very carefully review all APIs that we ship. - - -## Coding Style - -To keep the source consistent, readable, diffable and easy to merge, we use a -fairly rigid coding style, as defined by the -[google-styleguide](https://github.com/google/styleguide) project. All patches -will be expected to conform to the style outlined -[here](https://google.github.io/styleguide/cppguide.html). - -## Guidelines for Pull Requests - -* If you are a Googler, it is preferable to first create an internal CL and - have it reviewed and submitted. The code propagation process will deliver - the change to GitHub. - -* Create **small PRs** that are narrowly focused on **addressing a single - concern**. We often receive PRs that are trying to fix several things at a - time, but if only one fix is considered acceptable, nothing gets merged and - both author's & review's time is wasted. Create more PRs to address - different concerns and everyone will be happy. - -* For speculative changes, consider opening an [Abseil - issue](https://github.com/abseil/abseil-cpp/issues) and discussing it first. - If you are suggesting a behavioral or API change, consider starting with an - [Abseil proposal template](ABSEIL_ISSUE_TEMPLATE.md). - -* Provide a good **PR description** as a record of **what** change is being - made and **why** it was made. Link to a GitHub issue if it exists. - -* Don't fix code style and formatting unless you are already changing that - line to address an issue. Formatting of modified lines may be done using - `git clang-format`. PRs with irrelevant changes won't be merged. If - you do want to fix formatting or style, do that in a separate PR. - -* Unless your PR is trivial, you should expect there will be reviewer comments - that you'll need to address before merging. We expect you to be reasonably - responsive to those comments, otherwise the PR will be closed after 2-3 - weeks of inactivity. - -* Maintain **clean commit history** and use **meaningful commit messages**. - PRs with messy commit history are difficult to review and won't be merged. - Use `rebase -i upstream/master` to curate your commit history and/or to - bring in latest changes from master (but avoid rebasing in the middle of a - code review). - -* Keep your PR up to date with upstream/master (if there are merge conflicts, - we can't really merge your change). - -* **All tests need to be passing** before your change can be merged. We - recommend you **run tests locally** (see below) - -* Exceptions to the rules can be made if there's a compelling reason for doing - so. That is - the rules are here to serve us, not the other way around, and - the rules need to be serving their intended purpose to be valuable. - -* All submissions, including submissions by project members, require review. - -## Running Tests - -If you have [Bazel](https://bazel.build/) installed, use `bazel test ---test_tag_filters="-benchmark" ...` to run the unit tests. - -If you are running the Linux operating system and have -[Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh` -scripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci) -directory to test Abseil under a variety of conditions. - -## Abseil Committers - -The current members of the Abseil engineering team are the only committers at -present. - -## Release Process - -Abseil lives at head, where latest-and-greatest code can be found. diff --git a/third_party/abseil_cpp/FAQ.md b/third_party/abseil_cpp/FAQ.md deleted file mode 100644 index 78028fc09f1f..000000000000 --- a/third_party/abseil_cpp/FAQ.md +++ /dev/null @@ -1,164 +0,0 @@ -# Abseil FAQ - -## Is Abseil the right home for my utility library? - -Most often the answer to the question is "no." As both the [About -Abseil](https://abseil.io/about/) page and our [contributing -guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines) -explain, Abseil contains a variety of core C++ library code that is widely used -at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be -used as a dependency by Google's open source C++ projects. While we do hope that -Abseil is also useful to the C++ community at large, this added constraint also -means that we are unlikely to accept a contribution of utility code that isn't -already widely used by Google. - -## How to I set the C++ dialect used to build Abseil? - -The short answer is that whatever mechanism you choose, you need to make sure -that you set this option consistently at the global level for your entire -project. If, for example, you want to set the C++ dialect to C++17, with -[Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the -compiler, there several ways to do this: -* Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build - --cxxopt=-std=c++17 ...`) -* Set the environment variable `BAZEL_CXXOPTS` (for example, - `BAZEL_CXXOPTS=-std=c++17`) -* Add `build --cxxopt=-std=c++17` to your [`.bazelrc` - file](https://docs.bazel.build/versions/master/guide.html#bazelrc) - -If you are using CMake as the build system, you'll need to add a line like -`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the -[CMake build -instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md) -for more information. - -For a longer answer to this question and to understand why some other approaches -don't work, see the answer to ["What is ABI and why don't you recommend using a -pre-compiled version of -Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil) - -## What is ABI and why don't you recommend using a pre-compiled version of Abseil? - -For the purposes of this discussion, you can think of -[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the -compiled representation of the interfaces in code. This is in contrast to -[API](https://en.wikipedia.org/wiki/Application_programming_interface), which -you can think of as the interfaces as defined by the code itself. [Abseil has a -strong promise of API compatibility, but does not make any promise of ABI -compatibility](https://abseil.io/about/compatibility). Let's take a look at what -this means in practice. - -You might be tempted to do something like this in a -[Bazel](https://bazel.build/) `BUILD` file: - -``` -# DON'T DO THIS!!! -cc_library( - name = "my_library", - srcs = ["my_library.cc"], - copts = ["-std=c++17"], # May create a mixed-mode compile! - deps = ["@com_google_absl//absl/strings"], -) -``` - -Applying `-std=c++17` to an individual target in your `BUILD` file is going to -compile that specific target in C++17 mode, but it isn't going to ensure the -Abseil library is built in C++17 mode, since the Abseil library itself is a -different build target. If your code includes an Abseil header, then your -program may contain conflicting definitions of the same -class/function/variable/enum, etc. As a rule, all compile options that affect -the ABI of a program need to be applied to the entire build on a global basis. - -C++ has something called the [One Definition -Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't -allow multiple definitions of the same class/function/variable/enum, etc. ODR -violations sometimes result in linker errors, but linkers do not always catch -violations. Uncaught ODR violations can result in strange runtime behaviors or -crashes that can be hard to debug. - -If you build the Abseil library and your code using different compile options -that affect ABI, there is a good chance you will run afoul of the One Definition -Rule. Examples of GCC compile options that affect ABI include (but aren't -limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`), -code generation flags (e.g. `-fexceptions`), and preprocessor defines -(e.g. `-DNDEBUG`). - -If you use a pre-compiled version of Abseil, (for example, from your Linux -distribution package manager or from something like -[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to -ensure ABI compatibility across the components of your program. The only way you -can be sure your program is going to be correct regarding ABI is to ensure -you've used the exact same compile options as were used to build the -pre-compiled library. This does not mean that Abseil cannot work as part of a -Linux distribution since a knowledgeable binary packager will have ensured that -all packages have been built with consistent compile options. This is one of the -reasons we warn against - though do not outright reject - using Abseil as a -pre-compiled library. - -Another possible way that you might afoul of ABI issues is if you accidentally -include two versions of Abseil in your program. Multiple versions of Abseil can -end up within the same binary if your program uses the Abseil library and -another library also transitively depends on Abseil (resulting in what is -sometimes called the diamond dependency problem). In cases such as this you must -structure your build so that all libraries use the same version of Abseil. -[Abseil's strong promise of API compatibility between -releases](https://abseil.io/about/compatibility) means the latest "HEAD" release -of Abseil is almost certainly the right choice if you are doing as we recommend -and building all of your code from source. - -For these reasons we recommend you avoid pre-compiled code and build the Abseil -library yourself in a consistent manner with the rest of your code. - -## What is "live at head" and how do I do it? - -From Abseil's point-of-view, "live at head" means that every Abseil source -release (which happens on an almost daily basis) is either API compatible with -the previous release, or comes with an automated tool that you can run over code -to make it compatible. In practice, the need to use an automated tool is -extremely rare. This means that upgrading from one source release to another -should be a routine practice that can and should be performed often. - -We recommend you update to the [latest commit in the `master` branch of -Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as -possible. Not only will you pick up bug fixes more quickly, but if you have good -automated testing, you will catch and be able to fix any [Hyrum's -Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis -instead of being overwhelmed by them and having difficulty isolating them if you -wait longer between updates. - -If you are using the [Bazel](https://bazel.build/) build system and its -[external dependencies](https://docs.bazel.build/versions/master/external.html) -feature, updating the -[`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive) -rule in your -[`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for -`com_google_abseil` to point to the [latest commit in the `master` branch of -Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to -do. For example, on February 11, 2020, the latest commit to the master branch -was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you -would add the following snippet to your `WORKSPACE` file: - -``` -http_archive( - name = "com_google_absl", - urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"], # 2020-02-11T18:50:53Z - strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea", - sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87", -) -``` - -To get the `sha256` of this URL, run `curl -sL --output - -https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip -| sha256sum -`. - -You can commit the updated `WORKSPACE` file to your source control every time -you update, and if you have good automated testing, you might even consider -automating this. - -One thing we don't recommend is using GitHub's `master.zip` files (for example -[https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)), -which are always the latest commit in the `master` branch, to implement live at -head. Since these `master.zip` URLs are not versioned, you will lose build -reproducibility. In addition, some build systems, including Bazel, will simply -cache this file, which means you won't actually be updating to the latest -release until your cache is cleared or invalidated. diff --git a/third_party/abseil_cpp/LICENSE b/third_party/abseil_cpp/LICENSE deleted file mode 100644 index ccd61dcfe3db..000000000000 --- a/third_party/abseil_cpp/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/third_party/abseil_cpp/LTS.md b/third_party/abseil_cpp/LTS.md deleted file mode 100644 index ade8b17c7367..000000000000 --- a/third_party/abseil_cpp/LTS.md +++ /dev/null @@ -1,16 +0,0 @@ -# Long Term Support (LTS) Branches - -This repository contains periodic snapshots of the Abseil codebase that are -Long Term Support (LTS) branches. An LTS branch allows you to use a known -version of Abseil without interfering with other projects which may also, in -turn, use Abseil. (For more information about our releases, see the -[Abseil Release Management](https://abseil.io/about/releases) guide.) - -## LTS Branches - -The following lists LTS branches and the dates on which they have been released: - -* [LTS Branch 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/) -* [LTS Branch February 25, 2020](https://github.com/abseil/abseil-cpp/tree/lts_2020_02_25/) diff --git a/third_party/abseil_cpp/README.md b/third_party/abseil_cpp/README.md deleted file mode 100644 index 85de569658c6..000000000000 --- a/third_party/abseil_cpp/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# Abseil - C++ Common Libraries - -The repository contains the Abseil C++ library code. Abseil is an open-source -collection of C++ code (compliant to C++11) designed to augment the C++ -standard library. - -## Table of Contents - -- [About Abseil](#about) -- [Quickstart](#quickstart) -- [Building Abseil](#build) -- [Codemap](#codemap) -- [License](#license) -- [Links](#links) - -<a name="about"></a> -## About Abseil - -Abseil is an open-source collection of C++ library code designed to augment -the C++ standard library. The Abseil library code is collected from Google's -own C++ code base, has been extensively tested and used in production, and -is the same code we depend on in our daily coding lives. - -In some cases, Abseil provides pieces missing from the C++ standard; in -others, Abseil provides alternatives to the standard for special needs -we've found through usage in the Google code base. We denote those cases -clearly within the library code we provide you. - -Abseil is not meant to be a competitor to the standard library; we've -just found that many of these utilities serve a purpose within our code -base, and we now want to provide those resources to the C++ community as -a whole. - -<a name="quickstart"></a> -## Quickstart - -If you want to just get started, make sure you at least run through the -[Abseil Quickstart](https://abseil.io/docs/cpp/quickstart). The Quickstart -contains information about setting up your development environment, downloading -the Abseil code, running tests, and getting a simple binary working. - -<a name="build"></a> -## Building 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. - -<a name="cmake"></a> -If you require CMake support, please check the -[CMake build instructions](CMake/README.md). - -## Codemap - -Abseil contains the following C++ library components: - -* [`base`](absl/base/) Abseil Fundamentals - <br /> The `base` library contains initialization code and other code which - all other Abseil code depends on. Code within `base` may not depend on any - other code (other than the C++ standard library). -* [`algorithm`](absl/algorithm/) - <br /> The `algorithm` library contains additions to the C++ `<algorithm>` - library and container-based versions of such algorithms. -* [`container`](absl/container/) - <br /> The `container` library contains additional STL-style containers, - including Abseil's unordered "Swiss table" containers. -* [`debugging`](absl/debugging/) - <br /> The `debugging` library contains code useful for enabling leak - checks, and stacktrace and symbolization utilities. -* [`hash`](absl/hash/) - <br /> The `hash` library contains the hashing framework and default hash - functor implementations for hashable types in Abseil. -* [`memory`](absl/memory/) - <br /> The `memory` library contains C++11-compatible versions of - `std::make_unique()` and related memory management facilities. -* [`meta`](absl/meta/) - <br /> The `meta` library contains C++11-compatible versions of type checks - 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. -* [`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 - `std::string_view` type. -* [`synchronization`](absl/synchronization/) - <br /> The `synchronization` library contains concurrency primitives (Abseil's - `absl::Mutex` class, an alternative to `std::mutex`) and a variety of - synchronization abstractions. -* [`time`](absl/time/) - <br /> The `time` library contains abstractions for computing with absolute - points in time, durations of time, and formatting and parsing time within - time zones. -* [`types`](absl/types/) - <br /> The `types` library contains non-container utility types, like a - C++11-compatible version of the C++17 `std::optional` type. -* [`utility`](absl/utility/) - <br /> The `utility` library contains utility and helper code. - -## License - -The Abseil C++ library is licensed under the terms of the Apache -license. See [LICENSE](LICENSE) for more information. - -## Links - -For more information about Abseil: - -* Consult our [Abseil Introduction](https://abseil.io/about/intro) -* Read [Why Adopt Abseil](https://abseil.io/about/philosophy) to understand our - design philosophy. -* Peruse our - [Abseil Compatibility Guarantees](https://abseil.io/about/compatibility) to - understand both what we promise to you, and what we expect of you in return. diff --git a/third_party/abseil_cpp/UPGRADES.md b/third_party/abseil_cpp/UPGRADES.md deleted file mode 100644 index 35599d0878d1..000000000000 --- a/third_party/abseil_cpp/UPGRADES.md +++ /dev/null @@ -1,17 +0,0 @@ -# C++ Upgrade Tools - -Abseil may occassionally release API-breaking changes. As noted in our -[Compatibility Guidelines][compatibility-guide], we will aim to provide a tool -to do the work of effecting such API-breaking changes, when absolutely -necessary. - -These tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on -https://abseil.io. - -For more information, the [C++ Automated Upgrade Guide][api-upgrades-guide] -outlines this process. - -[compatibility-guide]: https://abseil.io/about/compatibility -[api-upgrades-guide]: https://abseil.io/docs/cpp/tools/api-upgrades -[upgrade-tools]: https://abseil.io/docs/cpp/tools/upgrades/ - diff --git a/third_party/abseil_cpp/WORKSPACE b/third_party/abseil_cpp/WORKSPACE deleted file mode 100644 index ed90d2ba9587..000000000000 --- a/third_party/abseil_cpp/WORKSPACE +++ /dev/null @@ -1,45 +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. -# - -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", - # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh. - urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"], # 2020-06-12T22:24:28Z - strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b", - sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48", -) - -# Google benchmark. -http_archive( - name = "com_github_google_benchmark", - urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"], - strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be", - sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3", -) - -# C++ rules for Bazel. -http_archive( - name = "rules_cc", - sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d", - strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa", - urls = [ - "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip", - ], -) diff --git a/third_party/abseil_cpp/absl/BUILD.bazel b/third_party/abseil_cpp/absl/BUILD.bazel deleted file mode 100644 index 6da20c49d28d..000000000000 --- a/third_party/abseil_cpp/absl/BUILD.bazel +++ /dev/null @@ -1,65 +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. - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -config_setting( - name = "clang_compiler", - flag_values = { - "@bazel_tools//tools/cpp:compiler": "clang", - }, - visibility = [":__subpackages__"], -) - -config_setting( - name = "osx", - constraint_values = [ - "@bazel_tools//platforms:osx", - ], -) - -config_setting( - name = "ios", - constraint_values = [ - "@bazel_tools//platforms:ios", - ], -) - -config_setting( - name = "windows", - constraint_values = [ - "@bazel_tools//platforms:x86_64", - "@bazel_tools//platforms:windows", - ], - visibility = [":__subpackages__"], -) - -config_setting( - name = "ppc", - values = { - "cpu": "ppc", - }, - visibility = [":__subpackages__"], -) - -config_setting( - name = "wasm", - values = { - "cpu": "wasm32", - }, - visibility = [":__subpackages__"], -) diff --git a/third_party/abseil_cpp/absl/CMakeLists.txt b/third_party/abseil_cpp/absl/CMakeLists.txt deleted file mode 100644 index fbfa7822b594..000000000000 --- a/third_party/abseil_cpp/absl/CMakeLists.txt +++ /dev/null @@ -1,37 +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. -# - -add_subdirectory(base) -add_subdirectory(algorithm) -add_subdirectory(container) -add_subdirectory(debugging) -add_subdirectory(flags) -add_subdirectory(functional) -add_subdirectory(hash) -add_subdirectory(memory) -add_subdirectory(meta) -add_subdirectory(numeric) -add_subdirectory(random) -add_subdirectory(status) -add_subdirectory(strings) -add_subdirectory(synchronization) -add_subdirectory(time) -add_subdirectory(types) -add_subdirectory(utility) - -if (${ABSL_BUILD_DLL}) - absl_make_dll() -endif() diff --git a/third_party/abseil_cpp/absl/abseil.podspec.gen.py b/third_party/abseil_cpp/absl/abseil.podspec.gen.py deleted file mode 100755 index 63752980d09b..000000000000 --- a/third_party/abseil_cpp/absl/abseil.podspec.gen.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -"""This script generates abseil.podspec from all BUILD.bazel files. - -This is expected to run on abseil git repository with Bazel 1.0 on Linux. -It recursively analyzes BUILD.bazel files using query command of Bazel to -dump its build rules in XML format. From these rules, it constructs podspec -structure. -""" - -import argparse -import collections -import os -import re -import subprocess -import xml.etree.ElementTree - -# Template of root podspec. -SPEC_TEMPLATE = """ -# This file has been automatically generated from a script. -# Please make modifications to `abseil.podspec.gen.py` instead. -Pod::Spec.new do |s| - s.name = 'abseil' - s.version = '${version}' - s.summary = 'Abseil Common Libraries (C++) from Google' - s.homepage = 'https://abseil.io' - s.license = 'Apache License, Version 2.0' - s.authors = { 'Abseil Team' => 'abseil-io@googlegroups.com' } - s.source = { - :git => 'https://github.com/abseil/abseil-cpp.git', - :tag => '${tag}', - } - s.module_name = 'absl' - s.header_mappings_dir = 'absl' - s.header_dir = 'absl' - s.libraries = 'c++' - s.compiler_flags = '-Wno-everything' - s.pod_target_xcconfig = { - 'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"', - 'USE_HEADERMAP' => 'NO', - 'ALWAYS_SEARCH_USER_PATHS' => 'NO', - } - s.ios.deployment_target = '9.0' - s.osx.deployment_target = '10.10' - s.tvos.deployment_target = '9.0' - s.watchos.deployment_target = '2.0' -""" - -# Rule object representing the rule of Bazel BUILD. -Rule = collections.namedtuple( - "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly") - - -def get_elem_value(elem, name): - """Returns the value of XML element with the given name.""" - for child in elem: - if child.attrib.get("name") != name: - continue - if child.tag == "string": - return child.attrib.get("value") - if child.tag == "boolean": - return child.attrib.get("value") == "true" - if child.tag == "list": - return [nested_child.attrib.get("value") for nested_child in child] - raise "Cannot recognize tag: " + child.tag - return None - - -def normalize_paths(paths): - """Returns the list of normalized path.""" - # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"] - return [path.lstrip("/").replace(":", "/") for path in paths] - - -def parse_rule(elem, package): - """Returns a rule from bazel XML rule.""" - return Rule( - type=elem.attrib["class"], - name=get_elem_value(elem, "name"), - package=package, - srcs=normalize_paths(get_elem_value(elem, "srcs") or []), - hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []), - textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []), - deps=get_elem_value(elem, "deps") or [], - visibility=get_elem_value(elem, "visibility") or [], - testonly=get_elem_value(elem, "testonly") or False) - - -def read_build(package): - """Runs bazel query on given package file and returns all cc rules.""" - result = subprocess.check_output( - ["bazel", "query", package + ":all", "--output", "xml"]) - root = xml.etree.ElementTree.fromstring(result) - return [ - parse_rule(elem, package) - for elem in root - if elem.tag == "rule" and elem.attrib["class"].startswith("cc_") - ] - - -def collect_rules(root_path): - """Collects and returns all rules from root path recursively.""" - rules = [] - for cur, _, _ in os.walk(root_path): - build_path = os.path.join(cur, "BUILD.bazel") - if os.path.exists(build_path): - rules.extend(read_build("//" + cur)) - return rules - - -def relevant_rule(rule): - """Returns true if a given rule is relevant when generating a podspec.""" - return ( - # cc_library only (ignore cc_test, cc_binary) - rule.type == "cc_library" and - # ignore empty rule - (rule.hdrs + rule.textual_hdrs + rule.srcs) and - # ignore test-only rule - not rule.testonly) - - -def get_spec_var(depth): - """Returns the name of variable for spec with given depth.""" - return "s" if depth == 0 else "s{}".format(depth) - - -def get_spec_name(label): - """Converts the label of bazel rule to the name of podspec.""" - assert label.startswith("//absl/"), "{} doesn't start with //absl/".format( - label) - # e.g. //absl/apple/banana -> abseil/apple/banana - return "abseil/" + label[7:] - - -def write_podspec(f, rules, args): - """Writes a podspec from given rules and args.""" - rule_dir = build_rule_directory(rules)["abseil"] - # Write root part with given arguments - spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)], - SPEC_TEMPLATE).lstrip() - f.write(spec) - # Write all target rules - write_podspec_map(f, rule_dir, 0) - f.write("end\n") - - -def build_rule_directory(rules): - """Builds a tree-style rule directory from given rules.""" - rule_dir = {} - for rule in rules: - cur = rule_dir - for frag in get_spec_name(rule.package).split("/"): - cur = cur.setdefault(frag, {}) - cur[rule.name] = rule - return rule_dir - - -def write_podspec_map(f, cur_map, depth): - """Writes podspec from rule map recursively.""" - for key, value in sorted(cur_map.items()): - indent = " " * (depth + 1) - f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format( - indent=indent, - key=key, - var0=get_spec_var(depth), - var1=get_spec_var(depth + 1))) - if isinstance(value, dict): - write_podspec_map(f, value, depth + 1) - else: - write_podspec_rule(f, value, depth + 1) - f.write("{indent}end\n".format(indent=indent)) - - -def write_podspec_rule(f, rule, depth): - """Writes podspec from given rule.""" - indent = " " * (depth + 1) - spec_var = get_spec_var(depth) - # Puts all files in hdrs, textual_hdrs, and srcs into source_files. - # Since CocoaPods treats header_files a bit differently from bazel, - # this won't generate a header_files field so that all source_files - # are considered as header files. - srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs)) - write_indented_list( - f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var), - srcs) - # Writes dependencies of this rule. - for dep in sorted(rule.deps): - name = get_spec_name(dep.replace(":", "/")) - f.write("{indent}{var}.dependency '{dep}'\n".format( - indent=indent, var=spec_var, dep=name)) - - -def write_indented_list(f, leading, values): - """Writes leading values in an indented style.""" - f.write(leading) - f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values)) - f.write("\n") - - -def generate(args): - """Generates a podspec file from all BUILD files under absl directory.""" - rules = filter(relevant_rule, collect_rules("absl")) - with open(args.output, "wt") as f: - write_podspec(f, rules, vars(args)) - - -def main(): - parser = argparse.ArgumentParser( - description="Generates abseil.podspec from BUILD.bazel") - parser.add_argument( - "-v", "--version", help="The version of podspec", required=True) - parser.add_argument( - "-t", - "--tag", - default=None, - help="The name of git tag (default: version)") - parser.add_argument( - "-o", - "--output", - default="abseil.podspec", - help="The name of output file (default: abseil.podspec)") - args = parser.parse_args() - if args.tag is None: - args.tag = args.version - generate(args) - - -if __name__ == "__main__": - main() diff --git a/third_party/abseil_cpp/absl/algorithm/BUILD.bazel b/third_party/abseil_cpp/absl/algorithm/BUILD.bazel deleted file mode 100644 index a3002b7dcd5f..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/BUILD.bazel +++ /dev/null @@ -1,91 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "algorithm", - hdrs = ["algorithm.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - ], -) - -cc_test( - name = "algorithm_test", - size = "small", - srcs = ["algorithm_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":algorithm", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "algorithm_benchmark", - srcs = ["equal_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":algorithm", - "//absl/base:core_headers", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "container", - hdrs = [ - "container.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":algorithm", - "//absl/base:core_headers", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "container_test", - srcs = ["container_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":container", - "//absl/base", - "//absl/base:core_headers", - "//absl/memory", - "//absl/types:span", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/algorithm/CMakeLists.txt b/third_party/abseil_cpp/absl/algorithm/CMakeLists.txt deleted file mode 100644 index 56cd0fb85b50..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/CMakeLists.txt +++ /dev/null @@ -1,69 +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. -# - -absl_cc_library( - NAME - algorithm - HDRS - "algorithm.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_test( - NAME - algorithm_test - SRCS - "algorithm_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::algorithm - gmock_main -) - -absl_cc_library( - NAME - algorithm_container - HDRS - "container.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::core_headers - absl::meta - PUBLIC -) - -absl_cc_test( - NAME - container_test - SRCS - "container_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::algorithm_container - absl::base - absl::core_headers - absl::memory - absl::span - gmock_main -) diff --git a/third_party/abseil_cpp/absl/algorithm/algorithm.h b/third_party/abseil_cpp/absl/algorithm/algorithm.h deleted file mode 100644 index e9b473387278..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/algorithm.h +++ /dev/null @@ -1,159 +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. -// -// ----------------------------------------------------------------------------- -// File: algorithm.h -// ----------------------------------------------------------------------------- -// -// This header file contains Google extensions to the standard <algorithm> C++ -// header. - -#ifndef ABSL_ALGORITHM_ALGORITHM_H_ -#define ABSL_ALGORITHM_ALGORITHM_H_ - -#include <algorithm> -#include <iterator> -#include <type_traits> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace algorithm_internal { - -// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`. -struct EqualTo { - template <typename T, typename U> - bool operator()(const T& a, const U& b) const { - return a == b; - } -}; - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred pred, std::input_iterator_tag, - std::input_iterator_tag) { - while (true) { - if (first1 == last1) return first2 == last2; - if (first2 == last2) return false; - if (!pred(*first1, *first2)) return false; - ++first1; - ++first2; - } -} - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred, std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2, std::forward<Pred>(pred)); -} - -// When we are using our own internal predicate that just applies operator==, we -// forward to the non-predicate form of std::equal. This enables an optimization -// in libstdc++ that can result in std::memcmp being used for integer types. -template <typename InputIter1, typename InputIter2> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, algorithm_internal::EqualTo /* unused */, - std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::true_type) { - return std::rotate(first, middle, last); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::false_type) { - std::rotate(first, middle, last); - return std::next(first, std::distance(middle, last)); -} - -} // namespace algorithm_internal - -// equal() -// -// Compares the equality of two ranges specified by pairs of iterators, using -// the given predicate, returning true iff for each corresponding iterator i1 -// and i2 in the first and second range respectively, pred(*i1, *i2) == true -// -// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`) -// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are -// both random-access iterators, and `last1` - `first1` != `last2` - `first2`, -// then the predicate is never invoked and the function returns false. -// -// This is a C++11-compatible implementation of C++14 `std::equal`. See -// https://en.cppreference.com/w/cpp/algorithm/equal for more information. -template <typename InputIter1, typename InputIter2, typename Pred> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred) { - return algorithm_internal::EqualImpl( - first1, last1, first2, last2, std::forward<Pred>(pred), - typename std::iterator_traits<InputIter1>::iterator_category{}, - typename std::iterator_traits<InputIter2>::iterator_category{}); -} - -// Overload of equal() that performs comparison of two ranges specified by pairs -// of iterators using operator==. -template <typename InputIter1, typename InputIter2> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2) { - return absl::equal(first1, last1, first2, last2, - algorithm_internal::EqualTo{}); -} - -// linear_search() -// -// Performs a linear search for `value` using the iterator `first` up to -// but not including `last`, returning true if [`first`, `last`) contains an -// element equal to `value`. -// -// A linear search is of O(n) complexity which is guaranteed to make at most -// n = (`last` - `first`) comparisons. A linear search over short containers -// may be faster than a binary search, even when the container is sorted. -template <typename InputIterator, typename EqualityComparable> -bool linear_search(InputIterator first, InputIterator last, - const EqualityComparable& value) { - return std::find(first, last, value) != last; -} - -// rotate() -// -// Performs a left rotation on a range of elements (`first`, `last`) such that -// `middle` is now the first element. `rotate()` returns an iterator pointing to -// the first element before rotation. This function is exactly the same as -// `std::rotate`, but fixes a bug in gcc -// <= 4.9 where `std::rotate` returns `void` instead of an iterator. -// -// The complexity of this algorithm is the same as that of `std::rotate`, but if -// `ForwardIterator` is not a random-access iterator, then `absl::rotate` -// performs an additional pass over the range to construct the return value. -template <typename ForwardIterator> -ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last) { - return algorithm_internal::RotateImpl( - first, middle, last, - std::is_same<decltype(std::rotate(first, middle, last)), - ForwardIterator>()); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_ALGORITHM_ALGORITHM_H_ diff --git a/third_party/abseil_cpp/absl/algorithm/algorithm_test.cc b/third_party/abseil_cpp/absl/algorithm/algorithm_test.cc deleted file mode 100644 index 81fccb61353e..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/algorithm_test.cc +++ /dev/null @@ -1,182 +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/algorithm/algorithm.h" - -#include <algorithm> -#include <list> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace { - -TEST(EqualTest, DefaultComparisonRandomAccess) { - std::vector<int> v1{1, 2, 3}; - std::vector<int> v2 = v1; - std::vector<int> v3 = {1, 2}; - std::vector<int> v4 = {1, 2, 4}; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end())); -} - -TEST(EqualTest, DefaultComparison) { - std::list<int> lst1{1, 2, 3}; - std::list<int> lst2 = lst1; - std::list<int> lst3{1, 2}; - std::list<int> lst4{1, 2, 4}; - - EXPECT_TRUE(absl::equal(lst1.begin(), lst1.end(), lst2.begin(), lst2.end())); - EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst3.begin(), lst3.end())); - EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst4.begin(), lst4.end())); -} - -TEST(EqualTest, EmptyRange) { - std::vector<int> v1{1, 2, 3}; - std::vector<int> empty1; - std::vector<int> empty2; - - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), empty1.begin(), empty1.end())); - EXPECT_FALSE(absl::equal(empty1.begin(), empty1.end(), v1.begin(), v1.end())); - EXPECT_TRUE( - absl::equal(empty1.begin(), empty1.end(), empty2.begin(), empty2.end())); -} - -TEST(EqualTest, MixedIterTypes) { - std::vector<int> v1{1, 2, 3}; - std::list<int> lst1{v1.begin(), v1.end()}; - std::list<int> lst2{1, 2, 4}; - std::list<int> lst3{1, 2}; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), lst1.begin(), lst1.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst2.begin(), lst2.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst3.begin(), lst3.end())); -} - -TEST(EqualTest, MixedValueTypes) { - std::vector<int> v1{1, 2, 3}; - std::vector<char> v2{1, 2, 3}; - std::vector<char> v3{1, 2}; - std::vector<char> v4{1, 2, 4}; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end())); -} - -TEST(EqualTest, WeirdIterators) { - std::vector<bool> v1{true, false}; - std::vector<bool> v2 = v1; - std::vector<bool> v3{true}; - std::vector<bool> v4{true, true, true}; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end())); -} - -TEST(EqualTest, CustomComparison) { - int n[] = {1, 2, 3, 4}; - std::vector<int*> v1{&n[0], &n[1], &n[2]}; - std::vector<int*> v2 = v1; - std::vector<int*> v3{&n[0], &n[1], &n[3]}; - std::vector<int*> v4{&n[0], &n[1]}; - - auto eq = [](int* a, int* b) { return *a == *b; }; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), eq)); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(), eq)); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end(), eq)); -} - -TEST(EqualTest, MoveOnlyPredicate) { - std::vector<int> v1{1, 2, 3}; - std::vector<int> v2{4, 5, 6}; - - // move-only equality predicate - struct Eq { - Eq() = default; - Eq(Eq &&) = default; - Eq(const Eq &) = delete; - Eq &operator=(const Eq &) = delete; - bool operator()(const int a, const int b) const { return a == b; } - }; - - EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v1.begin(), v1.end(), Eq())); - EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), Eq())); -} - -struct CountingTrivialPred { - int* count; - bool operator()(int, int) const { - ++*count; - return true; - } -}; - -TEST(EqualTest, RandomAccessComplexity) { - std::vector<int> v1{1, 1, 3}; - std::vector<int> v2 = v1; - std::vector<int> v3{1, 2}; - - do { - int count = 0; - absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), - CountingTrivialPred{&count}); - EXPECT_LE(count, 3); - } while (std::next_permutation(v2.begin(), v2.end())); - - int count = 0; - absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(), - CountingTrivialPred{&count}); - EXPECT_EQ(count, 0); -} - -class LinearSearchTest : public testing::Test { - protected: - LinearSearchTest() : container_{1, 2, 3} {} - - static bool Is3(int n) { return n == 3; } - static bool Is4(int n) { return n == 4; } - - std::vector<int> container_; -}; - -TEST_F(LinearSearchTest, linear_search) { - EXPECT_TRUE(absl::linear_search(container_.begin(), container_.end(), 3)); - EXPECT_FALSE(absl::linear_search(container_.begin(), container_.end(), 4)); -} - -TEST_F(LinearSearchTest, linear_searchConst) { - const std::vector<int> *const const_container = &container_; - EXPECT_TRUE( - absl::linear_search(const_container->begin(), const_container->end(), 3)); - EXPECT_FALSE( - absl::linear_search(const_container->begin(), const_container->end(), 4)); -} - -TEST(RotateTest, Rotate) { - std::vector<int> v{0, 1, 2, 3, 4}; - EXPECT_EQ(*absl::rotate(v.begin(), v.begin() + 2, v.end()), 0); - EXPECT_THAT(v, testing::ElementsAreArray({2, 3, 4, 0, 1})); - - std::list<int> l{0, 1, 2, 3, 4}; - EXPECT_EQ(*absl::rotate(l.begin(), std::next(l.begin(), 3), l.end()), 0); - EXPECT_THAT(l, testing::ElementsAreArray({3, 4, 0, 1, 2})); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/algorithm/container.h b/third_party/abseil_cpp/absl/algorithm/container.h deleted file mode 100644 index 6398438f08ce..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/container.h +++ /dev/null @@ -1,1764 +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. -// -// ----------------------------------------------------------------------------- -// File: container.h -// ----------------------------------------------------------------------------- -// -// This header file provides Container-based versions of algorithmic functions -// within the C++ standard library. The following standard library sets of -// functions are covered within this file: -// -// * Algorithmic <iterator> functions -// * Algorithmic <numeric> functions -// * <algorithm> functions -// -// The standard library functions operate on iterator ranges; the functions -// within this API operate on containers, though many return iterator ranges. -// -// All functions within this API are named with a `c_` prefix. Calls such as -// `absl::c_xx(container, ...) are equivalent to std:: functions such as -// `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on -// iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`) -// have no equivalent here. -// -// For template parameter and variable naming, `C` indicates the container type -// to which the function is applied, `Pred` indicates the predicate object type -// to be used by the function and `T` indicates the applicable element type. - -#ifndef ABSL_ALGORITHM_CONTAINER_H_ -#define ABSL_ALGORITHM_CONTAINER_H_ - -#include <algorithm> -#include <cassert> -#include <iterator> -#include <numeric> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <utility> -#include <vector> - -#include "absl/algorithm/algorithm.h" -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_algorithm_internal { - -// NOTE: it is important to defer to ADL lookup for building with C++ modules, -// especially for headers like <valarray> which are not visible from this file -// but specialize std::begin and std::end. -using std::begin; -using std::end; - -// The type of the iterator given by begin(c) (possibly std::begin(c)). -// ContainerIter<const vector<T>> gives vector<T>::const_iterator, -// while ContainerIter<vector<T>> gives vector<T>::iterator. -template <typename C> -using ContainerIter = decltype(begin(std::declval<C&>())); - -// An MSVC bug involving template parameter substitution requires us to use -// decltype() here instead of just std::pair. -template <typename C1, typename C2> -using ContainerIterPairType = - decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>())); - -template <typename C> -using ContainerDifferenceType = - decltype(std::distance(std::declval<ContainerIter<C>>(), - std::declval<ContainerIter<C>>())); - -template <typename C> -using ContainerPointerType = - typename std::iterator_traits<ContainerIter<C>>::pointer; - -// container_algorithm_internal::c_begin and -// container_algorithm_internal::c_end are abbreviations for proper ADL -// lookup of std::begin and std::end, i.e. -// using std::begin; -// using std::end; -// std::foo(begin(c), end(c)); -// becomes -// std::foo(container_algorithm_internal::begin(c), -// container_algorithm_internal::end(c)); -// These are meant for internal use only. - -template <typename C> -ContainerIter<C> c_begin(C& c) { return begin(c); } - -template <typename C> -ContainerIter<C> c_end(C& c) { return end(c); } - -template <typename T> -struct IsUnorderedContainer : std::false_type {}; - -template <class Key, class T, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer< - std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {}; - -template <class Key, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>> - : std::true_type {}; - -// container_algorithm_internal::c_size. It is meant for internal use only. - -template <class C> -auto c_size(C& c) -> decltype(c.size()) { - return c.size(); -} - -template <class T, std::size_t N> -constexpr std::size_t c_size(T (&)[N]) { - return N; -} - -} // namespace container_algorithm_internal - -// PUBLIC API - -//------------------------------------------------------------------------------ -// Abseil algorithm.h functions -//------------------------------------------------------------------------------ - -// c_linear_search() -// -// Container-based version of absl::linear_search() for performing a linear -// search within a container. -template <typename C, typename EqualityComparable> -bool c_linear_search(const C& c, EqualityComparable&& value) { - return linear_search(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<EqualityComparable>(value)); -} - -//------------------------------------------------------------------------------ -// <iterator> algorithms -//------------------------------------------------------------------------------ - -// c_distance() -// -// Container-based version of the <iterator> `std::distance()` function to -// return the number of elements within a container. -template <typename C> -container_algorithm_internal::ContainerDifferenceType<const C> c_distance( - const C& c) { - return std::distance(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Non-modifying sequence operations -//------------------------------------------------------------------------------ - -// c_all_of() -// -// Container-based version of the <algorithm> `std::all_of()` function to -// test a condition on all elements within a container. -template <typename C, typename Pred> -bool c_all_of(const C& c, Pred&& pred) { - return std::all_of(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_any_of() -// -// Container-based version of the <algorithm> `std::any_of()` function to -// test if any element in a container fulfills a condition. -template <typename C, typename Pred> -bool c_any_of(const C& c, Pred&& pred) { - return std::any_of(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<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. -template <typename C, typename Pred> -bool c_none_of(const C& c, Pred&& pred) { - return std::none_of(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_for_each() -// -// Container-based version of the <algorithm> `std::for_each()` function to -// apply a function to a container's elements. -template <typename C, typename Function> -decay_t<Function> c_for_each(C&& c, Function&& f) { - return std::for_each(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Function>(f)); -} - -// c_find() -// -// Container-based version of the <algorithm> `std::find()` function to find -// the first element containing the passed value within a container value. -template <typename C, typename T> -container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) { - return std::find(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<T>(value)); -} - -// c_find_if() -// -// Container-based version of the <algorithm> `std::find_if()` function to find -// the first element in a container matching the given condition. -template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) { - return std::find_if(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_find_if_not() -// -// Container-based version of the <algorithm> `std::find_if_not()` function to -// find the first element in a container not matching the given condition. -template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c, - Pred&& pred) { - return std::find_if_not(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_find_end() -// -// Container-based version of the <algorithm> `std::find_end()` function to -// find the last subsequence within a container. -template <typename Sequence1, typename Sequence2> -container_algorithm_internal::ContainerIter<Sequence1> c_find_end( - Sequence1& sequence, Sequence2& subsequence) { - return std::find_end(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - container_algorithm_internal::c_begin(subsequence), - container_algorithm_internal::c_end(subsequence)); -} - -// Overload of c_find_end() for using a predicate evaluation other than `==` as -// the function's test condition. -template <typename Sequence1, typename Sequence2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence1> c_find_end( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { - return std::find_end(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - container_algorithm_internal::c_begin(subsequence), - container_algorithm_internal::c_end(subsequence), - std::forward<BinaryPredicate>(pred)); -} - -// c_find_first_of() -// -// Container-based version of the <algorithm> `std::find_first_of()` function to -// find the first element within the container that is also within the options -// container. -template <typename C1, typename C2> -container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container, - C2& options) { - return std::find_first_of(container_algorithm_internal::c_begin(container), - container_algorithm_internal::c_end(container), - container_algorithm_internal::c_begin(options), - container_algorithm_internal::c_end(options)); -} - -// Overload of c_find_first_of() for using a predicate evaluation other than -// `==` as the function's test condition. -template <typename C1, typename C2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<C1> c_find_first_of( - C1& container, C2& options, BinaryPredicate&& pred) { - return std::find_first_of(container_algorithm_internal::c_begin(container), - container_algorithm_internal::c_end(container), - container_algorithm_internal::c_begin(options), - container_algorithm_internal::c_end(options), - std::forward<BinaryPredicate>(pred)); -} - -// c_adjacent_find() -// -// Container-based version of the <algorithm> `std::adjacent_find()` function to -// find equal adjacent elements within a container. -template <typename Sequence> -container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( - Sequence& sequence) { - return std::adjacent_find(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_adjacent_find() for using a predicate evaluation other than -// `==` as the function's test condition. -template <typename Sequence, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( - Sequence& sequence, BinaryPredicate&& pred) { - return std::adjacent_find(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<BinaryPredicate>(pred)); -} - -// c_count() -// -// Container-based version of the <algorithm> `std::count()` function to count -// values that match within a container. -template <typename C, typename T> -container_algorithm_internal::ContainerDifferenceType<const C> c_count( - const C& c, T&& value) { - return std::count(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<T>(value)); -} - -// c_count_if() -// -// Container-based version of the <algorithm> `std::count_if()` function to -// count values matching a condition within a container. -template <typename C, typename Pred> -container_algorithm_internal::ContainerDifferenceType<const C> c_count_if( - const C& c, Pred&& pred) { - return std::count_if(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// 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)). -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); -} - -// 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)). -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_equal() -// -// Container-based version of the <algorithm> `std::equal()` function to -// test whether two containers are equal. -// -// NOTE: the semantics of c_equal() are slightly different than those of -// equal(): while the latter iterates over the second container only up to the -// size of the first container, c_equal() also checks whether the container -// sizes are equal. This better matches expectations about c_equal() based on -// its signature. -// -// Example: -// vector v1 = <1, 2, 3>; -// vector v2 = <1, 2, 3, 4>; -// equal(std::begin(v1), std::end(v1), std::begin(v2)) returns true -// c_equal(v1, v2) returns false - -template <typename C1, typename C2> -bool c_equal(const C1& c1, const C2& c2) { - return ((container_algorithm_internal::c_size(c1) == - container_algorithm_internal::c_size(c2)) && - std::equal(container_algorithm_internal::c_begin(c1), - container_algorithm_internal::c_end(c1), - container_algorithm_internal::c_begin(c2))); -} - -// Overload of c_equal() for using a predicate evaluation other than `==` as -// the function's test condition. -template <typename C1, typename C2, typename BinaryPredicate> -bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { - return ((container_algorithm_internal::c_size(c1) == - container_algorithm_internal::c_size(c2)) && - std::equal(container_algorithm_internal::c_begin(c1), - container_algorithm_internal::c_end(c1), - container_algorithm_internal::c_begin(c2), - std::forward<BinaryPredicate>(pred))); -} - -// c_is_permutation() -// -// Container-based version of the <algorithm> `std::is_permutation()` function -// to test whether a container is a permutation of another. -template <typename C1, typename C2> -bool c_is_permutation(const C1& c1, const C2& c2) { - using std::begin; - using std::end; - return c1.size() == c2.size() && - std::is_permutation(begin(c1), end(c1), begin(c2)); -} - -// Overload of c_is_permutation() for using a predicate evaluation other than -// `==` as the function's test condition. -template <typename C1, typename C2, typename BinaryPredicate> -bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { - using std::begin; - using std::end; - return c1.size() == c2.size() && - std::is_permutation(begin(c1), end(c1), begin(c2), - std::forward<BinaryPredicate>(pred)); -} - -// c_search() -// -// Container-based version of the <algorithm> `std::search()` function to search -// a container for a subsequence. -template <typename Sequence1, typename Sequence2> -container_algorithm_internal::ContainerIter<Sequence1> c_search( - Sequence1& sequence, Sequence2& subsequence) { - return std::search(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - container_algorithm_internal::c_begin(subsequence), - container_algorithm_internal::c_end(subsequence)); -} - -// Overload of c_search() for using a predicate evaluation other than -// `==` as the function's test condition. -template <typename Sequence1, typename Sequence2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence1> c_search( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { - return std::search(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - container_algorithm_internal::c_begin(subsequence), - container_algorithm_internal::c_end(subsequence), - std::forward<BinaryPredicate>(pred)); -} - -// c_search_n() -// -// Container-based version of the <algorithm> `std::search_n()` function to -// search a container for the first sequence of N elements. -template <typename Sequence, typename Size, typename T> -container_algorithm_internal::ContainerIter<Sequence> c_search_n( - Sequence& sequence, Size count, T&& value) { - return std::search_n(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), count, - std::forward<T>(value)); -} - -// Overload of c_search_n() for using a predicate evaluation other than -// `==` as the function's test condition. -template <typename Sequence, typename Size, typename T, - typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence> c_search_n( - Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) { - return std::search_n(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), count, - std::forward<T>(value), - std::forward<BinaryPredicate>(pred)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Modifying sequence operations -//------------------------------------------------------------------------------ - -// c_copy() -// -// Container-based version of the <algorithm> `std::copy()` function to copy a -// container's elements into an iterator. -template <typename InputSequence, typename OutputIterator> -OutputIterator c_copy(const InputSequence& input, OutputIterator output) { - return std::copy(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), output); -} - -// c_copy_n() -// -// Container-based version of the <algorithm> `std::copy_n()` function to copy a -// container's first N elements into an iterator. -template <typename C, typename Size, typename OutputIterator> -OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) { - return std::copy_n(container_algorithm_internal::c_begin(input), n, output); -} - -// c_copy_if() -// -// Container-based version of the <algorithm> `std::copy_if()` function to copy -// a container's elements satisfying some condition into an iterator. -template <typename InputSequence, typename OutputIterator, typename Pred> -OutputIterator c_copy_if(const InputSequence& input, OutputIterator output, - Pred&& pred) { - return std::copy_if(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), output, - std::forward<Pred>(pred)); -} - -// c_copy_backward() -// -// Container-based version of the <algorithm> `std::copy_backward()` function to -// copy a container's elements in reverse order into an iterator. -template <typename C, typename BidirectionalIterator> -BidirectionalIterator c_copy_backward(const C& src, - BidirectionalIterator dest) { - return std::copy_backward(container_algorithm_internal::c_begin(src), - container_algorithm_internal::c_end(src), dest); -} - -// c_move() -// -// Container-based version of the <algorithm> `std::move()` function to move -// a container's elements into an iterator. -template <typename C, typename OutputIterator> -OutputIterator c_move(C&& src, OutputIterator dest) { - return std::move(container_algorithm_internal::c_begin(src), - container_algorithm_internal::c_end(src), dest); -} - -// c_move_backward() -// -// Container-based version of the <algorithm> `std::move_backward()` function to -// move a container's elements into an iterator in reverse order. -template <typename C, typename BidirectionalIterator> -BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) { - return std::move_backward(container_algorithm_internal::c_begin(src), - container_algorithm_internal::c_end(src), dest); -} - -// c_swap_ranges() -// -// Container-based version of the <algorithm> `std::swap_ranges()` function to -// swap a container's elements with another container's elements. Swaps the -// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). -template <typename C1, typename C2> -container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) { - auto first1 = container_algorithm_internal::c_begin(c1); - auto last1 = container_algorithm_internal::c_end(c1); - auto first2 = container_algorithm_internal::c_begin(c2); - auto last2 = container_algorithm_internal::c_end(c2); - - using std::swap; - for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { - swap(*first1, *first2); - } - return first2; -} - -// c_transform() -// -// Container-based version of the <algorithm> `std::transform()` function to -// transform a container's elements using the unary operation, storing the -// result in an iterator pointing to the last transformed element in the output -// range. -template <typename InputSequence, typename OutputIterator, typename UnaryOp> -OutputIterator c_transform(const InputSequence& input, OutputIterator output, - UnaryOp&& unary_op) { - return std::transform(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), output, - std::forward<UnaryOp>(unary_op)); -} - -// 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)). -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; -} - -// c_replace() -// -// Container-based version of the <algorithm> `std::replace()` function to -// replace a container's elements of some value with a new value. The container -// is modified in place. -template <typename Sequence, typename T> -void c_replace(Sequence& sequence, const T& old_value, const T& new_value) { - std::replace(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), old_value, - new_value); -} - -// c_replace_if() -// -// Container-based version of the <algorithm> `std::replace_if()` function to -// replace a container's elements of some value with a new value based on some -// condition. The container is modified in place. -template <typename C, typename Pred, typename T> -void c_replace_if(C& c, Pred&& pred, T&& new_value) { - std::replace_if(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred), std::forward<T>(new_value)); -} - -// c_replace_copy() -// -// Container-based version of the <algorithm> `std::replace_copy()` function to -// replace a container's elements of some value with a new value and return the -// results within an iterator. -template <typename C, typename OutputIterator, typename T> -OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value, - T&& new_value) { - return std::replace_copy(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result, - std::forward<T>(old_value), - std::forward<T>(new_value)); -} - -// c_replace_copy_if() -// -// Container-based version of the <algorithm> `std::replace_copy_if()` function -// to replace a container's elements of some value with a new value based on -// some condition, and return the results within an iterator. -template <typename C, typename OutputIterator, typename Pred, typename T> -OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred, - T&& new_value) { - return std::replace_copy_if(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result, - std::forward<Pred>(pred), - std::forward<T>(new_value)); -} - -// c_fill() -// -// Container-based version of the <algorithm> `std::fill()` function to fill a -// container with some value. -template <typename C, typename T> -void c_fill(C& c, T&& value) { - std::fill(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), std::forward<T>(value)); -} - -// c_fill_n() -// -// Container-based version of the <algorithm> `std::fill_n()` function to fill -// the first N elements in a container with some value. -template <typename C, typename Size, typename T> -void c_fill_n(C& c, Size n, T&& value) { - std::fill_n(container_algorithm_internal::c_begin(c), n, - std::forward<T>(value)); -} - -// c_generate() -// -// Container-based version of the <algorithm> `std::generate()` function to -// assign a container's elements to the values provided by the given generator. -template <typename C, typename Generator> -void c_generate(C& c, Generator&& gen) { - std::generate(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Generator>(gen)); -} - -// c_generate_n() -// -// Container-based version of the <algorithm> `std::generate_n()` function to -// assign a container's first N elements to the values provided by the given -// generator. -template <typename C, typename Size, typename Generator> -container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n, - Generator&& gen) { - return std::generate_n(container_algorithm_internal::c_begin(c), n, - std::forward<Generator>(gen)); -} - -// Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`, -// and `unique()` are omitted, because it's not clear whether or not such -// functions should call erase on their supplied sequences afterwards. Either -// behavior would be surprising for a different set of users. - -// c_remove_copy() -// -// Container-based version of the <algorithm> `std::remove_copy()` function to -// copy a container's elements while removing any elements matching the given -// `value`. -template <typename C, typename OutputIterator, typename T> -OutputIterator c_remove_copy(const C& c, OutputIterator result, T&& value) { - return std::remove_copy(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result, - std::forward<T>(value)); -} - -// c_remove_copy_if() -// -// Container-based version of the <algorithm> `std::remove_copy_if()` function -// to copy a container's elements while removing any elements matching the given -// condition. -template <typename C, typename OutputIterator, typename Pred> -OutputIterator c_remove_copy_if(const C& c, OutputIterator result, - Pred&& pred) { - return std::remove_copy_if(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result, - std::forward<Pred>(pred)); -} - -// c_unique_copy() -// -// Container-based version of the <algorithm> `std::unique_copy()` function to -// copy a container's elements while removing any elements containing duplicate -// values. -template <typename C, typename OutputIterator> -OutputIterator c_unique_copy(const C& c, OutputIterator result) { - return std::unique_copy(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result); -} - -// Overload of c_unique_copy() for using a predicate evaluation other than -// `==` for comparing uniqueness of the element values. -template <typename C, typename OutputIterator, typename BinaryPredicate> -OutputIterator c_unique_copy(const C& c, OutputIterator result, - BinaryPredicate&& pred) { - return std::unique_copy(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), result, - std::forward<BinaryPredicate>(pred)); -} - -// c_reverse() -// -// Container-based version of the <algorithm> `std::reverse()` function to -// reverse a container's elements. -template <typename Sequence> -void c_reverse(Sequence& sequence) { - std::reverse(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// c_reverse_copy() -// -// Container-based version of the <algorithm> `std::reverse()` function to -// reverse a container's elements and write them to an iterator range. -template <typename C, typename OutputIterator> -OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) { - return std::reverse_copy(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - result); -} - -// c_rotate() -// -// Container-based version of the <algorithm> `std::rotate()` function to -// shift a container's elements leftward such that the `middle` element becomes -// the first element in the container. -template <typename C, - typename Iterator = container_algorithm_internal::ContainerIter<C>> -Iterator c_rotate(C& sequence, Iterator middle) { - return absl::rotate(container_algorithm_internal::c_begin(sequence), middle, - container_algorithm_internal::c_end(sequence)); -} - -// c_rotate_copy() -// -// Container-based version of the <algorithm> `std::rotate_copy()` function to -// shift a container's elements leftward such that the `middle` element becomes -// the first element in a new iterator range. -template <typename C, typename OutputIterator> -OutputIterator c_rotate_copy( - const C& sequence, - container_algorithm_internal::ContainerIter<const C> middle, - OutputIterator result) { - return std::rotate_copy(container_algorithm_internal::c_begin(sequence), - middle, container_algorithm_internal::c_end(sequence), - result); -} - -// c_shuffle() -// -// Container-based version of the <algorithm> `std::shuffle()` function to -// randomly shuffle elements within the container using a `gen()` uniform random -// number generator. -template <typename RandomAccessContainer, typename UniformRandomBitGenerator> -void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { - std::shuffle(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<UniformRandomBitGenerator>(gen)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Partition functions -//------------------------------------------------------------------------------ - -// c_is_partitioned() -// -// Container-based version of the <algorithm> `std::is_partitioned()` function -// to test whether all elements in the container for which `pred` returns `true` -// precede those for which `pred` is `false`. -template <typename C, typename Pred> -bool c_is_partitioned(const C& c, Pred&& pred) { - return std::is_partitioned(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_partition() -// -// Container-based version of the <algorithm> `std::partition()` function -// to rearrange all elements in a container in such a way that all elements for -// which `pred` returns `true` precede all those for which it returns `false`, -// returning an iterator to the first element of the second group. -template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_partition(C& c, Pred&& pred) { - return std::partition(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_stable_partition() -// -// Container-based version of the <algorithm> `std::stable_partition()` function -// to rearrange all elements in a container in such a way that all elements for -// which `pred` returns `true` precede all those for which it returns `false`, -// preserving the relative ordering between the two groups. The function returns -// an iterator to the first element of the second group. -template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_stable_partition(C& c, - Pred&& pred) { - return std::stable_partition(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -// c_partition_copy() -// -// Container-based version of the <algorithm> `std::partition_copy()` function -// to partition a container's elements and return them into two iterators: one -// for which `pred` returns `true`, and one for which `pred` returns `false.` - -template <typename C, typename OutputIterator1, typename OutputIterator2, - typename Pred> -std::pair<OutputIterator1, OutputIterator2> c_partition_copy( - const C& c, OutputIterator1 out_true, OutputIterator2 out_false, - Pred&& pred) { - return std::partition_copy(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), out_true, - out_false, std::forward<Pred>(pred)); -} - -// c_partition_point() -// -// Container-based version of the <algorithm> `std::partition_point()` function -// to return the first element of an already partitioned container for which -// the given `pred` is not `true`. -template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_partition_point(C& c, - Pred&& pred) { - return std::partition_point(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Pred>(pred)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Sorting functions -//------------------------------------------------------------------------------ - -// c_sort() -// -// Container-based version of the <algorithm> `std::sort()` function -// to sort elements in ascending order of their values. -template <typename C> -void c_sort(C& c) { - std::sort(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_sort() for performing a `comp` comparison other than the -// default `operator<`. -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<Compare>(comp)); -} - -// c_stable_sort() -// -// Container-based version of the <algorithm> `std::stable_sort()` function -// to sort elements in ascending order of their values, preserving the order -// of equivalents. -template <typename C> -void c_stable_sort(C& c) { - std::stable_sort(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_stable_sort() for performing a `comp` comparison other than the -// default `operator<`. -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<Compare>(comp)); -} - -// c_is_sorted() -// -// Container-based version of the <algorithm> `std::is_sorted()` function -// to evaluate whether the given container is sorted in ascending order. -template <typename C> -bool c_is_sorted(const C& c) { - return std::is_sorted(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// c_is_sorted() overload for performing a `comp` comparison other than the -// default `operator<`. -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<Compare>(comp)); -} - -// c_partial_sort() -// -// Container-based version of the <algorithm> `std::partial_sort()` function -// to rearrange elements within a container such that elements before `middle` -// are sorted in ascending order. -template <typename RandomAccessContainer> -void c_partial_sort( - RandomAccessContainer& sequence, - container_algorithm_internal::ContainerIter<RandomAccessContainer> middle) { - std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_partial_sort() for performing a `comp` comparison other than -// the default `operator<`. -template <typename RandomAccessContainer, typename Compare> -void c_partial_sort( - RandomAccessContainer& sequence, - container_algorithm_internal::ContainerIter<RandomAccessContainer> middle, - Compare&& comp) { - std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, - container_algorithm_internal::c_end(sequence), - 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. -template <typename C, typename RandomAccessContainer> -container_algorithm_internal::ContainerIter<RandomAccessContainer> -c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) { - 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)); -} - -// Overload of c_partial_sort_copy() for performing a `comp` comparison other -// than the default `operator<`. -template <typename C, typename RandomAccessContainer, typename Compare> -container_algorithm_internal::ContainerIter<RandomAccessContainer> -c_partial_sort_copy(const C& sequence, RandomAccessContainer& result, - 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<Compare>(comp)); -} - -// c_is_sorted_until() -// -// Container-based version of the <algorithm> `std::is_sorted_until()` function -// to return the first element within a container that is not sorted in -// ascending order as an iterator. -template <typename C> -container_algorithm_internal::ContainerIter<C> c_is_sorted_until(C& c) { - return std::is_sorted_until(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_is_sorted_until() for performing a `comp` comparison other than -// the default `operator<`. -template <typename C, typename Compare> -container_algorithm_internal::ContainerIter<C> c_is_sorted_until( - C& c, Compare&& comp) { - return std::is_sorted_until(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<Compare>(comp)); -} - -// c_nth_element() -// -// Container-based version of the <algorithm> `std::nth_element()` function -// to rearrange the elements within a container such that the `nth` element -// would be in that position in an ordered sequence; other elements may be in -// any order, except that all preceding `nth` will be less than that element, -// and all following `nth` will be greater than that element. -template <typename RandomAccessContainer> -void c_nth_element( - RandomAccessContainer& sequence, - container_algorithm_internal::ContainerIter<RandomAccessContainer> nth) { - std::nth_element(container_algorithm_internal::c_begin(sequence), nth, - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_nth_element() for performing a `comp` comparison other than -// the default `operator<`. -template <typename RandomAccessContainer, typename Compare> -void c_nth_element( - RandomAccessContainer& sequence, - container_algorithm_internal::ContainerIter<RandomAccessContainer> nth, - Compare&& comp) { - std::nth_element(container_algorithm_internal::c_begin(sequence), nth, - container_algorithm_internal::c_end(sequence), - std::forward<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Binary Search -//------------------------------------------------------------------------------ - -// c_lower_bound() -// -// Container-based version of the <algorithm> `std::lower_bound()` function -// to return an iterator pointing to the first element in a sorted container -// which does not compare less than `value`. -template <typename Sequence, typename T> -container_algorithm_internal::ContainerIter<Sequence> c_lower_bound( - Sequence& sequence, T&& value) { - return std::lower_bound(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(value)); -} - -// Overload of c_lower_bound() for performing a `comp` comparison other than -// the default `operator<`. -template <typename Sequence, typename T, typename Compare> -container_algorithm_internal::ContainerIter<Sequence> c_lower_bound( - 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<Compare>(comp)); -} - -// c_upper_bound() -// -// Container-based version of the <algorithm> `std::upper_bound()` function -// to return an iterator pointing to the first element in a sorted container -// which is greater than `value`. -template <typename Sequence, typename T> -container_algorithm_internal::ContainerIter<Sequence> c_upper_bound( - Sequence& sequence, T&& value) { - return std::upper_bound(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(value)); -} - -// Overload of c_upper_bound() for performing a `comp` comparison other than -// the default `operator<`. -template <typename Sequence, typename T, typename Compare> -container_algorithm_internal::ContainerIter<Sequence> c_upper_bound( - 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<Compare>(comp)); -} - -// c_equal_range() -// -// Container-based version of the <algorithm> `std::equal_range()` function -// to return an iterator pair pointing to the first and last elements in a -// sorted container which compare equal to `value`. -template <typename Sequence, typename T> -container_algorithm_internal::ContainerIterPairType<Sequence, Sequence> -c_equal_range(Sequence& sequence, T&& value) { - return std::equal_range(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(value)); -} - -// Overload of c_equal_range() for performing a `comp` comparison other than -// the default `operator<`. -template <typename Sequence, typename T, typename Compare> -container_algorithm_internal::ContainerIterPairType<Sequence, Sequence> -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<Compare>(comp)); -} - -// c_binary_search() -// -// Container-based version of the <algorithm> `std::binary_search()` function -// to test if any element in the sorted container contains a value equivalent to -// 'value'. -template <typename Sequence, typename T> -bool c_binary_search(Sequence&& sequence, T&& value) { - return std::binary_search(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(value)); -} - -// Overload of c_binary_search() for performing a `comp` comparison other than -// the default `operator<`. -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<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Merge functions -//------------------------------------------------------------------------------ - -// c_merge() -// -// Container-based version of the <algorithm> `std::merge()` function -// to merge two sorted containers into a single sorted iterator. -template <typename C1, typename C2, typename OutputIterator> -OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) { - 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); -} - -// Overload of c_merge() for performing a `comp` comparison other than -// the default `operator<`. -template <typename C1, typename C2, typename OutputIterator, typename Compare> -OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result, - 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<Compare>(comp)); -} - -// c_inplace_merge() -// -// Container-based version of the <algorithm> `std::inplace_merge()` function -// to merge a supplied iterator `middle` into a container. -template <typename C> -void c_inplace_merge(C& c, - container_algorithm_internal::ContainerIter<C> middle) { - std::inplace_merge(container_algorithm_internal::c_begin(c), middle, - container_algorithm_internal::c_end(c)); -} - -// Overload of c_inplace_merge() for performing a merge using a `comp` other -// than `operator<`. -template <typename C, typename Compare> -void c_inplace_merge(C& c, - container_algorithm_internal::ContainerIter<C> middle, - Compare&& comp) { - std::inplace_merge(container_algorithm_internal::c_begin(c), middle, - container_algorithm_internal::c_end(c), - std::forward<Compare>(comp)); -} - -// c_includes() -// -// Container-based version of the <algorithm> `std::includes()` function -// to test whether a sorted container `c1` entirely contains another sorted -// container `c2`. -template <typename C1, typename C2> -bool c_includes(const C1& c1, const C2& c2) { - 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)); -} - -// Overload of c_includes() for performing a merge using a `comp` other than -// `operator<`. -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<Compare>(comp)); -} - -// c_set_union() -// -// Container-based version of the <algorithm> `std::set_union()` function -// to return an iterator containing the union of two containers; duplicate -// values are not copied into the output. -template <typename C1, typename C2, typename OutputIterator, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { - 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); -} - -// Overload of c_set_union() for performing a merge using a `comp` other than -// `operator<`. -template <typename C1, typename C2, typename OutputIterator, typename Compare, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, - 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<Compare>(comp)); -} - -// c_set_intersection() -// -// Container-based version of the <algorithm> `std::set_intersection()` function -// 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, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_intersection(const C1& c1, const C2& c2, - OutputIterator output) { - 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); -} - -// Overload of c_set_intersection() for performing a merge using a `comp` other -// than `operator<`. -template <typename C1, typename C2, typename OutputIterator, typename Compare, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_intersection(const C1& c1, const C2& c2, - 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<Compare>(comp)); -} - -// c_set_difference() -// -// Container-based version of the <algorithm> `std::set_difference()` function -// to return an iterator containing elements present in the first container but -// not in the second. -template <typename C1, typename C2, typename OutputIterator, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_difference(const C1& c1, const C2& c2, - OutputIterator output) { - 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); -} - -// Overload of c_set_difference() for performing a merge using a `comp` other -// than `operator<`. -template <typename C1, typename C2, typename OutputIterator, typename Compare, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_difference(const C1& c1, const C2& c2, - 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<Compare>(comp)); -} - -// c_set_symmetric_difference() -// -// Container-based version of the <algorithm> `std::set_symmetric_difference()` -// function to return an iterator containing elements present in either one -// container or the other, but not both. -template <typename C1, typename C2, typename OutputIterator, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, - OutputIterator output) { - 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); -} - -// Overload of c_set_symmetric_difference() for performing a merge using a -// `comp` other than `operator<`. -template <typename C1, typename C2, typename OutputIterator, typename Compare, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C1>::value, - void>::type, - typename = typename std::enable_if< - !container_algorithm_internal::IsUnorderedContainer<C2>::value, - void>::type> -OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, - OutputIterator output, - 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<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Heap functions -//------------------------------------------------------------------------------ - -// c_push_heap() -// -// Container-based version of the <algorithm> `std::push_heap()` function -// to push a value onto a container heap. -template <typename RandomAccessContainer> -void c_push_heap(RandomAccessContainer& sequence) { - std::push_heap(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_push_heap() for performing a push operation on a heap using a -// `comp` other than `operator<`. -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<Compare>(comp)); -} - -// c_pop_heap() -// -// Container-based version of the <algorithm> `std::pop_heap()` function -// to pop a value from a heap container. -template <typename RandomAccessContainer> -void c_pop_heap(RandomAccessContainer& sequence) { - std::pop_heap(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_pop_heap() for performing a pop operation on a heap using a -// `comp` other than `operator<`. -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<Compare>(comp)); -} - -// c_make_heap() -// -// Container-based version of the <algorithm> `std::make_heap()` function -// to make a container a heap. -template <typename RandomAccessContainer> -void c_make_heap(RandomAccessContainer& sequence) { - std::make_heap(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_make_heap() for performing heap comparisons using a -// `comp` other than `operator<` -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<Compare>(comp)); -} - -// c_sort_heap() -// -// Container-based version of the <algorithm> `std::sort_heap()` function -// to sort a heap into ascending order (after which it is no longer a heap). -template <typename RandomAccessContainer> -void c_sort_heap(RandomAccessContainer& sequence) { - std::sort_heap(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_sort_heap() for performing heap comparisons using a -// `comp` other than `operator<` -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<Compare>(comp)); -} - -// c_is_heap() -// -// Container-based version of the <algorithm> `std::is_heap()` function -// to check whether the given container is a heap. -template <typename RandomAccessContainer> -bool c_is_heap(const RandomAccessContainer& sequence) { - return std::is_heap(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_is_heap() for performing heap comparisons using a -// `comp` other than `operator<` -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<Compare>(comp)); -} - -// c_is_heap_until() -// -// Container-based version of the <algorithm> `std::is_heap_until()` function -// to find the first element in a given container which is not in heap order. -template <typename RandomAccessContainer> -container_algorithm_internal::ContainerIter<RandomAccessContainer> -c_is_heap_until(RandomAccessContainer& sequence) { - return std::is_heap_until(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_is_heap_until() for performing heap comparisons using a -// `comp` other than `operator<` -template <typename RandomAccessContainer, typename Compare> -container_algorithm_internal::ContainerIter<RandomAccessContainer> -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<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Min/max -//------------------------------------------------------------------------------ - -// c_min_element() -// -// Container-based version of the <algorithm> `std::min_element()` function -// to return an iterator pointing to the element with the smallest value, using -// `operator<` to make the comparisons. -template <typename Sequence> -container_algorithm_internal::ContainerIter<Sequence> c_min_element( - Sequence& sequence) { - return std::min_element(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_min_element() for performing a `comp` comparison other than -// `operator<`. -template <typename Sequence, typename Compare> -container_algorithm_internal::ContainerIter<Sequence> c_min_element( - Sequence& sequence, Compare&& comp) { - return std::min_element(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<Compare>(comp)); -} - -// c_max_element() -// -// Container-based version of the <algorithm> `std::max_element()` function -// to return an iterator pointing to the element with the largest value, using -// `operator<` to make the comparisons. -template <typename Sequence> -container_algorithm_internal::ContainerIter<Sequence> c_max_element( - Sequence& sequence) { - return std::max_element(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence)); -} - -// Overload of c_max_element() for performing a `comp` comparison other than -// `operator<`. -template <typename Sequence, typename Compare> -container_algorithm_internal::ContainerIter<Sequence> c_max_element( - Sequence& sequence, Compare&& comp) { - return std::max_element(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<Compare>(comp)); -} - -// c_minmax_element() -// -// Container-based version of the <algorithm> `std::minmax_element()` function -// to return a pair of iterators pointing to the elements containing the -// smallest and largest values, respectively, using `operator<` to make the -// comparisons. -template <typename C> -container_algorithm_internal::ContainerIterPairType<C, C> -c_minmax_element(C& c) { - return std::minmax_element(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_minmax_element() for performing `comp` comparisons other than -// `operator<`. -template <typename C, typename Compare> -container_algorithm_internal::ContainerIterPairType<C, C> -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<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <algorithm> Lexicographical Comparisons -//------------------------------------------------------------------------------ - -// c_lexicographical_compare() -// -// Container-based version of the <algorithm> `std::lexicographical_compare()` -// function to lexicographically compare (e.g. sort words alphabetically) two -// container sequences. The comparison is performed using `operator<`. Note -// that capital letters ("A-Z") have ASCII values less than lowercase letters -// ("a-z"). -template <typename Sequence1, typename Sequence2> -bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) { - 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)); -} - -// Overload of c_lexicographical_compare() for performing a lexicographical -// comparison using a `comp` operator instead of `operator<`. -template <typename Sequence1, typename Sequence2, typename Compare> -bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2, - 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<Compare>(comp)); -} - -// c_next_permutation() -// -// Container-based version of the <algorithm> `std::next_permutation()` function -// to rearrange a container's elements into the next lexicographically greater -// permutation. -template <typename C> -bool c_next_permutation(C& c) { - return std::next_permutation(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_next_permutation() for performing a lexicographical -// comparison using a `comp` operator instead of `operator<`. -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<Compare>(comp)); -} - -// c_prev_permutation() -// -// Container-based version of the <algorithm> `std::prev_permutation()` function -// to rearrange a container's elements into the next lexicographically lesser -// permutation. -template <typename C> -bool c_prev_permutation(C& c) { - return std::prev_permutation(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c)); -} - -// Overload of c_prev_permutation() for performing a lexicographical -// comparison using a `comp` operator instead of `operator<`. -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<Compare>(comp)); -} - -//------------------------------------------------------------------------------ -// <numeric> algorithms -//------------------------------------------------------------------------------ - -// c_iota() -// -// Container-based version of the <algorithm> `std::iota()` function -// to compute successive values of `value`, as if incremented with `++value` -// after each element is written. and write them to the container. -template <typename Sequence, typename T> -void c_iota(Sequence& sequence, T&& value) { - std::iota(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(value)); -} -// c_accumulate() -// -// Container-based version of the <algorithm> `std::accumulate()` function -// to accumulate the element values of a container to `init` and return that -// accumulation by value. -// -// Note: Due to a language technicality this function has return type -// absl::decay_t<T>. As a user of this function you can casually read -// this as "returns T by value" and assume it does the right thing. -template <typename Sequence, typename T> -decay_t<T> c_accumulate(const Sequence& sequence, T&& init) { - return std::accumulate(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(init)); -} - -// Overload of c_accumulate() for using a binary operations other than -// addition for computing the accumulation. -template <typename Sequence, typename T, typename BinaryOp> -decay_t<T> c_accumulate(const Sequence& sequence, T&& init, - BinaryOp&& binary_op) { - return std::accumulate(container_algorithm_internal::c_begin(sequence), - container_algorithm_internal::c_end(sequence), - std::forward<T>(init), - std::forward<BinaryOp>(binary_op)); -} - -// c_inner_product() -// -// Container-based version of the <algorithm> `std::inner_product()` function -// to compute the cumulative inner product of container element pairs. -// -// Note: Due to a language technicality this function has return type -// absl::decay_t<T>. As a user of this function you can casually read -// this as "returns T by value" and assume it does the right thing. -template <typename Sequence1, typename Sequence2, typename T> -decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2, - T&& sum) { - return std::inner_product(container_algorithm_internal::c_begin(factors1), - container_algorithm_internal::c_end(factors1), - container_algorithm_internal::c_begin(factors2), - std::forward<T>(sum)); -} - -// Overload of c_inner_product() for using binary operations other than -// `operator+` (for computing the accumulation) and `operator*` (for computing -// the product between the two container's element pair). -template <typename Sequence1, typename Sequence2, typename T, - typename BinaryOp1, typename BinaryOp2> -decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2, - T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) { - return std::inner_product(container_algorithm_internal::c_begin(factors1), - container_algorithm_internal::c_end(factors1), - container_algorithm_internal::c_begin(factors2), - std::forward<T>(sum), std::forward<BinaryOp1>(op1), - std::forward<BinaryOp2>(op2)); -} - -// c_adjacent_difference() -// -// Container-based version of the <algorithm> `std::adjacent_difference()` -// function to compute the difference between each element and the one preceding -// it and write it to an iterator. -template <typename InputSequence, typename OutputIt> -OutputIt c_adjacent_difference(const InputSequence& input, - OutputIt output_first) { - return std::adjacent_difference(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), - output_first); -} - -// Overload of c_adjacent_difference() for using a binary operation other than -// subtraction to compute the adjacent difference. -template <typename InputSequence, typename OutputIt, typename BinaryOp> -OutputIt c_adjacent_difference(const InputSequence& input, - OutputIt output_first, BinaryOp&& op) { - return std::adjacent_difference(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), - output_first, std::forward<BinaryOp>(op)); -} - -// c_partial_sum() -// -// Container-based version of the <algorithm> `std::partial_sum()` function -// to compute the partial sum of the elements in a sequence and write them -// to an iterator. The partial sum is the sum of all element values so far in -// the sequence. -template <typename InputSequence, typename OutputIt> -OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) { - return std::partial_sum(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), - output_first); -} - -// Overload of c_partial_sum() for using a binary operation other than addition -// to compute the "partial sum". -template <typename InputSequence, typename OutputIt, typename BinaryOp> -OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first, - BinaryOp&& op) { - return std::partial_sum(container_algorithm_internal::c_begin(input), - container_algorithm_internal::c_end(input), - output_first, std::forward<BinaryOp>(op)); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_ALGORITHM_CONTAINER_H_ diff --git a/third_party/abseil_cpp/absl/algorithm/container_test.cc b/third_party/abseil_cpp/absl/algorithm/container_test.cc deleted file mode 100644 index 605afc8040d7..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/container_test.cc +++ /dev/null @@ -1,1124 +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/algorithm/container.h" - -#include <functional> -#include <initializer_list> -#include <iterator> -#include <list> -#include <memory> -#include <ostream> -#include <random> -#include <set> -#include <unordered_set> -#include <utility> -#include <valarray> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/casts.h" -#include "absl/base/macros.h" -#include "absl/memory/memory.h" -#include "absl/types/span.h" - -namespace { - -using ::testing::Each; -using ::testing::ElementsAre; -using ::testing::Gt; -using ::testing::IsNull; -using ::testing::Lt; -using ::testing::Pointee; -using ::testing::Truly; -using ::testing::UnorderedElementsAre; - -// Most of these tests just check that the code compiles, not that it -// does the right thing. That's fine since the functions just forward -// to the STL implementation. -class NonMutatingTest : public testing::Test { - protected: - std::unordered_set<int> container_ = {1, 2, 3}; - std::list<int> sequence_ = {1, 2, 3}; - std::vector<int> vector_ = {1, 2, 3}; - int array_[3] = {1, 2, 3}; -}; - -struct AccumulateCalls { - void operator()(int value) { calls.push_back(value); } - std::vector<int> calls; -}; - -bool Predicate(int value) { return value < 3; } -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_)); - EXPECT_EQ(vector_.size(), absl::c_distance(vector_)); - EXPECT_EQ(ABSL_ARRAYSIZE(array_), absl::c_distance(array_)); - - // Works with a temporary argument. - EXPECT_EQ(vector_.size(), absl::c_distance(std::vector<int>(vector_))); -} - -TEST_F(NonMutatingTest, Distance_OverloadedBeginEnd) { - // Works with classes which have custom ADL-selected overloads of std::begin - // and std::end. - std::initializer_list<int> a = {1, 2, 3}; - std::valarray<int> b = {1, 2, 3}; - EXPECT_EQ(3, absl::c_distance(a)); - EXPECT_EQ(3, absl::c_distance(b)); - - // It is assumed that other c_* functions use the same mechanism for - // ADL-selecting begin/end overloads. -} - -TEST_F(NonMutatingTest, ForEach) { - AccumulateCalls c = absl::c_for_each(container_, AccumulateCalls()); - // Don't rely on the unordered_set's order. - std::sort(c.calls.begin(), c.calls.end()); - EXPECT_EQ(vector_, c.calls); - - // Works with temporary container, too. - AccumulateCalls c2 = - absl::c_for_each(std::unordered_set<int>(container_), AccumulateCalls()); - std::sort(c2.calls.begin(), c2.calls.end()); - EXPECT_EQ(vector_, c2.calls); -} - -TEST_F(NonMutatingTest, FindReturnsCorrectType) { - auto it = absl::c_find(container_, 3); - EXPECT_EQ(3, *it); - absl::c_find(absl::implicit_cast<const std::list<int>&>(sequence_), 3); -} - -TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); } - -TEST_F(NonMutatingTest, FindIfNot) { - absl::c_find_if_not(container_, Predicate); -} - -TEST_F(NonMutatingTest, FindEnd) { - absl::c_find_end(sequence_, vector_); - absl::c_find_end(vector_, sequence_); -} - -TEST_F(NonMutatingTest, FindEndWithPredicate) { - absl::c_find_end(sequence_, vector_, BinPredicate); - absl::c_find_end(vector_, sequence_, BinPredicate); -} - -TEST_F(NonMutatingTest, FindFirstOf) { - absl::c_find_first_of(container_, sequence_); - absl::c_find_first_of(sequence_, container_); -} - -TEST_F(NonMutatingTest, FindFirstOfWithPredicate) { - absl::c_find_first_of(container_, sequence_, BinPredicate); - absl::c_find_first_of(sequence_, container_, BinPredicate); -} - -TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); } - -TEST_F(NonMutatingTest, AdjacentFindWithPredicate) { - absl::c_adjacent_find(sequence_, BinPredicate); -} - -TEST_F(NonMutatingTest, Count) { EXPECT_EQ(1, absl::c_count(container_, 3)); } - -TEST_F(NonMutatingTest, CountIf) { - EXPECT_EQ(2, absl::c_count_if(container_, Predicate)); - const std::unordered_set<int>& const_container = container_; - EXPECT_EQ(2, absl::c_count_if(const_container, Predicate)); -} - -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); - } -} - -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()); - } -} - -TEST_F(NonMutatingTest, Equal) { - EXPECT_TRUE(absl::c_equal(vector_, sequence_)); - EXPECT_TRUE(absl::c_equal(sequence_, vector_)); - EXPECT_TRUE(absl::c_equal(sequence_, array_)); - EXPECT_TRUE(absl::c_equal(array_, vector_)); - - // Test that behavior appropriately differs from that of equal(). - std::vector<int> vector_plus = {1, 2, 3}; - vector_plus.push_back(4); - EXPECT_FALSE(absl::c_equal(vector_plus, sequence_)); - EXPECT_FALSE(absl::c_equal(sequence_, vector_plus)); - EXPECT_FALSE(absl::c_equal(array_, vector_plus)); -} - -TEST_F(NonMutatingTest, EqualWithPredicate) { - EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals)); - EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals)); - EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals)); - EXPECT_TRUE(absl::c_equal(vector_, array_, Equals)); - - // Test that behavior appropriately differs from that of equal(). - std::vector<int> vector_plus = {1, 2, 3}; - vector_plus.push_back(4); - EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals)); - EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals)); - EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals)); -} - -TEST_F(NonMutatingTest, IsPermutation) { - auto vector_permut_ = vector_; - std::next_permutation(vector_permut_.begin(), vector_permut_.end()); - EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_)); - EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_)); - - // Test that behavior appropriately differs from that of is_permutation(). - std::vector<int> vector_plus = {1, 2, 3}; - vector_plus.push_back(4); - EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_)); - EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus)); -} - -TEST_F(NonMutatingTest, IsPermutationWithPredicate) { - auto vector_permut_ = vector_; - std::next_permutation(vector_permut_.begin(), vector_permut_.end()); - EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_, Equals)); - EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_, Equals)); - - // Test that behavior appropriately differs from that of is_permutation(). - std::vector<int> vector_plus = {1, 2, 3}; - vector_plus.push_back(4); - EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_, Equals)); - EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus, Equals)); -} - -TEST_F(NonMutatingTest, Search) { - absl::c_search(sequence_, vector_); - absl::c_search(vector_, sequence_); - absl::c_search(array_, sequence_); -} - -TEST_F(NonMutatingTest, SearchWithPredicate) { - absl::c_search(sequence_, vector_, BinPredicate); - absl::c_search(vector_, sequence_, BinPredicate); -} - -TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); } - -TEST_F(NonMutatingTest, SearchNWithPredicate) { - absl::c_search_n(sequence_, 3, 1, BinPredicate); -} - -TEST_F(NonMutatingTest, LowerBound) { - std::list<int>::iterator i = absl::c_lower_bound(sequence_, 3); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(2, std::distance(sequence_.begin(), i)); - EXPECT_EQ(3, *i); -} - -TEST_F(NonMutatingTest, LowerBoundWithPredicate) { - std::vector<int> v(vector_); - std::sort(v.begin(), v.end(), std::greater<int>()); - std::vector<int>::iterator i = absl::c_lower_bound(v, 3, std::greater<int>()); - EXPECT_TRUE(i == v.begin()); - EXPECT_EQ(3, *i); -} - -TEST_F(NonMutatingTest, UpperBound) { - std::list<int>::iterator i = absl::c_upper_bound(sequence_, 1); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(1, std::distance(sequence_.begin(), i)); - EXPECT_EQ(2, *i); -} - -TEST_F(NonMutatingTest, UpperBoundWithPredicate) { - std::vector<int> v(vector_); - std::sort(v.begin(), v.end(), std::greater<int>()); - std::vector<int>::iterator i = absl::c_upper_bound(v, 1, std::greater<int>()); - EXPECT_EQ(3, i - v.begin()); - EXPECT_TRUE(i == v.end()); -} - -TEST_F(NonMutatingTest, EqualRange) { - std::pair<std::list<int>::iterator, std::list<int>::iterator> p = - absl::c_equal_range(sequence_, 2); - EXPECT_EQ(1, std::distance(sequence_.begin(), p.first)); - EXPECT_EQ(2, std::distance(sequence_.begin(), p.second)); -} - -TEST_F(NonMutatingTest, EqualRangeArray) { - auto p = absl::c_equal_range(array_, 2); - EXPECT_EQ(1, std::distance(std::begin(array_), p.first)); - EXPECT_EQ(2, std::distance(std::begin(array_), p.second)); -} - -TEST_F(NonMutatingTest, EqualRangeWithPredicate) { - std::vector<int> v(vector_); - std::sort(v.begin(), v.end(), std::greater<int>()); - std::pair<std::vector<int>::iterator, std::vector<int>::iterator> p = - absl::c_equal_range(v, 2, std::greater<int>()); - EXPECT_EQ(1, std::distance(v.begin(), p.first)); - EXPECT_EQ(2, std::distance(v.begin(), p.second)); -} - -TEST_F(NonMutatingTest, BinarySearch) { - EXPECT_TRUE(absl::c_binary_search(vector_, 2)); - EXPECT_TRUE(absl::c_binary_search(std::vector<int>(vector_), 2)); -} - -TEST_F(NonMutatingTest, BinarySearchWithPredicate) { - std::vector<int> v(vector_); - std::sort(v.begin(), v.end(), std::greater<int>()); - EXPECT_TRUE(absl::c_binary_search(v, 2, std::greater<int>())); - EXPECT_TRUE( - absl::c_binary_search(std::vector<int>(v), 2, std::greater<int>())); -} - -TEST_F(NonMutatingTest, MinElement) { - std::list<int>::iterator i = absl::c_min_element(sequence_); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(*i, 1); -} - -TEST_F(NonMutatingTest, MinElementWithPredicate) { - std::list<int>::iterator i = - absl::c_min_element(sequence_, std::greater<int>()); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(*i, 3); -} - -TEST_F(NonMutatingTest, MaxElement) { - std::list<int>::iterator i = absl::c_max_element(sequence_); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(*i, 3); -} - -TEST_F(NonMutatingTest, MaxElementWithPredicate) { - std::list<int>::iterator i = - absl::c_max_element(sequence_, std::greater<int>()); - ASSERT_TRUE(i != sequence_.end()); - EXPECT_EQ(*i, 1); -} - -TEST_F(NonMutatingTest, LexicographicalCompare) { - EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_)); - - std::vector<int> v; - v.push_back(1); - v.push_back(2); - v.push_back(4); - - EXPECT_TRUE(absl::c_lexicographical_compare(sequence_, v)); - EXPECT_TRUE(absl::c_lexicographical_compare(std::list<int>(sequence_), v)); -} - -TEST_F(NonMutatingTest, LexicographicalCopmareWithPredicate) { - EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_, - std::greater<int>())); - - std::vector<int> v; - v.push_back(1); - v.push_back(2); - v.push_back(4); - - EXPECT_TRUE( - absl::c_lexicographical_compare(v, sequence_, std::greater<int>())); - EXPECT_TRUE(absl::c_lexicographical_compare( - std::vector<int>(v), std::list<int>(sequence_), std::greater<int>())); -} - -TEST_F(NonMutatingTest, Includes) { - std::set<int> s(vector_.begin(), vector_.end()); - s.insert(4); - EXPECT_TRUE(absl::c_includes(s, vector_)); -} - -TEST_F(NonMutatingTest, IncludesWithPredicate) { - std::vector<int> v = {3, 2, 1}; - std::set<int, std::greater<int>> s(v.begin(), v.end()); - s.insert(4); - EXPECT_TRUE(absl::c_includes(s, v, std::greater<int>())); -} - -class NumericMutatingTest : public testing::Test { - protected: - std::list<int> list_ = {1, 2, 3}; - std::vector<int> output_; -}; - -TEST_F(NumericMutatingTest, Iota) { - absl::c_iota(list_, 5); - std::list<int> expected{5, 6, 7}; - EXPECT_EQ(list_, expected); -} - -TEST_F(NonMutatingTest, Accumulate) { - EXPECT_EQ(absl::c_accumulate(sequence_, 4), 1 + 2 + 3 + 4); -} - -TEST_F(NonMutatingTest, AccumulateWithBinaryOp) { - EXPECT_EQ(absl::c_accumulate(sequence_, 4, std::multiplies<int>()), - 1 * 2 * 3 * 4); -} - -TEST_F(NonMutatingTest, AccumulateLvalueInit) { - int lvalue = 4; - EXPECT_EQ(absl::c_accumulate(sequence_, lvalue), 1 + 2 + 3 + 4); -} - -TEST_F(NonMutatingTest, AccumulateWithBinaryOpLvalueInit) { - int lvalue = 4; - EXPECT_EQ(absl::c_accumulate(sequence_, lvalue, std::multiplies<int>()), - 1 * 2 * 3 * 4); -} - -TEST_F(NonMutatingTest, InnerProduct) { - EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 1000), - 1000 + 1 * 1 + 2 * 2 + 3 * 3); -} - -TEST_F(NonMutatingTest, InnerProductWithBinaryOps) { - EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 10, - std::multiplies<int>(), std::plus<int>()), - 10 * (1 + 1) * (2 + 2) * (3 + 3)); -} - -TEST_F(NonMutatingTest, InnerProductLvalueInit) { - int lvalue = 1000; - EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue), - 1000 + 1 * 1 + 2 * 2 + 3 * 3); -} - -TEST_F(NonMutatingTest, InnerProductWithBinaryOpsLvalueInit) { - int lvalue = 10; - EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue, - std::multiplies<int>(), std::plus<int>()), - 10 * (1 + 1) * (2 + 2) * (3 + 3)); -} - -TEST_F(NumericMutatingTest, AdjacentDifference) { - auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_)); - *last = 1000; - std::vector<int> expected{1, 2 - 1, 3 - 2, 1000}; - EXPECT_EQ(output_, expected); -} - -TEST_F(NumericMutatingTest, AdjacentDifferenceWithBinaryOp) { - auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_), - std::multiplies<int>()); - *last = 1000; - std::vector<int> expected{1, 2 * 1, 3 * 2, 1000}; - EXPECT_EQ(output_, expected); -} - -TEST_F(NumericMutatingTest, PartialSum) { - auto last = absl::c_partial_sum(list_, std::back_inserter(output_)); - *last = 1000; - std::vector<int> expected{1, 1 + 2, 1 + 2 + 3, 1000}; - EXPECT_EQ(output_, expected); -} - -TEST_F(NumericMutatingTest, PartialSumWithBinaryOp) { - auto last = absl::c_partial_sum(list_, std::back_inserter(output_), - std::multiplies<int>()); - *last = 1000; - std::vector<int> expected{1, 1 * 2, 1 * 2 * 3, 1000}; - EXPECT_EQ(output_, expected); -} - -TEST_F(NonMutatingTest, LinearSearch) { - EXPECT_TRUE(absl::c_linear_search(container_, 3)); - EXPECT_FALSE(absl::c_linear_search(container_, 4)); -} - -TEST_F(NonMutatingTest, AllOf) { - const std::vector<int>& v = vector_; - EXPECT_FALSE(absl::c_all_of(v, [](int x) { return x > 1; })); - EXPECT_TRUE(absl::c_all_of(v, [](int x) { return x > 0; })); -} - -TEST_F(NonMutatingTest, AnyOf) { - const std::vector<int>& v = vector_; - EXPECT_TRUE(absl::c_any_of(v, [](int x) { return x > 2; })); - EXPECT_FALSE(absl::c_any_of(v, [](int x) { return x > 5; })); -} - -TEST_F(NonMutatingTest, NoneOf) { - const std::vector<int>& v = vector_; - EXPECT_FALSE(absl::c_none_of(v, [](int x) { return x > 2; })); - EXPECT_TRUE(absl::c_none_of(v, [](int x) { return x > 5; })); -} - -TEST_F(NonMutatingTest, MinMaxElementLess) { - std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator> - p = absl::c_minmax_element(vector_, std::less<int>()); - EXPECT_TRUE(p.first == vector_.begin()); - EXPECT_TRUE(p.second == vector_.begin() + 2); -} - -TEST_F(NonMutatingTest, MinMaxElementGreater) { - std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator> - p = absl::c_minmax_element(vector_, std::greater<int>()); - EXPECT_TRUE(p.first == vector_.begin() + 2); - EXPECT_TRUE(p.second == vector_.begin()); -} - -TEST_F(NonMutatingTest, MinMaxElementNoPredicate) { - std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator> - p = absl::c_minmax_element(vector_); - EXPECT_TRUE(p.first == vector_.begin()); - EXPECT_TRUE(p.second == vector_.begin() + 2); -} - -class SortingTest : public testing::Test { - protected: - std::list<int> sorted_ = {1, 2, 3, 4}; - std::list<int> unsorted_ = {2, 4, 1, 3}; - std::list<int> reversed_ = {4, 3, 2, 1}; -}; - -TEST_F(SortingTest, IsSorted) { - EXPECT_TRUE(absl::c_is_sorted(sorted_)); - EXPECT_FALSE(absl::c_is_sorted(unsorted_)); - EXPECT_FALSE(absl::c_is_sorted(reversed_)); -} - -TEST_F(SortingTest, IsSortedWithPredicate) { - EXPECT_FALSE(absl::c_is_sorted(sorted_, std::greater<int>())); - EXPECT_FALSE(absl::c_is_sorted(unsorted_, std::greater<int>())); - EXPECT_TRUE(absl::c_is_sorted(reversed_, std::greater<int>())); -} - -TEST_F(SortingTest, IsSortedUntil) { - EXPECT_EQ(1, *absl::c_is_sorted_until(unsorted_)); - EXPECT_EQ(4, *absl::c_is_sorted_until(unsorted_, std::greater<int>())); -} - -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))); - absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>()); - EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2))); -} - -TEST(MutatingTest, IsPartitioned) { - EXPECT_TRUE( - absl::c_is_partitioned(std::vector<int>{1, 3, 5, 2, 4, 6}, IsOdd)); - EXPECT_FALSE( - absl::c_is_partitioned(std::vector<int>{1, 2, 3, 4, 5, 6}, IsOdd)); - EXPECT_FALSE( - absl::c_is_partitioned(std::vector<int>{2, 4, 6, 1, 3, 5}, IsOdd)); -} - -TEST(MutatingTest, Partition) { - std::vector<int> actual = {1, 2, 3, 4, 5}; - absl::c_partition(actual, IsOdd); - EXPECT_THAT(actual, Truly([](const std::vector<int>& c) { - return absl::c_is_partitioned(c, IsOdd); - })); -} - -TEST(MutatingTest, StablePartition) { - std::vector<int> actual = {1, 2, 3, 4, 5}; - absl::c_stable_partition(actual, IsOdd); - EXPECT_THAT(actual, ElementsAre(1, 3, 5, 2, 4)); -} - -TEST(MutatingTest, PartitionCopy) { - const std::vector<int> initial = {1, 2, 3, 4, 5}; - std::vector<int> odds, evens; - auto ends = absl::c_partition_copy(initial, back_inserter(odds), - back_inserter(evens), IsOdd); - *ends.first = 7; - *ends.second = 6; - EXPECT_THAT(odds, ElementsAre(1, 3, 5, 7)); - EXPECT_THAT(evens, ElementsAre(2, 4, 6)); -} - -TEST(MutatingTest, PartitionPoint) { - const std::vector<int> initial = {1, 3, 5, 2, 4}; - auto middle = absl::c_partition_point(initial, IsOdd); - EXPECT_EQ(2, *middle); -} - -TEST(MutatingTest, CopyMiddle) { - const std::vector<int> initial = {4, -1, -2, -3, 5}; - const std::list<int> input = {1, 2, 3}; - const std::vector<int> expected = {4, 1, 2, 3, 5}; - - std::list<int> test_list(initial.begin(), initial.end()); - absl::c_copy(input, ++test_list.begin()); - EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list); - - std::vector<int> test_vector = initial; - absl::c_copy(input, test_vector.begin() + 1); - EXPECT_EQ(expected, test_vector); -} - -TEST(MutatingTest, CopyFrontInserter) { - const std::list<int> initial = {4, 5}; - const std::list<int> input = {1, 2, 3}; - const std::list<int> expected = {3, 2, 1, 4, 5}; - - std::list<int> test_list = initial; - absl::c_copy(input, std::front_inserter(test_list)); - EXPECT_EQ(expected, test_list); -} - -TEST(MutatingTest, CopyBackInserter) { - const std::vector<int> initial = {4, 5}; - const std::list<int> input = {1, 2, 3}; - const std::vector<int> expected = {4, 5, 1, 2, 3}; - - std::list<int> test_list(initial.begin(), initial.end()); - absl::c_copy(input, std::back_inserter(test_list)); - EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list); - - std::vector<int> test_vector = initial; - absl::c_copy(input, std::back_inserter(test_vector)); - EXPECT_EQ(expected, test_vector); -} - -TEST(MutatingTest, CopyN) { - const std::vector<int> initial = {1, 2, 3, 4, 5}; - const std::vector<int> expected = {1, 2}; - std::vector<int> actual; - absl::c_copy_n(initial, 2, back_inserter(actual)); - EXPECT_EQ(expected, actual); -} - -TEST(MutatingTest, CopyIf) { - const std::list<int> input = {1, 2, 3}; - std::vector<int> output; - absl::c_copy_if(input, std::back_inserter(output), - [](int i) { return i != 2; }); - EXPECT_THAT(output, ElementsAre(1, 3)); -} - -TEST(MutatingTest, CopyBackward) { - std::vector<int> actual = {1, 2, 3, 4, 5}; - std::vector<int> expected = {1, 2, 1, 2, 3}; - absl::c_copy_backward(absl::MakeSpan(actual.data(), 3), actual.end()); - EXPECT_EQ(expected, actual); -} - -TEST(MutatingTest, Move) { - std::vector<std::unique_ptr<int>> src; - src.emplace_back(absl::make_unique<int>(1)); - src.emplace_back(absl::make_unique<int>(2)); - src.emplace_back(absl::make_unique<int>(3)); - src.emplace_back(absl::make_unique<int>(4)); - src.emplace_back(absl::make_unique<int>(5)); - - std::vector<std::unique_ptr<int>> dest = {}; - absl::c_move(src, std::back_inserter(dest)); - EXPECT_THAT(src, Each(IsNull())); - EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(4), - Pointee(5))); -} - -TEST(MutatingTest, MoveBackward) { - std::vector<std::unique_ptr<int>> actual; - actual.emplace_back(absl::make_unique<int>(1)); - actual.emplace_back(absl::make_unique<int>(2)); - actual.emplace_back(absl::make_unique<int>(3)); - actual.emplace_back(absl::make_unique<int>(4)); - actual.emplace_back(absl::make_unique<int>(5)); - auto subrange = absl::MakeSpan(actual.data(), 3); - absl::c_move_backward(subrange, actual.end()); - EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2), - Pointee(3))); -} - -TEST(MutatingTest, MoveWithRvalue) { - auto MakeRValueSrc = [] { - std::vector<std::unique_ptr<int>> src; - src.emplace_back(absl::make_unique<int>(1)); - src.emplace_back(absl::make_unique<int>(2)); - src.emplace_back(absl::make_unique<int>(3)); - return src; - }; - - std::vector<std::unique_ptr<int>> dest = MakeRValueSrc(); - absl::c_move(MakeRValueSrc(), std::back_inserter(dest)); - EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(1), - Pointee(2), Pointee(3))); -} - -TEST(MutatingTest, SwapRanges) { - std::vector<int> odds = {2, 4, 6}; - std::vector<int> evens = {1, 3, 5}; - 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) { - std::vector<int> x{0, 2, 4}, y, z; - auto end = absl::c_transform(x, back_inserter(y), std::negate<int>()); - EXPECT_EQ(std::vector<int>({0, -2, -4}), y); - *end = 7; - EXPECT_EQ(std::vector<int>({0, -2, -4, 7}), y); - - y = {1, 3, 0}; - end = absl::c_transform(x, y, back_inserter(z), std::plus<int>()); - 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) { - const std::vector<int> initial = {1, 2, 3, 1, 4, 5}; - const std::vector<int> expected = {4, 2, 3, 4, 4, 5}; - - std::vector<int> test_vector = initial; - absl::c_replace(test_vector, 1, 4); - EXPECT_EQ(expected, test_vector); - - std::list<int> test_list(initial.begin(), initial.end()); - absl::c_replace(test_list, 1, 4); - EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list); -} - -TEST(MutatingTest, ReplaceIf) { - std::vector<int> actual = {1, 2, 3, 4, 5}; - const std::vector<int> expected = {0, 2, 0, 4, 0}; - - absl::c_replace_if(actual, IsOdd, 0); - EXPECT_EQ(expected, actual); -} - -TEST(MutatingTest, ReplaceCopy) { - const std::vector<int> initial = {1, 2, 3, 1, 4, 5}; - const std::vector<int> expected = {4, 2, 3, 4, 4, 5}; - - std::vector<int> actual; - absl::c_replace_copy(initial, back_inserter(actual), 1, 4); - EXPECT_EQ(expected, actual); -} - -TEST(MutatingTest, Sort) { - std::vector<int> test_vector = {2, 3, 1, 4}; - absl::c_sort(test_vector); - EXPECT_THAT(test_vector, ElementsAre(1, 2, 3, 4)); -} - -TEST(MutatingTest, SortWithPredicate) { - std::vector<int> test_vector = {2, 3, 1, 4}; - absl::c_sort(test_vector, std::greater<int>()); - EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); -} - -// For absl::c_stable_sort tests. Needs an operator< that does not cover all -// fields so that the test can check the sort preserves order of equal elements. -struct Element { - int key; - int value; - friend bool operator<(const Element& e1, const Element& e2) { - return e1.key < e2.key; - } - // Make gmock print useful diagnostics. - friend std::ostream& operator<<(std::ostream& o, const Element& e) { - return o << "{" << e.key << ", " << e.value << "}"; - } -}; - -MATCHER_P2(IsElement, key, value, "") { - return arg.key == key && arg.value == 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))); -} - -TEST(MutatingTest, StableSortWithPredicate) { - std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}}; - 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))); -} - -TEST(MutatingTest, ReplaceCopyIf) { - const std::vector<int> initial = {1, 2, 3, 4, 5}; - const std::vector<int> expected = {0, 2, 0, 4, 0}; - - std::vector<int> actual; - absl::c_replace_copy_if(initial, back_inserter(actual), IsOdd, 0); - EXPECT_EQ(expected, actual); -} - -TEST(MutatingTest, Fill) { - std::vector<int> actual(5); - absl::c_fill(actual, 1); - EXPECT_THAT(actual, ElementsAre(1, 1, 1, 1, 1)); -} - -TEST(MutatingTest, FillN) { - std::vector<int> actual(5, 0); - absl::c_fill_n(actual, 2, 1); - EXPECT_THAT(actual, ElementsAre(1, 1, 0, 0, 0)); -} - -TEST(MutatingTest, Generate) { - std::vector<int> actual(5); - int x = 0; - absl::c_generate(actual, [&x]() { return ++x; }); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); -} - -TEST(MutatingTest, GenerateN) { - std::vector<int> actual(5, 0); - int x = 0; - absl::c_generate_n(actual, 3, [&x]() { return ++x; }); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 0, 0)); -} - -TEST(MutatingTest, RemoveCopy) { - std::vector<int> actual; - absl::c_remove_copy(std::vector<int>{1, 2, 3}, back_inserter(actual), 2); - EXPECT_THAT(actual, ElementsAre(1, 3)); -} - -TEST(MutatingTest, RemoveCopyIf) { - std::vector<int> actual; - absl::c_remove_copy_if(std::vector<int>{1, 2, 3}, back_inserter(actual), - IsOdd); - EXPECT_THAT(actual, ElementsAre(2)); -} - -TEST(MutatingTest, UniqueCopy) { - std::vector<int> actual; - absl::c_unique_copy(std::vector<int>{1, 2, 2, 2, 3, 3, 2}, - back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 2)); -} - -TEST(MutatingTest, UniqueCopyWithPredicate) { - std::vector<int> actual; - absl::c_unique_copy(std::vector<int>{1, 2, 3, -1, -2, -3, 1}, - back_inserter(actual), - [](int x, int y) { return (x < 0) == (y < 0); }); - EXPECT_THAT(actual, ElementsAre(1, -1, 1)); -} - -TEST(MutatingTest, Reverse) { - std::vector<int> test_vector = {1, 2, 3, 4}; - absl::c_reverse(test_vector); - EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); - - std::list<int> test_list = {1, 2, 3, 4}; - absl::c_reverse(test_list); - EXPECT_THAT(test_list, ElementsAre(4, 3, 2, 1)); -} - -TEST(MutatingTest, ReverseCopy) { - std::vector<int> actual; - absl::c_reverse_copy(std::vector<int>{1, 2, 3, 4}, back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(4, 3, 2, 1)); -} - -TEST(MutatingTest, Rotate) { - std::vector<int> actual = {1, 2, 3, 4}; - auto it = absl::c_rotate(actual, actual.begin() + 2); - EXPECT_THAT(actual, testing::ElementsAreArray({3, 4, 1, 2})); - EXPECT_EQ(*it, 1); -} - -TEST(MutatingTest, RotateCopy) { - std::vector<int> initial = {1, 2, 3, 4}; - std::vector<int> actual; - auto end = - absl::c_rotate_copy(initial, initial.begin() + 2, back_inserter(actual)); - *end = 5; - EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5)); -} - -TEST(MutatingTest, Shuffle) { - std::vector<int> actual = {1, 2, 3, 4, 5}; - absl::c_shuffle(actual, std::random_device()); - EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5)); -} - -TEST(MutatingTest, PartialSort) { - std::vector<int> sequence{5, 3, 42, 0}; - absl::c_partial_sort(sequence, sequence.begin() + 2); - EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(0, 3)); - absl::c_partial_sort(sequence, sequence.begin() + 2, std::greater<int>()); - EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(42, 5)); -} - -TEST(MutatingTest, PartialSortCopy) { - const std::vector<int> initial = {5, 3, 42, 0}; - std::vector<int> actual(2); - absl::c_partial_sort_copy(initial, actual); - EXPECT_THAT(actual, ElementsAre(0, 3)); - absl::c_partial_sort_copy(initial, actual, std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(42, 5)); -} - -TEST(MutatingTest, Merge) { - std::vector<int> actual; - absl::c_merge(std::vector<int>{1, 3, 5}, std::vector<int>{2, 4}, - back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); -} - -TEST(MutatingTest, MergeWithComparator) { - std::vector<int> actual; - absl::c_merge(std::vector<int>{5, 3, 1}, std::vector<int>{4, 2}, - back_inserter(actual), std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); -} - -TEST(MutatingTest, InplaceMerge) { - std::vector<int> actual = {1, 3, 5, 2, 4}; - absl::c_inplace_merge(actual, actual.begin() + 3); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); -} - -TEST(MutatingTest, InplaceMergeWithComparator) { - std::vector<int> actual = {5, 3, 1, 4, 2}; - absl::c_inplace_merge(actual, actual.begin() + 3, std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); -} - -class SetOperationsTest : public testing::Test { - protected: - std::vector<int> a_ = {1, 2, 3}; - std::vector<int> b_ = {1, 3, 5}; - - std::vector<int> a_reversed_ = {3, 2, 1}; - std::vector<int> b_reversed_ = {5, 3, 1}; -}; - -TEST_F(SetOperationsTest, SetUnion) { - std::vector<int> actual; - absl::c_set_union(a_, b_, back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(1, 2, 3, 5)); -} - -TEST_F(SetOperationsTest, SetUnionWithComparator) { - std::vector<int> actual; - absl::c_set_union(a_reversed_, b_reversed_, back_inserter(actual), - std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(5, 3, 2, 1)); -} - -TEST_F(SetOperationsTest, SetIntersection) { - std::vector<int> actual; - absl::c_set_intersection(a_, b_, back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(1, 3)); -} - -TEST_F(SetOperationsTest, SetIntersectionWithComparator) { - std::vector<int> actual; - absl::c_set_intersection(a_reversed_, b_reversed_, back_inserter(actual), - std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(3, 1)); -} - -TEST_F(SetOperationsTest, SetDifference) { - std::vector<int> actual; - absl::c_set_difference(a_, b_, back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(2)); -} - -TEST_F(SetOperationsTest, SetDifferenceWithComparator) { - std::vector<int> actual; - absl::c_set_difference(a_reversed_, b_reversed_, back_inserter(actual), - std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(2)); -} - -TEST_F(SetOperationsTest, SetSymmetricDifference) { - std::vector<int> actual; - absl::c_set_symmetric_difference(a_, b_, back_inserter(actual)); - EXPECT_THAT(actual, ElementsAre(2, 5)); -} - -TEST_F(SetOperationsTest, SetSymmetricDifferenceWithComparator) { - std::vector<int> actual; - absl::c_set_symmetric_difference(a_reversed_, b_reversed_, - back_inserter(actual), std::greater<int>()); - EXPECT_THAT(actual, ElementsAre(5, 2)); -} - -TEST(HeapOperationsTest, WithoutComparator) { - std::vector<int> heap = {1, 2, 3}; - EXPECT_FALSE(absl::c_is_heap(heap)); - absl::c_make_heap(heap); - EXPECT_TRUE(absl::c_is_heap(heap)); - heap.push_back(4); - EXPECT_EQ(3, absl::c_is_heap_until(heap) - heap.begin()); - absl::c_push_heap(heap); - EXPECT_EQ(4, heap[0]); - absl::c_pop_heap(heap); - EXPECT_EQ(4, heap[3]); - absl::c_make_heap(heap); - absl::c_sort_heap(heap); - EXPECT_THAT(heap, ElementsAre(1, 2, 3, 4)); - EXPECT_FALSE(absl::c_is_heap(heap)); -} - -TEST(HeapOperationsTest, WithComparator) { - using greater = std::greater<int>; - std::vector<int> heap = {3, 2, 1}; - EXPECT_FALSE(absl::c_is_heap(heap, greater())); - absl::c_make_heap(heap, greater()); - EXPECT_TRUE(absl::c_is_heap(heap, greater())); - heap.push_back(0); - EXPECT_EQ(3, absl::c_is_heap_until(heap, greater()) - heap.begin()); - absl::c_push_heap(heap, greater()); - EXPECT_EQ(0, heap[0]); - absl::c_pop_heap(heap, greater()); - EXPECT_EQ(0, heap[3]); - absl::c_make_heap(heap, greater()); - absl::c_sort_heap(heap, greater()); - EXPECT_THAT(heap, ElementsAre(3, 2, 1, 0)); - EXPECT_FALSE(absl::c_is_heap(heap, greater())); -} - -TEST(MutatingTest, PermutationOperations) { - std::vector<int> initial = {1, 2, 3, 4}; - std::vector<int> permuted = initial; - - absl::c_next_permutation(permuted); - EXPECT_TRUE(absl::c_is_permutation(initial, permuted)); - EXPECT_TRUE(absl::c_is_permutation(initial, permuted, std::equal_to<int>())); - - std::vector<int> permuted2 = initial; - absl::c_prev_permutation(permuted2, std::greater<int>()); - EXPECT_EQ(permuted, permuted2); - - absl::c_prev_permutation(permuted); - EXPECT_EQ(initial, permuted); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/algorithm/equal_benchmark.cc b/third_party/abseil_cpp/absl/algorithm/equal_benchmark.cc deleted file mode 100644 index 7bf62c9a7f56..000000000000 --- a/third_party/abseil_cpp/absl/algorithm/equal_benchmark.cc +++ /dev/null @@ -1,126 +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 <cstdint> -#include <cstring> - -#include "benchmark/benchmark.h" -#include "absl/algorithm/algorithm.h" - -namespace { - -// The range of sequence sizes to benchmark. -constexpr int kMinBenchmarkSize = 1024; -constexpr int kMaxBenchmarkSize = 8 * 1024 * 1024; - -// A user-defined type for use in equality benchmarks. Note that we expect -// std::memcmp to win for this type: libstdc++'s std::equal only defers to -// memcmp for integral types. This is because it is not straightforward to -// guarantee that std::memcmp would produce a result "as-if" compared by -// operator== for other types (example gotchas: NaN floats, structs with -// padding). -struct EightBits { - explicit EightBits(int /* unused */) : data(0) {} - bool operator==(const EightBits& rhs) const { return data == rhs.data; } - uint8_t data; -}; - -template <typename T> -void BM_absl_equal_benchmark(benchmark::State& state) { - std::vector<T> xs(state.range(0), T(0)); - std::vector<T> ys = xs; - while (state.KeepRunning()) { - const bool same = absl::equal(xs.begin(), xs.end(), ys.begin(), ys.end()); - benchmark::DoNotOptimize(same); - } -} - -template <typename T> -void BM_std_equal_benchmark(benchmark::State& state) { - std::vector<T> xs(state.range(0), T(0)); - std::vector<T> ys = xs; - while (state.KeepRunning()) { - const bool same = std::equal(xs.begin(), xs.end(), ys.begin()); - benchmark::DoNotOptimize(same); - } -} - -template <typename T> -void BM_memcmp_benchmark(benchmark::State& state) { - std::vector<T> xs(state.range(0), T(0)); - std::vector<T> ys = xs; - while (state.KeepRunning()) { - const bool same = - std::memcmp(xs.data(), ys.data(), xs.size() * sizeof(T)) == 0; - benchmark::DoNotOptimize(same); - } -} - -// The expectation is that the compiler should be able to elide the equality -// comparison altogether for sufficiently simple types. -template <typename T> -void BM_absl_equal_self_benchmark(benchmark::State& state) { - std::vector<T> xs(state.range(0), T(0)); - while (state.KeepRunning()) { - const bool same = absl::equal(xs.begin(), xs.end(), xs.begin(), xs.end()); - benchmark::DoNotOptimize(same); - } -} - -BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint8_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint8_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint8_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint8_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); - -BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint16_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint16_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint16_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint16_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); - -BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint32_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint32_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint32_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint32_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); - -BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint64_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint64_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint64_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint64_t) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); - -BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, EightBits) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_std_equal_benchmark, EightBits) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_memcmp_benchmark, EightBits) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); -BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits) - ->Range(kMinBenchmarkSize, kMaxBenchmarkSize); - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/BUILD.bazel b/third_party/abseil_cpp/absl/base/BUILD.bazel deleted file mode 100644 index 9d96abeb33ae..000000000000 --- a/third_party/abseil_cpp/absl/base/BUILD.bazel +++ /dev/null @@ -1,818 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "atomic_hook", - hdrs = ["internal/atomic_hook.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ":core_headers", - ], -) - -cc_library( - name = "errno_saver", - hdrs = ["internal/errno_saver.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [":config"], -) - -cc_library( - name = "log_severity", - srcs = ["log_severity.cc"], - hdrs = ["log_severity.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":core_headers", - ], -) - -cc_library( - name = "raw_logging_internal", - srcs = ["internal/raw_logging.cc"], - hdrs = ["internal/raw_logging.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":atomic_hook", - ":config", - ":core_headers", - ":log_severity", - ], -) - -cc_library( - name = "spinlock_wait", - srcs = [ - "internal/spinlock_akaros.inc", - "internal/spinlock_linux.inc", - "internal/spinlock_posix.inc", - "internal/spinlock_wait.cc", - "internal/spinlock_win32.inc", - ], - hdrs = ["internal/spinlock_wait.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/base:__pkg__", - ], - deps = [ - ":base_internal", - ":core_headers", - ":errno_saver", - ], -) - -cc_library( - name = "config", - hdrs = [ - "config.h", - "options.h", - "policy_checks.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, -) - -cc_library( - name = "dynamic_annotations", - srcs = [ - "internal/dynamic_annotations.h", - ], - hdrs = [ - "dynamic_annotations.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":core_headers", - ], -) - -cc_library( - name = "core_headers", - srcs = [ - "internal/thread_annotations.h", - ], - hdrs = [ - "attributes.h", - "const_init.h", - "macros.h", - "optimization.h", - "port.h", - "thread_annotations.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ], -) - -cc_library( - name = "malloc_internal", - srcs = [ - "internal/low_level_alloc.cc", - ], - hdrs = [ - "internal/direct_mmap.h", - "internal/low_level_alloc.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = select({ - "//absl:windows": [], - "//absl:wasm": [], - "//conditions:default": ["-pthread"], - }) + ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//visibility:public", - ], - deps = [ - ":base", - ":base_internal", - ":config", - ":core_headers", - ":dynamic_annotations", - ":raw_logging_internal", - ], -) - -cc_library( - name = "base_internal", - hdrs = [ - "internal/hide_ptr.h", - "internal/identity.h", - "internal/inline_variable.h", - "internal/invoke.h", - "internal/scheduling_mode.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "base", - srcs = [ - "internal/cycleclock.cc", - "internal/spinlock.cc", - "internal/sysinfo.cc", - "internal/thread_identity.cc", - "internal/unscaledcycleclock.cc", - ], - hdrs = [ - "call_once.h", - "casts.h", - "internal/cycleclock.h", - "internal/low_level_scheduling.h", - "internal/per_thread_tls.h", - "internal/spinlock.h", - "internal/sysinfo.h", - "internal/thread_identity.h", - "internal/tsan_mutex_interface.h", - "internal/unscaledcycleclock.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = select({ - "//absl:windows": [ - "-DEFAULTLIB:advapi32.lib", - ], - "//absl:wasm": [], - "//conditions:default": ["-pthread"], - }) + ABSL_DEFAULT_LINKOPTS, - deps = [ - ":atomic_hook", - ":base_internal", - ":config", - ":core_headers", - ":dynamic_annotations", - ":log_severity", - ":raw_logging_internal", - ":spinlock_wait", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "atomic_hook_test_helper", - testonly = 1, - srcs = ["internal/atomic_hook_test_helper.cc"], - hdrs = ["internal/atomic_hook_test_helper.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":atomic_hook", - ":core_headers", - ], -) - -cc_test( - name = "atomic_hook_test", - size = "small", - srcs = ["internal/atomic_hook_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":atomic_hook", - ":atomic_hook_test_helper", - ":core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "bit_cast_test", - size = "small", - srcs = [ - "bit_cast_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - ":core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "throw_delegate", - srcs = ["internal/throw_delegate.cc"], - hdrs = ["internal/throw_delegate.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ":raw_logging_internal", - ], -) - -cc_test( - name = "throw_delegate_test", - srcs = ["throw_delegate_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":throw_delegate", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "errno_saver_test", - size = "small", - srcs = ["internal/errno_saver_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":errno_saver", - ":strerror", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "exception_testing", - testonly = 1, - hdrs = ["internal/exception_testing.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "pretty_function", - hdrs = ["internal/pretty_function.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//absl:__subpackages__"], -) - -cc_library( - name = "exception_safety_testing", - testonly = 1, - srcs = ["internal/exception_safety_testing.cc"], - hdrs = ["internal/exception_safety_testing.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":pretty_function", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/utility", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "exception_safety_testing_test", - srcs = ["exception_safety_testing_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":exception_safety_testing", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "inline_variable_test", - size = "small", - srcs = [ - "inline_variable_test.cc", - "inline_variable_test_a.cc", - "inline_variable_test_b.cc", - "internal/inline_variable_testing.h", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "invoke_test", - size = "small", - srcs = ["invoke_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base_internal", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -# Common test library made available for use in non-absl code that overrides -# AbslInternalSpinLockDelay and AbslInternalSpinLockWake. -cc_library( - name = "spinlock_test_common", - testonly = 1, - srcs = ["spinlock_test_common.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - ":base_internal", - ":config", - ":core_headers", - "//absl/synchronization", - "@com_google_googletest//:gtest", - ], - alwayslink = 1, -) - -cc_test( - name = "spinlock_test", - size = "medium", - srcs = ["spinlock_test_common.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - ":base_internal", - ":config", - ":core_headers", - "//absl/synchronization", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "spinlock_benchmark_common", - testonly = 1, - srcs = ["internal/spinlock_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/base:__pkg__", - ], - deps = [ - ":base", - ":base_internal", - ":raw_logging_internal", - "//absl/synchronization", - "@com_github_google_benchmark//:benchmark_main", - ], - alwayslink = 1, -) - -cc_binary( - name = "spinlock_benchmark", - testonly = 1, - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":spinlock_benchmark_common", - ], -) - -cc_library( - name = "endian", - hdrs = [ - "internal/endian.h", - "internal/unaligned_access.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":core_headers", - ], -) - -cc_test( - name = "endian_test", - srcs = ["internal/endian_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":config", - ":endian", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "config_test", - srcs = ["config_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - "//absl/synchronization:thread_pool", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "call_once_test", - srcs = ["call_once_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - ":core_headers", - "//absl/synchronization", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "raw_logging_test", - srcs = ["raw_logging_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":raw_logging_internal", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "sysinfo_test", - size = "small", - srcs = ["internal/sysinfo_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - "//absl/synchronization", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "low_level_alloc_test", - size = "medium", - 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", - ], -) - -cc_test( - name = "thread_identity_test", - size = "small", - srcs = ["internal/thread_identity_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":base", - ":core_headers", - "//absl/synchronization", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "thread_identity_benchmark", - srcs = ["internal/thread_identity_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":base", - "//absl/synchronization", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "bits", - hdrs = ["internal/bits.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ":core_headers", - ], -) - -cc_test( - name = "bits_test", - size = "small", - srcs = ["internal/bits_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":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 = "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, - deps = [ - ":core_headers", - ":exponential_biased", - ], -) - -cc_test( - name = "periodic_sampler_test", - size = "small", - srcs = ["internal/periodic_sampler_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - ":core_headers", - ":periodic_sampler", - "@com_google_googletest//:gtest_main", - ], -) - -cc_binary( - name = "periodic_sampler_benchmark", - testonly = 1, - srcs = ["internal/periodic_sampler_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":core_headers", - ":periodic_sampler", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "scoped_set_env", - testonly = 1, - srcs = ["internal/scoped_set_env.cc"], - hdrs = ["internal/scoped_set_env.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ":raw_logging_internal", - ], -) - -cc_test( - name = "scoped_set_env_test", - size = "small", - srcs = ["internal/scoped_set_env_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":scoped_set_env", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "log_severity_test", - size = "small", - srcs = ["log_severity_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":log_severity", - "//absl/flags:flag_internal", - "//absl/flags:marshalling", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "strerror", - srcs = ["internal/strerror.cc"], - hdrs = ["internal/strerror.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ":core_headers", - ":errno_saver", - ], -) - -cc_test( - name = "strerror_test", - size = "small", - srcs = ["internal/strerror_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":strerror", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_binary( - name = "strerror_benchmark", - testonly = 1, - srcs = ["internal/strerror_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strerror", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "fast_type_id", - hdrs = ["internal/fast_type_id.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":config", - ], -) - -cc_test( - name = "fast_type_id_test", - size = "small", - srcs = ["internal/fast_type_id_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fast_type_id", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "unique_small_name_test", - size = "small", - srcs = ["internal/unique_small_name_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - linkstatic = 1, - deps = [ - ":core_headers", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "optimization_test", - size = "small", - srcs = ["optimization_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":core_headers", - "//absl/types:optional", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/base/CMakeLists.txt b/third_party/abseil_cpp/absl/base/CMakeLists.txt deleted file mode 100644 index 9ff5aa243ca1..000000000000 --- a/third_party/abseil_cpp/absl/base/CMakeLists.txt +++ /dev/null @@ -1,717 +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. -# - -find_library(LIBRT rt) - -absl_cc_library( - NAME - atomic_hook - HDRS - "internal/atomic_hook.h" - DEPS - absl::config - absl::core_headers - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - errno_saver - HDRS - "internal/errno_saver.h" - DEPS - absl::config - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - log_severity - HDRS - "log_severity.h" - SRCS - "log_severity.cc" - DEPS - absl::core_headers - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - raw_logging_internal - HDRS - "internal/raw_logging.h" - SRCS - "internal/raw_logging.cc" - DEPS - absl::atomic_hook - absl::config - absl::core_headers - absl::log_severity - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - spinlock_wait - HDRS - "internal/spinlock_wait.h" - SRCS - "internal/spinlock_akaros.inc" - "internal/spinlock_linux.inc" - "internal/spinlock_posix.inc" - "internal/spinlock_wait.cc" - "internal/spinlock_win32.inc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base_internal - absl::core_headers - absl::errno_saver -) - -absl_cc_library( - NAME - config - HDRS - "config.h" - "options.h" - "policy_checks.h" - COPTS - ${ABSL_DEFAULT_COPTS} - PUBLIC -) - -absl_cc_library( - NAME - dynamic_annotations - HDRS - "dynamic_annotations.h" - SRCS - "internal/dynamic_annotations.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_library( - NAME - core_headers - HDRS - "attributes.h" - "const_init.h" - "macros.h" - "optimization.h" - "port.h" - "thread_annotations.h" - "internal/thread_annotations.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_library( - NAME - malloc_internal - HDRS - "internal/direct_mmap.h" - "internal/low_level_alloc.h" - SRCS - "internal/low_level_alloc.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::base_internal - absl::config - absl::core_headers - absl::dynamic_annotations - absl::raw_logging_internal - Threads::Threads -) - -absl_cc_library( - NAME - base_internal - HDRS - "internal/hide_ptr.h" - "internal/identity.h" - "internal/inline_variable.h" - "internal/invoke.h" - "internal/scheduling_mode.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::type_traits -) - -absl_cc_library( - NAME - base - HDRS - "call_once.h" - "casts.h" - "internal/cycleclock.h" - "internal/low_level_scheduling.h" - "internal/per_thread_tls.h" - "internal/spinlock.h" - "internal/sysinfo.h" - "internal/thread_identity.h" - "internal/tsan_mutex_interface.h" - "internal/unscaledcycleclock.h" - SRCS - "internal/cycleclock.cc" - "internal/spinlock.cc" - "internal/sysinfo.cc" - "internal/thread_identity.cc" - "internal/unscaledcycleclock.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - $<$<BOOL:${LIBRT}>:-lrt> - $<$<BOOL:${MINGW}>:"advapi32"> - DEPS - absl::atomic_hook - absl::base_internal - absl::config - absl::core_headers - absl::dynamic_annotations - absl::log_severity - absl::raw_logging_internal - absl::spinlock_wait - absl::type_traits - Threads::Threads - PUBLIC -) - -absl_cc_library( - NAME - throw_delegate - HDRS - "internal/throw_delegate.h" - SRCS - "internal/throw_delegate.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal -) - -absl_cc_library( - NAME - exception_testing - HDRS - "internal/exception_testing.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - gtest - TESTONLY -) - -absl_cc_library( - NAME - pretty_function - HDRS - "internal/pretty_function.h" - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - exception_safety_testing - HDRS - "internal/exception_safety_testing.h" - SRCS - "internal/exception_safety_testing.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::config - absl::pretty_function - absl::memory - absl::meta - absl::strings - absl::utility - gtest - TESTONLY -) - -absl_cc_test( - NAME - absl_exception_safety_testing_test - SRCS - "exception_safety_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::exception_safety_testing - absl::memory - gtest_main -) - -absl_cc_library( - NAME - atomic_hook_test_helper - SRCS - "internal/atomic_hook_test_helper.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::atomic_hook - absl::core_headers - TESTONLY -) - -absl_cc_test( - NAME - atomic_hook_test - SRCS - "internal/atomic_hook_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::atomic_hook_test_helper - absl::atomic_hook - absl::core_headers - gmock - gtest_main -) - -absl_cc_test( - NAME - bit_cast_test - SRCS - "bit_cast_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::core_headers - gtest_main -) - -absl_cc_test( - NAME - errno_saver_test - SRCS - "internal/errno_saver_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::errno_saver - absl::strerror - gmock - gtest_main -) - -absl_cc_test( - NAME - throw_delegate_test - SRCS - "throw_delegate_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::config - absl::throw_delegate - gtest_main -) - -absl_cc_test( - NAME - inline_variable_test - SRCS - "internal/inline_variable_testing.h" - "inline_variable_test.cc" - "inline_variable_test_a.cc" - "inline_variable_test_b.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base_internal - gtest_main -) - -absl_cc_test( - NAME - invoke_test - SRCS - "invoke_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base_internal - absl::memory - absl::strings - gmock - gtest_main -) - -absl_cc_library( - NAME - spinlock_test_common - SRCS - "spinlock_test_common.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::config - absl::base_internal - absl::core_headers - absl::synchronization - gtest - TESTONLY -) - -# On bazel BUILD this target use "alwayslink = 1" which is not implemented here -absl_cc_test( - NAME - spinlock_test - SRCS - "spinlock_test_common.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::base_internal - absl::config - absl::core_headers - absl::synchronization - gtest_main -) - -absl_cc_library( - NAME - endian - HDRS - "internal/endian.h" - "internal/unaligned_access.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - PUBLIC -) - -absl_cc_test( - NAME - endian_test - SRCS - "internal/endian_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::config - absl::endian - gtest_main -) - -absl_cc_test( - NAME - config_test - SRCS - "config_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::config - absl::synchronization - gtest_main -) - -absl_cc_test( - NAME - call_once_test - SRCS - "call_once_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::core_headers - absl::synchronization - gtest_main -) - -absl_cc_test( - NAME - raw_logging_test - SRCS - "raw_logging_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::raw_logging_internal - absl::strings - gtest_main -) - -absl_cc_test( - NAME - sysinfo_test - SRCS - "internal/sysinfo_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::synchronization - gtest_main -) - -absl_cc_test( - NAME - low_level_alloc_test - SRCS - "internal/low_level_alloc_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::malloc_internal - absl::node_hash_map - Threads::Threads -) - -absl_cc_test( - NAME - thread_identity_test - SRCS - "internal/thread_identity_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::core_headers - absl::synchronization - Threads::Threads - gtest_main -) - -absl_cc_library( - NAME - bits - HDRS - "internal/bits.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers -) - -absl_cc_test( - NAME - bits_test - SRCS - "internal/bits_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::bits - gtest_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 - 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 - gmock_main -) - -absl_cc_library( - NAME - scoped_set_env - SRCS - "internal/scoped_set_env.cc" - HDRS - "internal/scoped_set_env.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal -) - -absl_cc_test( - NAME - scoped_set_env_test - SRCS - "internal/scoped_set_env_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::scoped_set_env - gtest_main -) - -absl_cc_test( - NAME - cmake_thread_test - SRCS - "internal/cmake_thread_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - 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 -) - -absl_cc_library( - NAME - strerror - SRCS - "internal/strerror.cc" - HDRS - "internal/strerror.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::errno_saver -) - -absl_cc_test( - NAME - strerror_test - SRCS - "internal/strerror_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strerror - absl::strings - gmock - gtest_main -) - -absl_cc_library( - NAME - fast_type_id - HDRS - "internal/fast_type_id.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config -) - -absl_cc_test( - NAME - fast_type_id_test - SRCS - "internal/fast_type_id_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::fast_type_id - gtest_main -) - -absl_cc_test( - NAME - optimization_test - SRCS - "optimization_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::core_headers - absl::optional - gtest_main -) diff --git a/third_party/abseil_cpp/absl/base/attributes.h b/third_party/abseil_cpp/absl/base/attributes.h deleted file mode 100644 index f1d3cfe4d188..000000000000 --- a/third_party/abseil_cpp/absl/base/attributes.h +++ /dev/null @@ -1,683 +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 header file defines macros for declaring attributes for functions, -// types, and variables. -// -// 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. -// -// GCC attributes documentation: -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html -// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html -// -// Most attributes in this file are already supported by GCC 4.7. However, some -// 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). - -#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 -// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a -// nonzero constant integer if the attribute is supported or 0 if not. -// -// It evaluates to zero if `__has_attribute` is not defined by the compiler. -// -// GCC: https://gcc.gnu.org/gcc-5/changes.html -// Clang: https://clang.llvm.org/docs/LanguageExtensions.html -#ifdef __has_attribute -#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) -#else -#define ABSL_HAVE_ATTRIBUTE(x) 0 -#endif - -// ABSL_HAVE_CPP_ATTRIBUTE -// -// A function-like feature checking macro that accepts C++11 style attributes. -// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 -// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't -// find `__has_cpp_attribute`, will evaluate to 0. -#if defined(__cplusplus) && defined(__has_cpp_attribute) -// NOTE: requiring __cplusplus above should not be necessary, but -// works around https://bugs.llvm.org/show_bug.cgi?id=23435. -#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -#else -#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 -#endif - -// ----------------------------------------------------------------------------- -// Function Attributes -// ----------------------------------------------------------------------------- -// -// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -// Clang: https://clang.llvm.org/docs/AttributeReference.html - -// ABSL_PRINTF_ATTRIBUTE -// ABSL_SCANF_ATTRIBUTE -// -// Tells the compiler to perform `printf` format string checking if the -// compiler supports it; see the 'format' attribute in -// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>. -// -// Note: As the GCC manual states, "[s]ince non-static C++ methods -// have an implicit 'this' argument, the arguments of such methods -// should be counted from two, not one." -#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ - __attribute__((__format__(__printf__, string_index, first_to_check))) -#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ - __attribute__((__format__(__scanf__, string_index, first_to_check))) -#else -#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) -#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) -#endif - -// ABSL_ATTRIBUTE_ALWAYS_INLINE -// ABSL_ATTRIBUTE_NOINLINE -// -// Forces functions to either inline or not inline. Introduced in gcc 3.1. -#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 -#else -#define ABSL_ATTRIBUTE_ALWAYS_INLINE -#endif - -#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 -#else -#define ABSL_ATTRIBUTE_NOINLINE -#endif - -// ABSL_ATTRIBUTE_NO_TAIL_CALL -// -// Prevents the compiler from optimizing away stack frames for functions which -// end in a call to another function. -#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__) -#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 -#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ - __attribute__((optimize("no-optimize-sibling-calls"))) -#else -#define ABSL_ATTRIBUTE_NO_TAIL_CALL -#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 -#endif - -// ABSL_ATTRIBUTE_WEAK -// -// Tags a function as weak for the purposes of compilation and linking. -// Weak attributes currently do not work properly in LLVM's Windows backend, -// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 -// for further information. -// The MinGW compiler doesn't complain about the weak attribute until the link -// step, presumably because Windows doesn't use ELF binaries. -#if (ABSL_HAVE_ATTRIBUTE(weak) || \ - (defined(__GNUC__) && !defined(__clang__))) && \ - !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__) -#undef ABSL_ATTRIBUTE_WEAK -#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) -#define ABSL_HAVE_ATTRIBUTE_WEAK 1 -#else -#define ABSL_ATTRIBUTE_WEAK -#define ABSL_HAVE_ATTRIBUTE_WEAK 0 -#endif - -// ABSL_ATTRIBUTE_NONNULL -// -// Tells the compiler either (a) that a particular function parameter -// should be a non-null pointer, or (b) that all pointer arguments should -// be non-null. -// -// Note: As the GCC manual states, "[s]ince non-static C++ methods -// have an implicit 'this' argument, the arguments of such methods -// should be counted from two, not one." -// -// Args are indexed starting at 1. -// -// For non-static class member functions, the implicit `this` argument -// is arg 1, and the first explicit argument is arg 2. For static class member -// functions, there is no implicit `this`, and the first explicit argument is -// arg 1. -// -// Example: -// -// /* arg_a cannot be null, but arg_b can */ -// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); -// -// class C { -// /* arg_a cannot be null, but arg_b can */ -// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); -// -// /* arg_a cannot be null, but arg_b can */ -// static void StaticMethod(void* arg_a, void* arg_b) -// ABSL_ATTRIBUTE_NONNULL(1); -// }; -// -// If no arguments are provided, then all pointer arguments should be non-null. -// -// /* No pointer arguments may be null. */ -// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); -// -// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but -// ABSL_ATTRIBUTE_NONNULL does not. -#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) -#else -#define ABSL_ATTRIBUTE_NONNULL(...) -#endif - -// ABSL_ATTRIBUTE_NORETURN -// -// Tells the compiler that a given function never returns. -#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) -#else -#define ABSL_ATTRIBUTE_NORETURN -#endif - -// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS -// -// Tells the AddressSanitizer (or other memory testing tools) to ignore a given -// function. Useful for cases when a function reads random locations on stack, -// calls _exit from a cloned subprocess, deliberately accesses buffer -// 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) -#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS -#endif - -// 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. -// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. -#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) -#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY -#endif - -// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD -// -// 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) -#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD -#endif - -// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED -// -// Tells the UndefinedSanitizer to ignore a given function. Useful for cases -// 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) -#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ - __attribute__((no_sanitize("undefined"))) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED -#endif - -// ABSL_ATTRIBUTE_NO_SANITIZE_CFI -// -// 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) -#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI -#endif - -// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK -// -// Tells the SafeStack to not instrument a given function. -// See https://clang.llvm.org/docs/SafeStack.html for details. -#if ABSL_HAVE_ATTRIBUTE(no_sanitize) -#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ - __attribute__((no_sanitize("safe-stack"))) -#else -#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK -#endif - -// ABSL_ATTRIBUTE_RETURNS_NONNULL -// -// Tells the compiler that a particular function never returns a null pointer. -#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 -#endif - -// ABSL_HAVE_ATTRIBUTE_SECTION -// -// Indicates whether labeled sections are supported. Weak symbol support is -// a prerequisite. Labeled sections are not supported on Darwin/iOS. -#ifdef ABSL_HAVE_ATTRIBUTE_SECTION -#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set -#elif (ABSL_HAVE_ATTRIBUTE(section) || \ - (defined(__GNUC__) && !defined(__clang__))) && \ - !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK -#define ABSL_HAVE_ATTRIBUTE_SECTION 1 - -// ABSL_ATTRIBUTE_SECTION -// -// Tells the compiler/linker to put a given function into a section and define -// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. -// This functionality is supported by GNU linker. Any function annotated with -// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into -// whatever section its caller is placed into. -// -#ifndef ABSL_ATTRIBUTE_SECTION -#define ABSL_ATTRIBUTE_SECTION(name) \ - __attribute__((section(#name))) __attribute__((noinline)) -#endif - - -// ABSL_ATTRIBUTE_SECTION_VARIABLE -// -// Tells the compiler/linker to put a given variable into a section and define -// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. -// This functionality is supported by GNU linker. -#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE -#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) -#endif - -// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS -// -// A weak section declaration to be used as a global declaration -// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link -// even without functions with ABSL_ATTRIBUTE_SECTION(name). -// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's -// a no-op on ELF but not on Mach-O. -// -#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS -#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ - extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ - extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK -#endif -#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS -#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) -#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) -#endif - -// ABSL_ATTRIBUTE_SECTION_START -// -// Returns `void*` pointers to start/end of a section of code with -// functions having ABSL_ATTRIBUTE_SECTION(name). -// Returns 0 if no such functions exist. -// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and -// link. -// -#define ABSL_ATTRIBUTE_SECTION_START(name) \ - (reinterpret_cast<void *>(__start_##name)) -#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ - (reinterpret_cast<void *>(__stop_##name)) - -#else // !ABSL_HAVE_ATTRIBUTE_SECTION - -#define ABSL_HAVE_ATTRIBUTE_SECTION 0 - -// provide dummy definitions -#define ABSL_ATTRIBUTE_SECTION(name) -#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) -#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) -#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) -#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) -#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0)) -#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0)) - -#endif // ABSL_ATTRIBUTE_SECTION - -// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -// -// Support for aligning the stack on 32-bit x86. -#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ - (defined(__GNUC__) && !defined(__clang__)) -#if defined(__i386__) -#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ - __attribute__((force_align_arg_pointer)) -#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#elif defined(__x86_64__) -#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) -#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#else // !__i386__ && !__x86_64 -#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#endif // __i386__ -#else -#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC -#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) -#endif - -// ABSL_MUST_USE_RESULT -// -// Tells the compiler to warn about unused results. -// -// When annotating a function, it must appear as the first part of the -// declaration or definition. The compiler will warn if the return value from -// such a function is unused: -// -// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); -// AllocateSprocket(); // Triggers a warning. -// -// When annotating a class, it is equivalent to annotating every function which -// returns an instance. -// -// class ABSL_MUST_USE_RESULT Sprocket {}; -// Sprocket(); // Triggers a warning. -// -// Sprocket MakeSprocket(); -// MakeSprocket(); // Triggers a warning. -// -// Note that references and pointers are not instances: -// -// Sprocket* SprocketPointer(); -// SprocketPointer(); // Does *not* trigger a warning. -// -// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result -// warning. For that, warn_unused_result is used only for clang but not for gcc. -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 -// -// Note: past advice was to place the macro after the argument list. -#if ABSL_HAVE_ATTRIBUTE(nodiscard) -#define ABSL_MUST_USE_RESULT [[nodiscard]] -#elif defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) -#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) -#else -#define ABSL_MUST_USE_RESULT -#endif - -// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD -// -// Tells GCC that a function is hot or cold. GCC can use this information to -// improve static analysis, i.e. a conditional branch to a cold function -// is likely to be not-taken. -// This annotation is used for function declarations. -// -// Example: -// -// int foo() ABSL_ATTRIBUTE_HOT; -#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) -#else -#define ABSL_ATTRIBUTE_HOT -#endif - -#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) -#else -#define ABSL_ATTRIBUTE_COLD -#endif - -// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS -// -// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT -// macro used as an attribute to mark functions that must always or never be -// instrumented by XRay. Currently, this is only supported in Clang/LLVM. -// -// For reference on the LLVM XRay instrumentation, see -// http://llvm.org/docs/XRay.html. -// -// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration -// will always get the XRay instrumentation sleds. These sleds may introduce -// some binary size and runtime overhead and must be used sparingly. -// -// These attributes only take effect when the following conditions are met: -// -// * The file/target is built in at least C++11 mode, with a Clang compiler -// that supports XRay attributes. -// * The file/target is built with the -fxray-instrument flag set for the -// Clang/LLVM compiler. -// * The function is defined in the translation unit (the compiler honors the -// attribute in either the definition or the declaration, and must match). -// -// There are cases when, even when building with XRay instrumentation, users -// might want to control specifically which functions are instrumented for a -// particular build using special-case lists provided to the compiler. These -// special case lists are provided to Clang via the -// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The -// attributes in source take precedence over these special-case lists. -// -// To disable the XRay attributes at build-time, users may define -// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific -// 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__) -#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) -#define ABSL_XRAY_LOG_ARGS(N) \ - [[clang::xray_always_instrument, clang::xray_log_args(N)]] -#else -#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] -#endif -#else -#define ABSL_XRAY_ALWAYS_INSTRUMENT -#define ABSL_XRAY_NEVER_INSTRUMENT -#define ABSL_XRAY_LOG_ARGS(N) -#endif - -// ABSL_ATTRIBUTE_REINITIALIZES -// -// Indicates that a member function reinitializes the entire object to a known -// state, independent of the previous state of the object. -// -// The clang-tidy check bugprone-use-after-move allows member functions marked -// with this attribute to be called on objects that have been moved from; -// without the attribute, this would result in a use-after-move warning. -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) -#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] -#else -#define ABSL_ATTRIBUTE_REINITIALIZES -#endif - -// ----------------------------------------------------------------------------- -// Variable Attributes -// ----------------------------------------------------------------------------- - -// ABSL_ATTRIBUTE_UNUSED -// -// Prevents the compiler from complaining about variables that appear unused. -#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) -#undef ABSL_ATTRIBUTE_UNUSED -#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) -#else -#define ABSL_ATTRIBUTE_UNUSED -#endif - -// ABSL_ATTRIBUTE_INITIAL_EXEC -// -// Tells the compiler to use "initial-exec" mode for a thread-local variable. -// See http://people.redhat.com/drepper/tls.pdf for the gory details. -#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) -#else -#define ABSL_ATTRIBUTE_INITIAL_EXEC -#endif - -// ABSL_ATTRIBUTE_PACKED -// -// Instructs the compiler not to use natural alignment for a tagged data -// structure, but instead to reduce its alignment to 1. This attribute can -// either be applied to members of a structure or to a structure in its -// entirety. Applying this attribute (judiciously) to a structure in its -// entirety to optimize the memory footprint of very commonly-used structs is -// fine. Do not apply this attribute to a structure in its entirety if the -// purpose is to control the offsets of the members in the structure. Instead, -// apply this attribute only to structure members that need it. -// -// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the -// natural alignment of structure members not annotated is preserved. Aligned -// member accesses are faster than non-aligned member accesses even if the -// targeted microprocessor supports non-aligned accesses. -#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) -#else -#define ABSL_ATTRIBUTE_PACKED -#endif - -// ABSL_ATTRIBUTE_FUNC_ALIGN -// -// Tells the compiler to align the function start at least to certain -// alignment boundary -#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) -#else -#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) -#endif - -// ABSL_FALLTHROUGH_INTENDED -// -// Annotates implicit fall-through between switch labels, allowing a case to -// indicate intentional fallthrough and turn off warnings about any lack of a -// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by -// a semicolon and can be used in most places where `break` can, provided that -// no statements exist between it and the next switch label. -// -// Example: -// -// switch (x) { -// case 40: -// case 41: -// if (truth_is_out_there) { -// ++x; -// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations -// // in comments -// } else { -// return x; -// } -// case 42: -// ... -// -// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED -// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed -// when performing switch labels fall-through diagnostic -// (`-Wimplicit-fallthrough`). See clang documentation on language extensions -// for details: -// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough -// -// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro -// has no effect on diagnostics. In any case this macro has no effect on runtime -// behavior and performance of code. - -#ifdef ABSL_FALLTHROUGH_INTENDED -#error "ABSL_FALLTHROUGH_INTENDED should not be defined." -#endif - -// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported. -#if defined(__clang__) && defined(__has_warning) -#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") -#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] -#endif -#elif defined(__GNUC__) && __GNUC__ >= 7 -#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] -#endif - -#ifndef ABSL_FALLTHROUGH_INTENDED -#define ABSL_FALLTHROUGH_INTENDED \ - do { \ - } while (0) -#endif - -// ABSL_DEPRECATED() -// -// Marks a deprecated class, struct, enum, function, method and variable -// declarations. The macro argument is used as a custom diagnostic message (e.g. -// suggestion of a better alternative). -// -// Examples: -// -// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; -// -// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} -// -// template <typename T> -// ABSL_DEPRECATED("Use DoThat() instead") -// void DoThis(); -// -// Every usage of a deprecated entity will trigger a warning when compiled with -// clang's `-Wdeprecated-declarations` option. This option is turned off by -// default, but the warnings will be reported by clang-tidy. -#if defined(__clang__) && __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 -// not compile (on supported platforms) unless the variable has a constant -// initializer. This is useful for variables with static and thread storage -// duration, because it guarantees that they will not suffer from the so-called -// "static init order fiasco". Prefer to put this attribute on the most visible -// declaration of the variable, if there's more than one, because code that -// accesses the variable can then use the attribute for optimization. -// -// Example: -// -// class MyClass { -// public: -// ABSL_CONST_INIT static MyType my_var; -// }; -// -// MyType MyClass::my_var = MakeMyType(...); -// -// Note that this attribute is redundant if the variable is declared constexpr. -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) -#define ABSL_CONST_INIT [[clang::require_constant_initialization]] -#else -#define ABSL_CONST_INIT -#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) - -#endif // ABSL_BASE_ATTRIBUTES_H_ diff --git a/third_party/abseil_cpp/absl/base/bit_cast_test.cc b/third_party/abseil_cpp/absl/base/bit_cast_test.cc deleted file mode 100644 index 8a3a41ea0231..000000000000 --- a/third_party/abseil_cpp/absl/base/bit_cast_test.cc +++ /dev/null @@ -1,109 +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. - -// Unit test for bit_cast template. - -#include <cstdint> -#include <cstring> - -#include "gtest/gtest.h" -#include "absl/base/casts.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -template <int N> -struct marshall { char buf[N]; }; - -template <typename T> -void TestMarshall(const T values[], int num_values) { - for (int i = 0; i < num_values; ++i) { - T t0 = values[i]; - marshall<sizeof(T)> m0 = absl::bit_cast<marshall<sizeof(T)> >(t0); - T t1 = absl::bit_cast<T>(m0); - marshall<sizeof(T)> m1 = absl::bit_cast<marshall<sizeof(T)> >(t1); - ASSERT_EQ(0, memcmp(&t0, &t1, sizeof(T))); - ASSERT_EQ(0, memcmp(&m0, &m1, sizeof(T))); - } -} - -// Convert back and forth to an integral type. The C++ standard does -// not guarantee this will work, but we test that this works on all the -// platforms we support. -// -// Likewise, we below make assumptions about sizeof(float) and -// sizeof(double) which the standard does not guarantee, but which hold on the -// platforms we support. - -template <typename T, typename I> -void TestIntegral(const T values[], int num_values) { - for (int i = 0; i < num_values; ++i) { - T t0 = values[i]; - I i0 = absl::bit_cast<I>(t0); - T t1 = absl::bit_cast<T>(i0); - I i1 = absl::bit_cast<I>(t1); - ASSERT_EQ(0, memcmp(&t0, &t1, sizeof(T))); - ASSERT_EQ(i0, i1); - } -} - -TEST(BitCast, Bool) { - static const bool bool_list[] = { false, true }; - TestMarshall<bool>(bool_list, ABSL_ARRAYSIZE(bool_list)); -} - -TEST(BitCast, Int32) { - static const int32_t int_list[] = - { 0, 1, 100, 2147483647, -1, -100, -2147483647, -2147483647-1 }; - TestMarshall<int32_t>(int_list, ABSL_ARRAYSIZE(int_list)); -} - -TEST(BitCast, Int64) { - static const int64_t int64_list[] = - { 0, 1, 1LL << 40, -1, -(1LL<<40) }; - TestMarshall<int64_t>(int64_list, ABSL_ARRAYSIZE(int64_list)); -} - -TEST(BitCast, Uint64) { - static const uint64_t uint64_list[] = - { 0, 1, 1LLU << 40, 1LLU << 63 }; - TestMarshall<uint64_t>(uint64_list, ABSL_ARRAYSIZE(uint64_list)); -} - -TEST(BitCast, Float) { - static const float float_list[] = - { 0.0f, 1.0f, -1.0f, 10.0f, -10.0f, - 1e10f, 1e20f, 1e-10f, 1e-20f, - 2.71828f, 3.14159f }; - TestMarshall<float>(float_list, ABSL_ARRAYSIZE(float_list)); - TestIntegral<float, int>(float_list, ABSL_ARRAYSIZE(float_list)); - TestIntegral<float, unsigned>(float_list, ABSL_ARRAYSIZE(float_list)); -} - -TEST(BitCast, Double) { - static const double double_list[] = - { 0.0, 1.0, -1.0, 10.0, -10.0, - 1e10, 1e100, 1e-10, 1e-100, - 2.718281828459045, - 3.141592653589793238462643383279502884197169399375105820974944 }; - TestMarshall<double>(double_list, ABSL_ARRAYSIZE(double_list)); - TestIntegral<double, int64_t>(double_list, ABSL_ARRAYSIZE(double_list)); - TestIntegral<double, uint64_t>(double_list, ABSL_ARRAYSIZE(double_list)); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/call_once.h b/third_party/abseil_cpp/absl/base/call_once.h deleted file mode 100644 index 5b468af855f1..000000000000 --- a/third_party/abseil_cpp/absl/base/call_once.h +++ /dev/null @@ -1,226 +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. -// -// ----------------------------------------------------------------------------- -// File: call_once.h -// ----------------------------------------------------------------------------- -// -// This header file provides an Abseil version of `std::call_once` for invoking -// a given function at most once, across all threads. This Abseil version is -// faster than the C++11 version and incorporates the C++17 argument-passing -// fix, so that (for example) non-const references may be passed to the invoked -// function. - -#ifndef ABSL_BASE_CALL_ONCE_H_ -#define ABSL_BASE_CALL_ONCE_H_ - -#include <algorithm> -#include <atomic> -#include <cstdint> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/invoke.h" -#include "absl/base/internal/low_level_scheduling.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/scheduling_mode.h" -#include "absl/base/internal/spinlock_wait.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class once_flag; - -namespace base_internal { -std::atomic<uint32_t>* ControlWord(absl::once_flag* flag); -} // namespace base_internal - -// call_once() -// -// For all invocations using a given `once_flag`, invokes a given `fn` exactly -// once across all threads. The first call to `call_once()` with a particular -// `once_flag` argument (that does not throw an exception) will run the -// specified function with the provided `args`; other calls with the same -// `once_flag` argument will not run the function, but will wait -// for the provided function to finish running (if it is still running). -// -// This mechanism provides a safe, simple, and fast mechanism for one-time -// initialization in a multi-threaded process. -// -// Example: -// -// class MyInitClass { -// public: -// ... -// mutable absl::once_flag once_; -// -// MyInitClass* init() const { -// absl::call_once(once_, &MyInitClass::Init, this); -// return ptr_; -// } -// -template <typename Callable, typename... Args> -void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args); - -// once_flag -// -// Objects of this type are used to distinguish calls to `call_once()` and -// ensure the provided function is only invoked once across all threads. This -// type is not copyable or movable. However, it has a `constexpr` -// constructor, and is safe to use as a namespace-scoped global variable. -class once_flag { - public: - constexpr once_flag() : control_(0) {} - once_flag(const once_flag&) = delete; - once_flag& operator=(const once_flag&) = delete; - - private: - friend std::atomic<uint32_t>* base_internal::ControlWord(once_flag* flag); - std::atomic<uint32_t> control_; -}; - -//------------------------------------------------------------------------------ -// End of public interfaces. -// Implementation details follow. -//------------------------------------------------------------------------------ - -namespace base_internal { - -// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to -// initialize entities used by the scheduler implementation. -template <typename Callable, typename... Args> -void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args); - -// Disables scheduling while on stack when scheduling mode is non-cooperative. -// No effect for cooperative scheduling modes. -class SchedulingHelper { - public: - explicit SchedulingHelper(base_internal::SchedulingMode mode) : mode_(mode) { - if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) { - guard_result_ = base_internal::SchedulingGuard::DisableRescheduling(); - } - } - - ~SchedulingHelper() { - if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) { - base_internal::SchedulingGuard::EnableRescheduling(guard_result_); - } - } - - private: - base_internal::SchedulingMode mode_; - bool guard_result_; -}; - -// Bit patterns for call_once state machine values. Internal implementation -// detail, not for use by clients. -// -// The bit patterns are arbitrarily chosen from unlikely values, to aid in -// debugging. However, kOnceInit must be 0, so that a zero-initialized -// once_flag will be valid for immediate use. -enum { - kOnceInit = 0, - kOnceRunning = 0x65C2937B, - kOnceWaiter = 0x05A308D2, - // A very small constant is chosen for kOnceDone so that it fit in a single - // compare with immediate instruction for most common ISAs. This is verified - // for x86, POWER and ARM. - kOnceDone = 221, // Random Number -}; - -template <typename Callable, typename... Args> -ABSL_ATTRIBUTE_NOINLINE -void CallOnceImpl(std::atomic<uint32_t>* control, - base_internal::SchedulingMode scheduling_mode, Callable&& fn, - Args&&... args) { -#ifndef NDEBUG - { - uint32_t old_control = control->load(std::memory_order_relaxed); - if (old_control != kOnceInit && - old_control != kOnceRunning && - old_control != kOnceWaiter && - old_control != kOnceDone) { - ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx", - static_cast<unsigned long>(old_control)); // NOLINT - } - } -#endif // NDEBUG - static const base_internal::SpinLockWaitTransition trans[] = { - {kOnceInit, kOnceRunning, true}, - {kOnceRunning, kOnceWaiter, false}, - {kOnceDone, kOnceDone, true}}; - - // Must do this before potentially modifying control word's state. - base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode); - // Short circuit the simplest case to avoid procedure call overhead. - // The base_internal::SpinLockWait() call returns either kOnceInit or - // kOnceDone. If it returns kOnceDone, it must have loaded the control word - // with std::memory_order_acquire and seen a value of kOnceDone. - uint32_t old_control = kOnceInit; - if (control->compare_exchange_strong(old_control, kOnceRunning, - std::memory_order_relaxed) || - base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans, - scheduling_mode) == kOnceInit) { - base_internal::invoke(std::forward<Callable>(fn), - std::forward<Args>(args)...); - // 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); - } - } // else *control is already kOnceDone -} - -inline std::atomic<uint32_t>* ControlWord(once_flag* flag) { - return &flag->control_; -} - -template <typename Callable, typename... Args> -void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args) { - std::atomic<uint32_t>* once = base_internal::ControlWord(flag); - uint32_t s = once->load(std::memory_order_acquire); - if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) { - base_internal::CallOnceImpl(once, base_internal::SCHEDULE_KERNEL_ONLY, - std::forward<Callable>(fn), - std::forward<Args>(args)...); - } -} - -} // namespace base_internal - -template <typename Callable, typename... Args> -void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) { - std::atomic<uint32_t>* once = base_internal::ControlWord(&flag); - uint32_t s = once->load(std::memory_order_acquire); - if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) { - base_internal::CallOnceImpl( - once, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL, - std::forward<Callable>(fn), std::forward<Args>(args)...); - } -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_CALL_ONCE_H_ diff --git a/third_party/abseil_cpp/absl/base/call_once_test.cc b/third_party/abseil_cpp/absl/base/call_once_test.cc deleted file mode 100644 index 11d26c44d1a4..000000000000 --- a/third_party/abseil_cpp/absl/base/call_once_test.cc +++ /dev/null @@ -1,107 +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/base/call_once.h" - -#include <thread> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/const_init.h" -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -absl::once_flag once; - -ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit); - -int running_thread_count ABSL_GUARDED_BY(counters_mu) = 0; -int call_once_invoke_count ABSL_GUARDED_BY(counters_mu) = 0; -int call_once_finished_count ABSL_GUARDED_BY(counters_mu) = 0; -int call_once_return_count ABSL_GUARDED_BY(counters_mu) = 0; -bool done_blocking ABSL_GUARDED_BY(counters_mu) = false; - -// Function to be called from absl::call_once. Waits for a notification. -void WaitAndIncrement() { - counters_mu.Lock(); - ++call_once_invoke_count; - counters_mu.Unlock(); - - counters_mu.LockWhen(Condition(&done_blocking)); - ++call_once_finished_count; - counters_mu.Unlock(); -} - -void ThreadBody() { - counters_mu.Lock(); - ++running_thread_count; - counters_mu.Unlock(); - - absl::call_once(once, WaitAndIncrement); - - counters_mu.Lock(); - ++call_once_return_count; - counters_mu.Unlock(); -} - -// Returns true if all threads are set up for the test. -bool ThreadsAreSetup(void*) ABSL_EXCLUSIVE_LOCKS_REQUIRED(counters_mu) { - // All ten threads must be running, and WaitAndIncrement should be blocked. - return running_thread_count == 10 && call_once_invoke_count == 1; -} - -TEST(CallOnceTest, ExecutionCount) { - std::vector<std::thread> threads; - - // Start 10 threads all calling call_once on the same once_flag. - for (int i = 0; i < 10; ++i) { - threads.emplace_back(ThreadBody); - } - - - // Wait until all ten threads have started, and WaitAndIncrement has been - // invoked. - counters_mu.LockWhen(Condition(ThreadsAreSetup, nullptr)); - - // WaitAndIncrement should have been invoked by exactly one call_once() - // instance. That thread should be blocking on a notification, and all other - // call_once instances should be blocking as well. - EXPECT_EQ(call_once_invoke_count, 1); - EXPECT_EQ(call_once_finished_count, 0); - EXPECT_EQ(call_once_return_count, 0); - - // Allow WaitAndIncrement to finish executing. Once it does, the other - // call_once waiters will be unblocked. - done_blocking = true; - counters_mu.Unlock(); - - for (std::thread& thread : threads) { - thread.join(); - } - - counters_mu.Lock(); - EXPECT_EQ(call_once_invoke_count, 1); - EXPECT_EQ(call_once_finished_count, 1); - EXPECT_EQ(call_once_return_count, 10); - counters_mu.Unlock(); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/casts.h b/third_party/abseil_cpp/absl/base/casts.h deleted file mode 100644 index 83c691265ff3..000000000000 --- a/third_party/abseil_cpp/absl/base/casts.h +++ /dev/null @@ -1,187 +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. -// -// ----------------------------------------------------------------------------- -// File: casts.h -// ----------------------------------------------------------------------------- -// -// This header file defines casting templates to fit use cases not covered by -// the standard casts provided in the C++ standard. As with all cast operations, -// use these with caution and only if alternatives do not exist. - -#ifndef ABSL_BASE_CASTS_H_ -#define ABSL_BASE_CASTS_H_ - -#include <cstring> -#include <memory> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/identity.h" -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace internal_casts { - -template <class Dest, class Source> -struct is_bitcastable - : std::integral_constant< - bool, - sizeof(Dest) == sizeof(Source) && - type_traits_internal::is_trivially_copyable<Source>::value && - type_traits_internal::is_trivially_copyable<Dest>::value && - std::is_default_constructible<Dest>::value> {}; - -} // namespace internal_casts - -// implicit_cast() -// -// Performs an implicit conversion between types following the language -// rules for implicit conversion; if an implicit conversion is otherwise -// allowed by the language in the given context, this function performs such an -// implicit conversion. -// -// Example: -// -// // If the context allows implicit conversion: -// From from; -// To to = from; -// -// // Such code can be replaced by: -// implicit_cast<To>(from); -// -// An `implicit_cast()` may also be used to annotate numeric type conversions -// that, although safe, may produce compiler warnings (such as `long` to `int`). -// Additionally, an `implicit_cast()` is also useful within return statements to -// indicate a specific implicit conversion is being undertaken. -// -// Example: -// -// return implicit_cast<double>(size_in_bytes) / capacity_; -// -// Annotating code with `implicit_cast()` allows you to explicitly select -// particular overloads and template instantiations, while providing a safer -// cast than `reinterpret_cast()` or `static_cast()`. -// -// Additionally, an `implicit_cast()` can be used to allow upcasting within a -// type hierarchy where incorrect use of `static_cast()` could accidentally -// allow downcasting. -// -// Finally, an `implicit_cast()` can be used to perform implicit conversions -// from unrelated types that otherwise couldn't be implicitly cast directly; -// C++ will normally only implicitly cast "one step" in such conversions. -// -// That is, if C is a type which can be implicitly converted to B, with B being -// a type that can be implicitly converted to A, an `implicit_cast()` can be -// used to convert C to B (which the compiler can then implicitly convert to A -// using language rules). -// -// Example: -// -// // Assume an object C is convertible to B, which is implicitly convertible -// // to A -// A a = implicit_cast<B>(C); -// -// Such implicit cast chaining may be useful within template logic. -template <typename To> -constexpr To implicit_cast(typename absl::internal::identity_t<To> to) { - return to; -} - -// bit_cast() -// -// Performs a bitwise cast on a type without changing the underlying bit -// representation of that type's value. The two types must be of the same size -// and both types must be trivially copyable. As with most casts, use with -// caution. A `bit_cast()` might be needed when you need to temporarily treat a -// type as some other type, such as in the following cases: -// -// * Serialization (casting temporarily to `char *` for those purposes is -// always allowed by the C++ standard) -// * Managing the individual bits of a type within mathematical operations -// that are not normally accessible through that type -// * Casting non-pointer types to pointer types (casting the other way is -// allowed by `reinterpret_cast()` but round-trips cannot occur the other -// way). -// -// Example: -// -// float f = 3.14159265358979; -// int i = bit_cast<int32_t>(f); -// // i = 0x40490fdb -// -// Casting non-pointer types to pointer types and then dereferencing them -// traditionally produces undefined behavior. -// -// Example: -// -// // WRONG -// float f = 3.14159265358979; // WRONG -// int i = * reinterpret_cast<int*>(&f); // WRONG -// -// The address-casting method produces undefined behavior according to the ISO -// C++ specification section [basic.lval]. Roughly, this section says: if an -// object in memory has one type, and a program accesses it with a different -// type, the result is undefined behavior for most values of "different type". -// -// Such casting results in type punning: holding an object in memory of one type -// and reading its bits back using a different type. A `bit_cast()` avoids this -// issue by implementing its casts using `memcpy()`, which avoids introducing -// this undefined behavior. -// -// NOTE: The requirements here are more strict than the bit_cast of standard -// proposal p0476 due to the need for workarounds and lack of intrinsics. -// Specifically, this implementation also requires `Dest` to be -// default-constructible. -template < - typename Dest, typename Source, - typename std::enable_if<internal_casts::is_bitcastable<Dest, Source>::value, - int>::type = 0> -inline Dest bit_cast(const Source& source) { - Dest dest; - memcpy(static_cast<void*>(std::addressof(dest)), - static_cast<const void*>(std::addressof(source)), sizeof(dest)); - 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. -template < - typename Dest, typename Source, - typename std::enable_if< - !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.") -inline Dest bit_cast(const Source& source) { - static_assert(sizeof(Dest) == sizeof(Source), - "Source and destination types should have equal sizes."); - - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_CASTS_H_ diff --git a/third_party/abseil_cpp/absl/base/config.h b/third_party/abseil_cpp/absl/base/config.h deleted file mode 100644 index 3f7f32b9e6e3..000000000000 --- a/third_party/abseil_cpp/absl/base/config.h +++ /dev/null @@ -1,714 +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. -// -// ----------------------------------------------------------------------------- -// File: config.h -// ----------------------------------------------------------------------------- -// -// This header file defines a set of macros for checking the presence of -// important compiler and platform features. Such macros can be used to -// produce portable code by parameterizing compilation based on the presence or -// lack of a given feature. -// -// We define a "feature" as some interface we wish to program to: for example, -// a library function or system call. A value of `1` indicates support for -// that feature; any other value indicates the feature support is undefined. -// -// Example: -// -// Suppose a programmer wants to write a program that uses the 'mmap()' system -// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to -// selectively include the `mmap.h` header and bracket code using that feature -// in the macro: -// -// #include "absl/base/config.h" -// -// #ifdef ABSL_HAVE_MMAP -// #include "sys/mman.h" -// #endif //ABSL_HAVE_MMAP -// -// ... -// #ifdef ABSL_HAVE_MMAP -// void *ptr = mmap(...); -// ... -// #endif // ABSL_HAVE_MMAP - -#ifndef ABSL_BASE_CONFIG_H_ -#define ABSL_BASE_CONFIG_H_ - -// Included for the __GLIBC__ macro (or similar macros on other systems). -#include <limits.h> - -#ifdef __cplusplus -// Included for __GLIBCXX__, _LIBCPP_VERSION -#include <cstddef> -#endif // __cplusplus - -#if defined(__APPLE__) -// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, -// __IPHONE_8_0. -#include <Availability.h> -#include <TargetConditionals.h> -#endif - -#include "absl/base/options.h" -#include "absl/base/policy_checks.h" - -// Helper macro to convert a CPP variable to a string literal. -#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x -#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x) - -// ----------------------------------------------------------------------------- -// Abseil namespace annotations -// ----------------------------------------------------------------------------- - -// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END -// -// An annotation placed at the beginning/end of each `namespace absl` scope. -// This is used to inject an inline namespace. -// -// The proper way to write Abseil code in the `absl` namespace is: -// -// namespace absl { -// ABSL_NAMESPACE_BEGIN -// -// void Foo(); // absl::Foo(). -// -// ABSL_NAMESPACE_END -// } // namespace absl -// -// Users of Abseil should not use these macros, because users of Abseil should -// not write `namespace absl {` in their own code for any reason. (Abseil does -// not support forward declarations of its own types, nor does it support -// user-provided specialization of Abseil templates. Code that violates these -// rules may be broken without warning.) -#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \ - !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME) -#error options.h is misconfigured. -#endif - -// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" -#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1 - -#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \ - ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) - -static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', - "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " - "not be empty."); -static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || - ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' || - ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' || - ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' || - ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0', - "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must " - "be changed to a new, unique identifier name."); - -#endif - -#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 -#define ABSL_NAMESPACE_BEGIN -#define ABSL_NAMESPACE_END -#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1 -#define ABSL_NAMESPACE_BEGIN \ - inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME { -#define ABSL_NAMESPACE_END } -#else -#error options.h is misconfigured. -#endif - -// ----------------------------------------------------------------------------- -// Compiler Feature Checks -// ----------------------------------------------------------------------------- - -// ABSL_HAVE_BUILTIN() -// -// Checks whether the compiler supports a Clang Feature Checking Macro, and if -// so, checks whether it supports the provided builtin function "x" where x -// is one of the functions noted in -// https://clang.llvm.org/docs/LanguageExtensions.html -// -// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. -// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html -#ifdef __has_builtin -#define ABSL_HAVE_BUILTIN(x) __has_builtin(x) -#else -#define ABSL_HAVE_BUILTIN(x) 0 -#endif - -#if defined(__is_identifier) -#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x)) -#else -#define ABSL_INTERNAL_HAS_KEYWORD(x) 0 -#endif - -#ifdef __has_feature -#define ABSL_HAVE_FEATURE(f) __has_feature(f) -#else -#define ABSL_HAVE_FEATURE(f) 0 -#endif - -// ABSL_HAVE_TLS is defined to 1 when __thread should be supported. -// We assume __thread is supported on Linux when compiled with Clang or compiled -// against libstdc++ with _GLIBCXX_HAVE_TLS defined. -#ifdef ABSL_HAVE_TLS -#error ABSL_HAVE_TLS cannot be directly set -#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS)) -#define ABSL_HAVE_TLS 1 -#endif - -// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE -// -// Checks whether `std::is_trivially_destructible<T>` is supported. -// -// Notes: All supported compilers using libc++ support this feature, as does -// 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(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \ - defined(_MSC_VER) -#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1 -#endif - -// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE -// -// Checks whether `std::is_trivially_default_constructible<T>` and -// `std::is_trivially_copy_constructible<T>` are supported. - -// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE -// -// Checks whether `std::is_trivially_copy_assignable<T>` is supported. - -// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with -// either libc++ or libstdc++, and Visual Studio (but not NVCC). -#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) -#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set -#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE) -#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set -#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \ - (!defined(__clang__) && defined(__GNUC__) && \ - (__GNUC__ > 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 -#endif - -// ABSL_HAVE_SOURCE_LOCATION_CURRENT -// -// Indicates whether `absl::SourceLocation::current()` will return useful -// information in some contexts. -#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT -#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \ - ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE) -#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1 -#endif -#endif - -// ABSL_HAVE_THREAD_LOCAL -// -// Checks whether C++11's `thread_local` storage duration specifier is -// supported. -#ifdef ABSL_HAVE_THREAD_LOCAL -#error ABSL_HAVE_THREAD_LOCAL cannot be directly set -#elif defined(__APPLE__) -// Notes: -// * Xcode's clang did not support `thread_local` until version 8, and -// even then not for all iOS < 9.0. -// * 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. -// -#if ABSL_HAVE_FEATURE(cxx_thread_local) && \ - !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) -#define ABSL_HAVE_THREAD_LOCAL 1 -#endif -#else // !defined(__APPLE__) -#define ABSL_HAVE_THREAD_LOCAL 1 -#endif - -// There are platforms for which TLS should not be used even though the compiler -// makes it seem like it's supported (Android NDK < r12b for example). -// This is primarily because of linker problems and toolchain misconfiguration: -// Abseil does not intend to support this indefinitely. Currently, the newest -// toolchain that we intend to support that requires this behavior is the -// r11 NDK - allowing for a 5 year support window on that means this option -// is likely to be removed around June of 2021. -// TLS isn't supported until NDK r12b per -// https://developer.android.com/ndk/downloads/revision_history.html -// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in -// <android/ndk-version.h>. For NDK < r16, users should define these macros, -// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11. -#if defined(__ANDROID__) && defined(__clang__) -#if __has_include(<android/ndk-version.h>) -#include <android/ndk-version.h> -#endif // __has_include(<android/ndk-version.h>) -#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ - defined(__NDK_MINOR__) && \ - ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) -#undef ABSL_HAVE_TLS -#undef ABSL_HAVE_THREAD_LOCAL -#endif -#endif // defined(__ANDROID__) && defined(__clang__) - -// ABSL_HAVE_INTRINSIC_INT128 -// -// Checks whether the __int128 compiler extension for a 128-bit integral type is -// supported. -// -// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is -// supported, but we avoid using it in certain cases: -// * On Clang: -// * Building using Clang for Windows, where the Clang runtime library has -// 128-bit support only on LP64 architectures, but Windows is LLP64. -// * On Nvidia's nvcc: -// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions -// actually support __int128. -#ifdef ABSL_HAVE_INTRINSIC_INT128 -#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set -#elif defined(__SIZEOF_INT128__) -#if (defined(__clang__) && !defined(_WIN32)) || \ - (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ - (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) -#define ABSL_HAVE_INTRINSIC_INT128 1 -#elif defined(__CUDACC__) -// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a -// string explaining that it has been removed starting with CUDA 9. We use -// nested #ifs because there is no short-circuiting in the preprocessor. -// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined. -#if __CUDACC_VER__ >= 70000 -#define ABSL_HAVE_INTRINSIC_INT128 1 -#endif // __CUDACC_VER__ >= 70000 -#endif // defined(__CUDACC__) -#endif // ABSL_HAVE_INTRINSIC_INT128 - -// ABSL_HAVE_EXCEPTIONS -// -// Checks whether the compiler both supports and enables exceptions. Many -// compilers support a "no exceptions" mode that disables exceptions. -// -// Generally, when ABSL_HAVE_EXCEPTIONS is not defined: -// -// * Code using `throw` and `try` may not compile. -// * The `noexcept` specifier will still compile and behave as normal. -// * The `noexcept` operator may still return `false`. -// -// For further details, consult the compiler's documentation. -#ifdef ABSL_HAVE_EXCEPTIONS -#error ABSL_HAVE_EXCEPTIONS cannot be directly set. - -#elif defined(__clang__) - -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) -// Clang >= 3.6 -#if ABSL_HAVE_FEATURE(cxx_exceptions) -#define ABSL_HAVE_EXCEPTIONS 1 -#endif // ABSL_HAVE_FEATURE(cxx_exceptions) -#else -// Clang < 3.6 -// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro -#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) -#define ABSL_HAVE_EXCEPTIONS 1 -#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions) -#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) - -// Handle remaining special cases and default to exceptions being supported. -#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \ - !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \ - !(defined(_MSC_VER) && !defined(_CPPUNWIND)) -#define ABSL_HAVE_EXCEPTIONS 1 -#endif - -// ----------------------------------------------------------------------------- -// Platform Feature Checks -// ----------------------------------------------------------------------------- - -// Currently supported operating systems and associated preprocessor -// symbols: -// -// Linux and Linux-derived __linux__ -// Android __ANDROID__ (implies __linux__) -// Linux (non-Android) __linux__ && !__ANDROID__ -// Darwin (macOS and iOS) __APPLE__ -// Akaros (http://akaros.org) __ros__ -// Windows _WIN32 -// NaCL __native_client__ -// AsmJS __asmjs__ -// WebAssembly __wasm__ -// Fuchsia __Fuchsia__ -// -// Note that since Android defines both __ANDROID__ and __linux__, one -// may probe for either Linux or Android by simply testing for __linux__. - -// ABSL_HAVE_MMAP -// -// Checks whether the platform has an mmap(2) implementation as defined in -// POSIX.1-2001. -#ifdef ABSL_HAVE_MMAP -#error ABSL_HAVE_MMAP cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ - defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ - defined(__ASYLO__) || defined(__myriad2__) -#define ABSL_HAVE_MMAP 1 -#endif - -// ABSL_HAVE_PTHREAD_GETSCHEDPARAM -// -// Checks whether the platform implements the pthread_(get|set)schedparam(3) -// functions as defined in POSIX.1-2001. -#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM -#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) -#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 -#endif - -// ABSL_HAVE_SCHED_YIELD -// -// Checks whether the platform implements sched_yield(2) as defined in -// POSIX.1-2001. -#ifdef ABSL_HAVE_SCHED_YIELD -#error ABSL_HAVE_SCHED_YIELD cannot be directly set -#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) -#define ABSL_HAVE_SCHED_YIELD 1 -#endif - -// ABSL_HAVE_SEMAPHORE_H -// -// Checks whether the platform supports the <semaphore.h> header and sem_init(3) -// family of functions as standardized in POSIX.1-2001. -// -// Note: While Apple provides <semaphore.h> for both iOS and macOS, it is -// explicitly deprecated and will cause build failures if enabled for those -// platforms. We side-step the issue by not defining it here for Apple -// platforms. -#ifdef ABSL_HAVE_SEMAPHORE_H -#error ABSL_HAVE_SEMAPHORE_H cannot be directly set -#elif defined(__linux__) || defined(__ros__) -#define ABSL_HAVE_SEMAPHORE_H 1 -#endif - -// ABSL_HAVE_ALARM -// -// Checks whether the platform supports the <signal.h> header and alarm(2) -// function as standardized in POSIX.1-2001. -#ifdef ABSL_HAVE_ALARM -#error ABSL_HAVE_ALARM cannot be directly set -#elif defined(__GOOGLE_GRTE_VERSION__) -// feature tests for Google's GRTE -#define ABSL_HAVE_ALARM 1 -#elif defined(__GLIBC__) -// feature test for glibc -#define ABSL_HAVE_ALARM 1 -#elif defined(_MSC_VER) -// feature tests for Microsoft's library -#elif defined(__MINGW32__) -// mingw32 doesn't provide alarm(2): -// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h -// mingw-w64 provides a no-op implementation: -// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c -#elif defined(__EMSCRIPTEN__) -// emscripten doesn't support signals -#elif defined(__Fuchsia__) -// Signals don't exist on fuchsia. -#elif defined(__native_client__) -#else -// other standard libraries -#define ABSL_HAVE_ALARM 1 -#endif - -// ABSL_IS_LITTLE_ENDIAN -// ABSL_IS_BIG_ENDIAN -// -// Checks the endianness of the platform. -// -// Notes: uses the built in endian macros provided by GCC (since 4.6) and -// Clang (since 3.2); see -// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. -// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error. -#if defined(ABSL_IS_BIG_ENDIAN) -#error "ABSL_IS_BIG_ENDIAN cannot be directly set." -#endif -#if defined(ABSL_IS_LITTLE_ENDIAN) -#error "ABSL_IS_LITTLE_ENDIAN cannot be directly set." -#endif - -#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define ABSL_IS_LITTLE_ENDIAN 1 -#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define ABSL_IS_BIG_ENDIAN 1 -#elif defined(_WIN32) -#define ABSL_IS_LITTLE_ENDIAN 1 -#else -#error "absl endian detection needs to be set up for your compiler" -#endif - -// macOS 10.13 and iOS 10.11 don't let you use <any>, <optional>, or <variant> -// even though the headers exist and are publicly noted to work. See -// https://github.com/abseil/abseil-cpp/issues/207 and -// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes -// libc++ spells out the availability requirements in the file -// llvm-project/libcxx/include/__config via the #define -// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. -#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \ - ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000)) -#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 -#else -#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 -#endif - -// ABSL_HAVE_STD_ANY -// -// Checks whether C++17 std::any is available by checking whether <any> exists. -#ifdef ABSL_HAVE_STD_ANY -#error "ABSL_HAVE_STD_ANY cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include(<any>) && __cplusplus >= 201703L && \ - !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define ABSL_HAVE_STD_ANY 1 -#endif -#endif - -// ABSL_HAVE_STD_OPTIONAL -// -// Checks whether C++17 std::optional is available. -#ifdef ABSL_HAVE_STD_OPTIONAL -#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include(<optional>) && __cplusplus >= 201703L && \ - !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define ABSL_HAVE_STD_OPTIONAL 1 -#endif -#endif - -// ABSL_HAVE_STD_VARIANT -// -// Checks whether C++17 std::variant is available. -#ifdef ABSL_HAVE_STD_VARIANT -#error "ABSL_HAVE_STD_VARIANT cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include(<variant>) && __cplusplus >= 201703L && \ - !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define ABSL_HAVE_STD_VARIANT 1 -#endif -#endif - -// ABSL_HAVE_STD_STRING_VIEW -// -// Checks whether C++17 std::string_view is available. -#ifdef ABSL_HAVE_STD_STRING_VIEW -#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." -#endif - -#ifdef __has_include -#if __has_include(<string_view>) && __cplusplus >= 201703L -#define ABSL_HAVE_STD_STRING_VIEW 1 -#endif -#endif - -// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than -// the support for <optional>, <any>, <string_view>, <variant>. So we use -// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>, -// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is -// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language -// version. -// TODO(zhangxy): fix tests before enabling aliasing for `std::any`. -#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ - ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402) -// #define ABSL_HAVE_STD_ANY 1 -#define ABSL_HAVE_STD_OPTIONAL 1 -#define ABSL_HAVE_STD_VARIANT 1 -#define ABSL_HAVE_STD_STRING_VIEW 1 -#endif - -// ABSL_USES_STD_ANY -// -// Indicates whether absl::any is an alias for std::any. -#if !defined(ABSL_OPTION_USE_STD_ANY) -#error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_ANY == 0 || \ - (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY)) -#undef ABSL_USES_STD_ANY -#elif ABSL_OPTION_USE_STD_ANY == 1 || \ - (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY)) -#define ABSL_USES_STD_ANY 1 -#else -#error options.h is misconfigured. -#endif - -// ABSL_USES_STD_OPTIONAL -// -// Indicates whether absl::optional is an alias for std::optional. -#if !defined(ABSL_OPTION_USE_STD_OPTIONAL) -#error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \ - (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL)) -#undef ABSL_USES_STD_OPTIONAL -#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \ - (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL)) -#define ABSL_USES_STD_OPTIONAL 1 -#else -#error options.h is misconfigured. -#endif - -// ABSL_USES_STD_VARIANT -// -// Indicates whether absl::variant is an alias for std::variant. -#if !defined(ABSL_OPTION_USE_STD_VARIANT) -#error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \ - (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT)) -#undef ABSL_USES_STD_VARIANT -#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \ - (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT)) -#define ABSL_USES_STD_VARIANT 1 -#else -#error options.h is misconfigured. -#endif - -// ABSL_USES_STD_STRING_VIEW -// -// Indicates whether absl::string_view is an alias for std::string_view. -#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW) -#error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \ - (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - !defined(ABSL_HAVE_STD_STRING_VIEW)) -#undef ABSL_USES_STD_STRING_VIEW -#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \ - (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \ - defined(ABSL_HAVE_STD_STRING_VIEW)) -#define ABSL_USES_STD_STRING_VIEW 1 -#else -#error options.h is misconfigured. -#endif - -// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION -// SEH exception from emplace for variant<SomeStruct> when constructing the -// struct can throw. This defeats some of variant_test and -// variant_exception_safety_test. -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) -#define ABSL_INTERNAL_MSVC_2017_DBG_MODE -#endif - -// ABSL_INTERNAL_MANGLED_NS -// ABSL_INTERNAL_MANGLED_BACKREFERENCE -// -// Internal macros for building up mangled names in our internal fork of CCTZ. -// This implementation detail is only needed and provided for the MSVC build. -// -// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is -// the mangled spelling of the `absl` namespace, and -// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing -// the proper count to skip past the CCTZ fork namespace names. (This number -// is one larger when there is an inline namespace name to skip.) -#if defined(_MSC_VER) -#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0 -#define ABSL_INTERNAL_MANGLED_NS "absl" -#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5" -#else -#define ABSL_INTERNAL_MANGLED_NS \ - ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl" -#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6" -#endif -#endif - -#undef ABSL_INTERNAL_HAS_KEYWORD - -// ABSL_DLL -// -// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)` -// so we can annotate symbols appropriately as being exported. When used in -// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so -// that consumers know the symbol is defined inside the DLL. In all other cases, -// the macro expands to nothing. -#if defined(_MSC_VER) -#if defined(ABSL_BUILD_DLL) -#define ABSL_DLL __declspec(dllexport) -#elif defined(ABSL_CONSUME_DLL) -#define ABSL_DLL __declspec(dllimport) -#else -#define ABSL_DLL -#endif -#else -#define ABSL_DLL -#endif // defined(_MSC_VER) - -// ABSL_HAVE_MEMORY_SANITIZER -// -// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of -// a compiler instrumentation module and a run-time library. -#ifdef ABSL_HAVE_MEMORY_SANITIZER -#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set." -#elif defined(MEMORY_SANITIZER) -// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it -// for now. -#define ABSL_HAVE_MEMORY_SANITIZER 1 -#elif defined(__SANITIZE_MEMORY__) -#define ABSL_HAVE_MEMORY_SANITIZER 1 -#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer) -#define ABSL_HAVE_MEMORY_SANITIZER 1 -#endif - -// ABSL_HAVE_THREAD_SANITIZER -// -// ThreadSanitizer (TSan) is a fast data race detector. -#ifdef ABSL_HAVE_THREAD_SANITIZER -#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set." -#elif defined(THREAD_SANITIZER) -// The THREAD_SANITIZER macro is deprecated but we will continue to honor it -// for now. -#define ABSL_HAVE_THREAD_SANITIZER 1 -#elif defined(__SANITIZE_THREAD__) -#define ABSL_HAVE_THREAD_SANITIZER 1 -#elif ABSL_HAVE_FEATURE(thread_sanitizer) -#define ABSL_HAVE_THREAD_SANITIZER 1 -#endif - -// ABSL_HAVE_ADDRESS_SANITIZER -// -// AddressSanitizer (ASan) is a fast memory error detector. -#ifdef ABSL_HAVE_ADDRESS_SANITIZER -#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set." -#elif defined(ADDRESS_SANITIZER) -// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it -// for now. -#define ABSL_HAVE_ADDRESS_SANITIZER 1 -#elif defined(__SANITIZE_ADDRESS__) -#define ABSL_HAVE_ADDRESS_SANITIZER 1 -#elif ABSL_HAVE_FEATURE(address_sanitizer) -#define ABSL_HAVE_ADDRESS_SANITIZER 1 -#endif - -#endif // ABSL_BASE_CONFIG_H_ diff --git a/third_party/abseil_cpp/absl/base/config_test.cc b/third_party/abseil_cpp/absl/base/config_test.cc deleted file mode 100644 index 7e0c033de59f..000000000000 --- a/third_party/abseil_cpp/absl/base/config_test.cc +++ /dev/null @@ -1,60 +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/base/config.h" - -#include <cstdint> - -#include "gtest/gtest.h" -#include "absl/synchronization/internal/thread_pool.h" - -namespace { - -TEST(ConfigTest, Endianness) { - union { - uint32_t value; - uint8_t data[sizeof(uint32_t)]; - } number; - number.data[0] = 0x00; - number.data[1] = 0x01; - number.data[2] = 0x02; - number.data[3] = 0x03; -#if defined(ABSL_IS_LITTLE_ENDIAN) && defined(ABSL_IS_BIG_ENDIAN) -#error Both ABSL_IS_LITTLE_ENDIAN and ABSL_IS_BIG_ENDIAN are defined -#elif defined(ABSL_IS_LITTLE_ENDIAN) - EXPECT_EQ(UINT32_C(0x03020100), number.value); -#elif defined(ABSL_IS_BIG_ENDIAN) - EXPECT_EQ(UINT32_C(0x00010203), number.value); -#else -#error Unknown endianness -#endif -} - -#if defined(ABSL_HAVE_THREAD_LOCAL) -TEST(ConfigTest, ThreadLocal) { - static thread_local int mine_mine_mine = 16; - EXPECT_EQ(16, mine_mine_mine); - { - absl::synchronization_internal::ThreadPool pool(1); - pool.Schedule([&] { - EXPECT_EQ(16, mine_mine_mine); - mine_mine_mine = 32; - EXPECT_EQ(32, mine_mine_mine); - }); - } - EXPECT_EQ(16, mine_mine_mine); -} -#endif - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/const_init.h b/third_party/abseil_cpp/absl/base/const_init.h deleted file mode 100644 index 16520b61d95b..000000000000 --- a/third_party/abseil_cpp/absl/base/const_init.h +++ /dev/null @@ -1,76 +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. -// -// ----------------------------------------------------------------------------- -// kConstInit -// ----------------------------------------------------------------------------- -// -// A constructor tag used to mark an object as safe for use as a global -// variable, avoiding the usual lifetime issues that can affect globals. - -#ifndef ABSL_BASE_CONST_INIT_H_ -#define ABSL_BASE_CONST_INIT_H_ - -#include "absl/base/config.h" - -// In general, objects with static storage duration (such as global variables) -// can trigger tricky object lifetime situations. Attempting to access them -// from the constructors or destructors of other global objects can result in -// undefined behavior, unless their constructors and destructors are designed -// with this issue in mind. -// -// The normal way to deal with this issue in C++11 is to use constant -// initialization and trivial destructors. -// -// Constant initialization is guaranteed to occur before any other code -// executes. Constructors that are declared 'constexpr' are eligible for -// constant initialization. You can annotate a variable declaration with the -// ABSL_CONST_INIT macro to express this intent. For compilers that support -// it, this annotation will cause a compilation error for declarations that -// aren't subject to constant initialization (perhaps because a runtime value -// was passed as a constructor argument). -// -// On program shutdown, lifetime issues can be avoided on global objects by -// ensuring that they contain trivial destructors. A class has a trivial -// destructor unless it has a user-defined destructor, a virtual method or base -// class, or a data member or base class with a non-trivial destructor of its -// own. Objects with static storage duration and a trivial destructor are not -// cleaned up on program shutdown, and are thus safe to access from other code -// running during shutdown. -// -// For a few core Abseil classes, we make a best effort to allow for safe global -// instances, even though these classes have non-trivial destructors. These -// objects can be created with the absl::kConstInit tag. For example: -// ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit); -// -// The line above declares a global variable of type absl::Mutex which can be -// accessed at any point during startup or shutdown. global_mutex's destructor -// will still run, but will not invalidate the object. Note that C++ specifies -// that accessing an object after its destructor has run results in undefined -// behavior, but this pattern works on the toolchains we support. -// -// The absl::kConstInit tag should only be used to define objects with static -// or thread_local storage duration. - -namespace absl { -ABSL_NAMESPACE_BEGIN - -enum ConstInitType { - kConstInit, -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_CONST_INIT_H_ diff --git a/third_party/abseil_cpp/absl/base/dynamic_annotations.h b/third_party/abseil_cpp/absl/base/dynamic_annotations.h deleted file mode 100644 index 545f8cbc916b..000000000000 --- a/third_party/abseil_cpp/absl/base/dynamic_annotations.h +++ /dev/null @@ -1,482 +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., ABSL_ANNOTATE_THREAD_NAME). -// -// Actual implementation of these macros may differ depending on the dynamic -// analysis tool being used. -// -// This file supports the following configurations: -// - Dynamic Annotations enabled (with static thread-safety warnings disabled). -// In this case, macros expand to functions implemented by Thread Sanitizer, -// when building with TSan. When not provided an external implementation, -// dynamic_annotations.cc provides no-op implementations. -// -// - Static Clang thread-safety warnings enabled. -// When building with a Clang compiler that supports thread-safety warnings, -// a subset of annotations can be statically-checked at compile-time. We -// expand these macros to static-inline functions that can be analyzed for -// thread-safety, but afterwards elided when building the final binary. -// -// - All annotations are disabled. -// If neither Dynamic Annotations nor Clang thread-safety warnings are -// enabled, then all annotation-macros expand to empty. - -#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ -#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ - -#include <stddef.h> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#ifdef __cplusplus -#include "absl/base/macros.h" -#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 - -#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. - -#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 - -// Read/write annotations are enabled in Annotalysis mode; disabled otherwise. -#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \ - ABSL_INTERNAL_ANNOTALYSIS_ENABLED - -#endif // ABSL_HAVE_THREAD_SANITIZER - -#ifdef __cplusplus -#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" { -#define ABSL_INTERNAL_END_EXTERN_C } // extern "C" -#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F -#define ABSL_INTERNAL_STATIC_INLINE inline -#else -#define 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 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 - -// Report that the lock at address `lock` is about to be destroyed. -#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \ - ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock) - -// Report that the lock at address `lock` has been acquired. -// `is_w`=1 for writer lock, `is_w`=0 for reader lock. -#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ - ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \ - (__FILE__, __LINE__, lock, is_w) - -// Report that the lock at address `lock` is about to be released. -// `is_w`=1 for writer lock, `is_w`=0 for reader lock. -#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ - ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \ - (__FILE__, __LINE__, lock, is_w) - -// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`. -#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ - namespace { \ - class static_var##_annotator { \ - public: \ - static_var##_annotator() { \ - ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \ - #static_var ": " description); \ - } \ - }; \ - static static_var##_annotator the##static_var##_annotator; \ - } // namespace - -// Function prototypes of annotations provided by the compiler-based sanitizer -// implementation. -ABSL_INTERNAL_BEGIN_EXTERN_C -void AnnotateRWLockCreate(const char* file, int line, - const volatile void* lock); -void AnnotateRWLockCreateStatic(const char* file, int line, - const volatile void* lock); -void AnnotateRWLockDestroy(const char* file, int line, - const volatile void* lock); -void AnnotateRWLockAcquired(const char* file, int line, - const volatile void* lock, long is_w); // NOLINT -void AnnotateRWLockReleased(const char* file, int line, - const volatile void* lock, long is_w); // NOLINT -void AnnotateBenignRace(const char* file, int line, - const volatile void* address, const char* description); -void AnnotateBenignRaceSized(const char* file, int line, - const volatile void* address, size_t size, - const char* description); -void AnnotateThreadName(const char* file, int line, const char* name); -void AnnotateEnableRaceDetection(const char* file, int line, int enable); -ABSL_INTERNAL_END_EXTERN_C - -#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0 - -#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty -#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty -#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty -#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty -#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty -#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty -#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty -#define ABSL_ANNOTATE_THREAD_NAME(name) // empty -#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty -#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty - -#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED - -// ------------------------------------------------------------------------- -// Define memory annotations. - -#ifdef ABSL_HAVE_MEMORY_SANITIZER - -#include <sanitizer/msan_interface.h> - -#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \ - __msan_unpoison(address, size) - -#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \ - __msan_allocated_memory(address, size) - -#else // !defined(ABSL_HAVE_MEMORY_SANITIZER) - -// TODO(rogeeff): remove this branch -#ifdef ABSL_HAVE_THREAD_SANITIZER -#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \ - do { \ - (void)(address); \ - (void)(size); \ - } while (0) -#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \ - do { \ - (void)(address); \ - (void)(size); \ - } while (0) -#else - -#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty -#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty - -#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 ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1 - -// 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 ABSL_ANNOTATE_IGNORE_READS_END() \ - ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__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 - -#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED) - -// When Annotalysis is enabled without Dynamic Annotations, the use of -// static-inline functions allows the annotations to be read at compile-time, -// while still letting the compiler elide the functions from the final build. -// -// TODO(delesley) -- The exclusive lock here ignores writes as well, but -// allows IGNORE_READS_AND_WRITES to work properly. - -#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \ - ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)() - -#define ABSL_ANNOTATE_IGNORE_READS_END() \ - ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)() - -ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsBegin() - ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {} - -ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsEnd() - ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {} - -#else - -#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty -#define ABSL_ANNOTATE_IGNORE_READS_END() // empty - -#endif - -// ------------------------------------------------------------------------- -// Define IGNORE_WRITES_BEGIN/_END annotations. - -#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1 - -// 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 - -#else - -#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty -#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty - -#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) - -#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) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -template <typename T> -inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT - ABSL_ANNOTATE_IGNORE_READS_BEGIN(); - T res = x; - ABSL_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) - -#endif - -#ifdef __cplusplus -#ifdef ABSL_HAVE_THREAD_SANITIZER -ABSL_INTERNAL_BEGIN_EXTERN_C -int RunningOnValgrind(); -double ValgrindSlowdown(); -ABSL_INTERNAL_END_EXTERN_C -#else -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -ABSL_DEPRECATED( - "Don't use this interface. It is misleading and is being deleted.") -ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; } -ABSL_DEPRECATED( - "Don't use this interface. It is misleading and is being deleted.") -ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; } -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -using absl::base_internal::RunningOnValgrind; -using absl::base_internal::ValgrindSlowdown; -#endif -#endif - -// ------------------------------------------------------------------------- -// 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 ABSL_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 { \ - char x[8] __attribute__((aligned(8))); \ - } name - -#else - -#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty -#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "") - -#endif // ABSL_HAVE_ADDRESS_SANITIZER - -// ------------------------------------------------------------------------- -// Undefine the macros intended only for this file. - -#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED -#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED -#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED -#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED -#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED -#undef ABSL_INTERNAL_BEGIN_EXTERN_C -#undef ABSL_INTERNAL_END_EXTERN_C -#undef ABSL_INTERNAL_STATIC_INLINE - -#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ diff --git a/third_party/abseil_cpp/absl/base/exception_safety_testing_test.cc b/third_party/abseil_cpp/absl/base/exception_safety_testing_test.cc deleted file mode 100644 index a59be29e919c..000000000000 --- a/third_party/abseil_cpp/absl/base/exception_safety_testing_test.cc +++ /dev/null @@ -1,956 +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/base/internal/exception_safety_testing.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include <cstddef> -#include <exception> -#include <iostream> -#include <list> -#include <type_traits> -#include <vector> - -#include "gtest/gtest-spi.h" -#include "gtest/gtest.h" -#include "absl/memory/memory.h" - -namespace testing { - -namespace { - -using ::testing::exceptions_internal::SetCountdown; -using ::testing::exceptions_internal::TestException; -using ::testing::exceptions_internal::UnsetCountdown; - -// EXPECT_NO_THROW can't inspect the thrown inspection in general. -template <typename F> -void ExpectNoThrow(const F& f) { - try { - f(); - } catch (const TestException& e) { - ADD_FAILURE() << "Unexpected exception thrown from " << e.what(); - } -} - -TEST(ThrowingValueTest, Throws) { - SetCountdown(); - EXPECT_THROW(ThrowingValue<> bomb, TestException); - - // It's not guaranteed that every operator only throws *once*. The default - // ctor only throws once, though, so use it to make sure we only throw when - // the countdown hits 0 - SetCountdown(2); - ExpectNoThrow([]() { ThrowingValue<> bomb; }); - ExpectNoThrow([]() { ThrowingValue<> bomb; }); - EXPECT_THROW(ThrowingValue<> bomb, TestException); - - UnsetCountdown(); -} - -// Tests that an operation throws when the countdown is at 0, doesn't throw when -// the countdown doesn't hit 0, and doesn't modify the state of the -// ThrowingValue if it throws -template <typename F> -void TestOp(const F& f) { - ExpectNoThrow(f); - - SetCountdown(); - EXPECT_THROW(f(), TestException); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, ThrowingCtors) { - ThrowingValue<> bomb; - - TestOp([]() { ThrowingValue<> bomb(1); }); - TestOp([&]() { ThrowingValue<> bomb1 = bomb; }); - TestOp([&]() { ThrowingValue<> bomb1 = std::move(bomb); }); -} - -TEST(ThrowingValueTest, ThrowingAssignment) { - ThrowingValue<> bomb, bomb1; - - TestOp([&]() { bomb = bomb1; }); - TestOp([&]() { bomb = std::move(bomb1); }); - - // Test that when assignment throws, the assignment should fail (lhs != rhs) - // and strong guarantee fails (lhs != lhs_copy). - { - ThrowingValue<> lhs(39), rhs(42); - ThrowingValue<> lhs_copy(lhs); - SetCountdown(); - EXPECT_THROW(lhs = rhs, TestException); - UnsetCountdown(); - EXPECT_NE(lhs, rhs); - EXPECT_NE(lhs_copy, lhs); - } - { - ThrowingValue<> lhs(39), rhs(42); - ThrowingValue<> lhs_copy(lhs), rhs_copy(rhs); - SetCountdown(); - EXPECT_THROW(lhs = std::move(rhs), TestException); - UnsetCountdown(); - EXPECT_NE(lhs, rhs_copy); - EXPECT_NE(lhs_copy, lhs); - } -} - -TEST(ThrowingValueTest, ThrowingComparisons) { - ThrowingValue<> bomb1, bomb2; - TestOp([&]() { return bomb1 == bomb2; }); - TestOp([&]() { return bomb1 != bomb2; }); - TestOp([&]() { return bomb1 < bomb2; }); - TestOp([&]() { return bomb1 <= bomb2; }); - TestOp([&]() { return bomb1 > bomb2; }); - TestOp([&]() { return bomb1 >= bomb2; }); -} - -TEST(ThrowingValueTest, ThrowingArithmeticOps) { - ThrowingValue<> bomb1(1), bomb2(2); - - TestOp([&bomb1]() { +bomb1; }); - TestOp([&bomb1]() { -bomb1; }); - TestOp([&bomb1]() { ++bomb1; }); - TestOp([&bomb1]() { bomb1++; }); - TestOp([&bomb1]() { --bomb1; }); - TestOp([&bomb1]() { bomb1--; }); - - TestOp([&]() { bomb1 + bomb2; }); - TestOp([&]() { bomb1 - bomb2; }); - TestOp([&]() { bomb1* bomb2; }); - TestOp([&]() { bomb1 / bomb2; }); - TestOp([&]() { bomb1 << 1; }); - TestOp([&]() { bomb1 >> 1; }); -} - -TEST(ThrowingValueTest, ThrowingLogicalOps) { - ThrowingValue<> bomb1, bomb2; - - TestOp([&bomb1]() { !bomb1; }); - TestOp([&]() { bomb1&& bomb2; }); - TestOp([&]() { bomb1 || bomb2; }); -} - -TEST(ThrowingValueTest, ThrowingBitwiseOps) { - ThrowingValue<> bomb1, bomb2; - - TestOp([&bomb1]() { ~bomb1; }); - TestOp([&]() { bomb1& bomb2; }); - TestOp([&]() { bomb1 | bomb2; }); - TestOp([&]() { bomb1 ^ bomb2; }); -} - -TEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) { - ThrowingValue<> bomb1(1), bomb2(2); - - TestOp([&]() { bomb1 += bomb2; }); - TestOp([&]() { bomb1 -= bomb2; }); - TestOp([&]() { bomb1 *= bomb2; }); - TestOp([&]() { bomb1 /= bomb2; }); - TestOp([&]() { bomb1 %= bomb2; }); - TestOp([&]() { bomb1 &= bomb2; }); - TestOp([&]() { bomb1 |= bomb2; }); - TestOp([&]() { bomb1 ^= bomb2; }); - TestOp([&]() { bomb1 *= bomb2; }); -} - -TEST(ThrowingValueTest, ThrowingStreamOps) { - ThrowingValue<> bomb; - - TestOp([&]() { - std::istringstream stream; - stream >> bomb; - }); - TestOp([&]() { - std::stringstream stream; - stream << bomb; - }); -} - -// Tests the operator<< of ThrowingValue by forcing ConstructorTracker to emit -// a nonfatal failure that contains the string representation of the Thrower -TEST(ThrowingValueTest, StreamOpsOutput) { - using ::testing::TypeSpec; - exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); - - // Test default spec list (kEverythingThrows) - EXPECT_NONFATAL_FAILURE( - { - using Thrower = ThrowingValue<TypeSpec{}>; - auto thrower = Thrower(123); - thrower.~Thrower(); - }, - "ThrowingValue<>(123)"); - - // Test with one item in spec list (kNoThrowCopy) - EXPECT_NONFATAL_FAILURE( - { - using Thrower = ThrowingValue<TypeSpec::kNoThrowCopy>; - auto thrower = Thrower(234); - thrower.~Thrower(); - }, - "ThrowingValue<kNoThrowCopy>(234)"); - - // Test with multiple items in spec list (kNoThrowMove, kNoThrowNew) - EXPECT_NONFATAL_FAILURE( - { - using Thrower = - ThrowingValue<TypeSpec::kNoThrowMove | TypeSpec::kNoThrowNew>; - auto thrower = Thrower(345); - thrower.~Thrower(); - }, - "ThrowingValue<kNoThrowMove | kNoThrowNew>(345)"); - - // Test with all items in spec list (kNoThrowCopy, kNoThrowMove, kNoThrowNew) - EXPECT_NONFATAL_FAILURE( - { - using Thrower = ThrowingValue<static_cast<TypeSpec>(-1)>; - auto thrower = Thrower(456); - thrower.~Thrower(); - }, - "ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)"); -} - -template <typename F> -void TestAllocatingOp(const F& f) { - ExpectNoThrow(f); - - SetCountdown(); - EXPECT_THROW(f(), exceptions_internal::TestBadAllocException); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, ThrowingAllocatingOps) { - // make_unique calls unqualified operator new, so these exercise the - // ThrowingValue overloads. - TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); }); - TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); }); -} - -TEST(ThrowingValueTest, NonThrowingMoveCtor) { - ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor; - - SetCountdown(); - ExpectNoThrow([¬hrow_ctor]() { - ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor); - }); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, NonThrowingMoveAssign) { - ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2; - - SetCountdown(); - ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() { - nothrow_assign1 = std::move(nothrow_assign2); - }); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, ThrowingCopyCtor) { - ThrowingValue<> tv; - - TestOp([&]() { ThrowingValue<> tv_copy(tv); }); -} - -TEST(ThrowingValueTest, ThrowingCopyAssign) { - ThrowingValue<> tv1, tv2; - - TestOp([&]() { tv1 = tv2; }); -} - -TEST(ThrowingValueTest, NonThrowingCopyCtor) { - ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor; - - SetCountdown(); - ExpectNoThrow([¬hrow_ctor]() { - ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor); - }); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, NonThrowingCopyAssign) { - ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2; - - SetCountdown(); - ExpectNoThrow([¬hrow_assign1, ¬hrow_assign2]() { - nothrow_assign1 = nothrow_assign2; - }); - UnsetCountdown(); -} - -TEST(ThrowingValueTest, ThrowingSwap) { - ThrowingValue<> bomb1, bomb2; - TestOp([&]() { std::swap(bomb1, bomb2); }); -} - -TEST(ThrowingValueTest, NonThrowingSwap) { - ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2; - ExpectNoThrow([&]() { std::swap(bomb1, bomb2); }); -} - -TEST(ThrowingValueTest, NonThrowingAllocation) { - ThrowingValue<TypeSpec::kNoThrowNew>* allocated; - ThrowingValue<TypeSpec::kNoThrowNew>* array; - - ExpectNoThrow([&allocated]() { - allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1); - delete allocated; - }); - ExpectNoThrow([&array]() { - array = new ThrowingValue<TypeSpec::kNoThrowNew>[2]; - delete[] array; - }); -} - -TEST(ThrowingValueTest, NonThrowingDelete) { - auto* allocated = new ThrowingValue<>(1); - auto* array = new ThrowingValue<>[2]; - - SetCountdown(); - ExpectNoThrow([allocated]() { delete allocated; }); - SetCountdown(); - ExpectNoThrow([array]() { delete[] array; }); - - UnsetCountdown(); -} - -TEST(ThrowingValueTest, NonThrowingPlacementDelete) { - constexpr int kArrayLen = 2; - // We intentionally create extra space to store the tag allocated by placement - // new[]. - constexpr int kStorageLen = 4; - - alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)]; - alignas(ThrowingValue<>) unsigned char - array_buf[sizeof(ThrowingValue<>[kStorageLen])]; - auto* placed = new (&buf) ThrowingValue<>(1); - auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen]; - - SetCountdown(); - ExpectNoThrow([placed, &buf]() { - placed->~ThrowingValue<>(); - ThrowingValue<>::operator delete(placed, &buf); - }); - - SetCountdown(); - ExpectNoThrow([&, placed_array]() { - for (int i = 0; i < kArrayLen; ++i) placed_array[i].~ThrowingValue<>(); - ThrowingValue<>::operator delete[](placed_array, &array_buf); - }); - - UnsetCountdown(); -} - -TEST(ThrowingValueTest, NonThrowingDestructor) { - auto* allocated = new ThrowingValue<>(); - - SetCountdown(); - ExpectNoThrow([allocated]() { delete allocated; }); - UnsetCountdown(); -} - -TEST(ThrowingBoolTest, ThrowingBool) { - ThrowingBool t = true; - - // Test that it's contextually convertible to bool - if (t) { // NOLINT(whitespace/empty_if_body) - } - EXPECT_TRUE(t); - - TestOp([&]() { (void)!t; }); -} - -TEST(ThrowingAllocatorTest, MemoryManagement) { - // Just exercise the memory management capabilities under LSan to make sure we - // don't leak. - ThrowingAllocator<int> int_alloc; - int* ip = int_alloc.allocate(1); - int_alloc.deallocate(ip, 1); - int* i_array = int_alloc.allocate(2); - int_alloc.deallocate(i_array, 2); - - ThrowingAllocator<ThrowingValue<>> tv_alloc; - ThrowingValue<>* ptr = tv_alloc.allocate(1); - tv_alloc.deallocate(ptr, 1); - ThrowingValue<>* tv_array = tv_alloc.allocate(2); - tv_alloc.deallocate(tv_array, 2); -} - -TEST(ThrowingAllocatorTest, CallsGlobalNew) { - ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc; - ThrowingValue<>* ptr; - - SetCountdown(); - // This will only throw if ThrowingValue::new is called. - ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); }); - nothrow_alloc.deallocate(ptr, 1); - - UnsetCountdown(); -} - -TEST(ThrowingAllocatorTest, ThrowingConstructors) { - ThrowingAllocator<int> int_alloc; - int* ip = nullptr; - - SetCountdown(); - EXPECT_THROW(ip = int_alloc.allocate(1), TestException); - ExpectNoThrow([&]() { ip = int_alloc.allocate(1); }); - - *ip = 1; - SetCountdown(); - EXPECT_THROW(int_alloc.construct(ip, 2), TestException); - EXPECT_EQ(*ip, 1); - int_alloc.deallocate(ip, 1); - - UnsetCountdown(); -} - -TEST(ThrowingAllocatorTest, NonThrowingConstruction) { - { - ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc; - int* ip = nullptr; - - SetCountdown(); - ExpectNoThrow([&]() { ip = int_alloc.allocate(1); }); - - SetCountdown(); - ExpectNoThrow([&]() { int_alloc.construct(ip, 2); }); - - EXPECT_EQ(*ip, 2); - int_alloc.deallocate(ip, 1); - - UnsetCountdown(); - } - - { - ThrowingAllocator<int> int_alloc; - int* ip = nullptr; - ExpectNoThrow([&]() { ip = int_alloc.allocate(1); }); - ExpectNoThrow([&]() { int_alloc.construct(ip, 2); }); - EXPECT_EQ(*ip, 2); - int_alloc.deallocate(ip, 1); - } - - { - ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> - nothrow_alloc; - ThrowingValue<>* ptr; - - SetCountdown(); - ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); }); - - SetCountdown(); - ExpectNoThrow( - [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); }); - - EXPECT_EQ(ptr->Get(), 2); - nothrow_alloc.destroy(ptr); - nothrow_alloc.deallocate(ptr, 1); - - UnsetCountdown(); - } - - { - ThrowingAllocator<int> a; - - SetCountdown(); - ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = a; }); - - SetCountdown(); - ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = std::move(a); }); - - UnsetCountdown(); - } -} - -TEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) { - ThrowingAllocator<int> a; - TestOp([]() { ThrowingAllocator<int> a; }); - TestOp([&]() { a.select_on_container_copy_construction(); }); -} - -TEST(ThrowingAllocatorTest, State) { - ThrowingAllocator<int> a1, a2; - EXPECT_NE(a1, a2); - - auto a3 = a1; - EXPECT_EQ(a3, a1); - int* ip = a1.allocate(1); - EXPECT_EQ(a3, a1); - a3.deallocate(ip, 1); - EXPECT_EQ(a3, a1); -} - -TEST(ThrowingAllocatorTest, InVector) { - std::vector<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> v; - for (int i = 0; i < 20; ++i) v.push_back({}); - for (int i = 0; i < 20; ++i) v.pop_back(); -} - -TEST(ThrowingAllocatorTest, InList) { - std::list<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> l; - for (int i = 0; i < 20; ++i) l.push_back({}); - for (int i = 0; i < 20; ++i) l.pop_back(); - for (int i = 0; i < 20; ++i) l.push_front({}); - for (int i = 0; i < 20; ++i) l.pop_front(); -} - -template <typename TesterInstance, typename = void> -struct NullaryTestValidator : public std::false_type {}; - -template <typename TesterInstance> -struct NullaryTestValidator< - TesterInstance, - absl::void_t<decltype(std::declval<TesterInstance>().Test())>> - : public std::true_type {}; - -template <typename TesterInstance> -bool HasNullaryTest(const TesterInstance&) { - return NullaryTestValidator<TesterInstance>::value; -} - -void DummyOp(void*) {} - -template <typename TesterInstance, typename = void> -struct UnaryTestValidator : public std::false_type {}; - -template <typename TesterInstance> -struct UnaryTestValidator< - TesterInstance, - absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>> - : public std::true_type {}; - -template <typename TesterInstance> -bool HasUnaryTest(const TesterInstance&) { - return UnaryTestValidator<TesterInstance>::value; -} - -TEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) { - using T = exceptions_internal::UninitializedT; - auto op = [](T* t) {}; - auto inv = [](T*) { return testing::AssertionSuccess(); }; - auto fac = []() { return absl::make_unique<T>(); }; - - // Test that providing operation and inveriants still does not allow for the - // the invocation of .Test() and .Test(op) because it lacks a factory - auto without_fac = - testing::MakeExceptionSafetyTester().WithOperation(op).WithContracts( - inv, testing::strong_guarantee); - EXPECT_FALSE(HasNullaryTest(without_fac)); - EXPECT_FALSE(HasUnaryTest(without_fac)); - - // Test that providing contracts and factory allows the invocation of - // .Test(op) but does not allow for .Test() because it lacks an operation - auto without_op = testing::MakeExceptionSafetyTester() - .WithContracts(inv, testing::strong_guarantee) - .WithFactory(fac); - EXPECT_FALSE(HasNullaryTest(without_op)); - EXPECT_TRUE(HasUnaryTest(without_op)); - - // Test that providing operation and factory still does not allow for the - // the invocation of .Test() and .Test(op) because it lacks contracts - auto without_inv = - testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac); - EXPECT_FALSE(HasNullaryTest(without_inv)); - EXPECT_FALSE(HasUnaryTest(without_inv)); -} - -struct ExampleStruct {}; - -std::unique_ptr<ExampleStruct> ExampleFunctionFactory() { - return absl::make_unique<ExampleStruct>(); -} - -void ExampleFunctionOperation(ExampleStruct*) {} - -testing::AssertionResult ExampleFunctionContract(ExampleStruct*) { - return testing::AssertionSuccess(); -} - -struct { - std::unique_ptr<ExampleStruct> operator()() const { - return ExampleFunctionFactory(); - } -} example_struct_factory; - -struct { - void operator()(ExampleStruct*) const {} -} example_struct_operation; - -struct { - testing::AssertionResult operator()(ExampleStruct* example_struct) const { - return ExampleFunctionContract(example_struct); - } -} example_struct_contract; - -auto example_lambda_factory = []() { return ExampleFunctionFactory(); }; - -auto example_lambda_operation = [](ExampleStruct*) {}; - -auto example_lambda_contract = [](ExampleStruct* example_struct) { - return ExampleFunctionContract(example_struct); -}; - -// Testing that function references, pointers, structs with operator() and -// lambdas can all be used with ExceptionSafetyTester -TEST(ExceptionSafetyTesterTest, MixedFunctionTypes) { - // function reference - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithFactory(ExampleFunctionFactory) - .WithOperation(ExampleFunctionOperation) - .WithContracts(ExampleFunctionContract) - .Test()); - - // function pointer - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithFactory(&ExampleFunctionFactory) - .WithOperation(&ExampleFunctionOperation) - .WithContracts(&ExampleFunctionContract) - .Test()); - - // struct - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithFactory(example_struct_factory) - .WithOperation(example_struct_operation) - .WithContracts(example_struct_contract) - .Test()); - - // lambda - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithFactory(example_lambda_factory) - .WithOperation(example_lambda_operation) - .WithContracts(example_lambda_contract) - .Test()); -} - -struct NonNegative { - bool operator==(const NonNegative& other) const { return i == other.i; } - int i; -}; - -testing::AssertionResult CheckNonNegativeInvariants(NonNegative* g) { - if (g->i >= 0) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "i should be non-negative but is " << g->i; -} - -struct { - template <typename T> - void operator()(T* t) const { - (*t)(); - } -} invoker; - -auto tester = - testing::MakeExceptionSafetyTester().WithOperation(invoker).WithContracts( - CheckNonNegativeInvariants); -auto strong_tester = tester.WithContracts(testing::strong_guarantee); - -struct FailsBasicGuarantee : public NonNegative { - void operator()() { - --i; - ThrowingValue<> bomb; - ++i; - } -}; - -TEST(ExceptionCheckTest, BasicGuaranteeFailure) { - EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test()); -} - -struct FollowsBasicGuarantee : public NonNegative { - void operator()() { - ++i; - ThrowingValue<> bomb; - } -}; - -TEST(ExceptionCheckTest, BasicGuarantee) { - EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test()); -} - -TEST(ExceptionCheckTest, StrongGuaranteeFailure) { - EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test()); - EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test()); -} - -struct BasicGuaranteeWithExtraContracts : public NonNegative { - // After operator(), i is incremented. If operator() throws, i is set to 9999 - void operator()() { - int old_i = i; - i = kExceptionSentinel; - ThrowingValue<> bomb; - i = ++old_i; - } - - static constexpr int kExceptionSentinel = 9999; -}; -constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel; - -TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) { - auto tester_with_val = - tester.WithInitialValue(BasicGuaranteeWithExtraContracts{}); - EXPECT_TRUE(tester_with_val.Test()); - EXPECT_TRUE( - tester_with_val - .WithContracts([](BasicGuaranteeWithExtraContracts* o) { - if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "i should be " - << BasicGuaranteeWithExtraContracts::kExceptionSentinel - << ", but is " << o->i; - }) - .Test()); -} - -struct FollowsStrongGuarantee : public NonNegative { - void operator()() { ThrowingValue<> bomb; } -}; - -TEST(ExceptionCheckTest, StrongGuarantee) { - EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test()); - EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test()); -} - -struct HasReset : public NonNegative { - void operator()() { - i = -1; - ThrowingValue<> bomb; - i = 1; - } - - void reset() { i = 0; } -}; - -testing::AssertionResult CheckHasResetContracts(HasReset* h) { - h->reset(); - return testing::AssertionResult(h->i == 0); -} - -TEST(ExceptionCheckTest, ModifyingChecker) { - auto set_to_1000 = [](FollowsBasicGuarantee* g) { - g->i = 1000; - return testing::AssertionSuccess(); - }; - auto is_1000 = [](FollowsBasicGuarantee* g) { - return testing::AssertionResult(g->i == 1000); - }; - auto increment = [](FollowsStrongGuarantee* g) { - ++g->i; - return testing::AssertionSuccess(); - }; - - EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{}) - .WithContracts(set_to_1000, is_1000) - .Test()); - EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}) - .WithContracts(increment) - .Test()); - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithInitialValue(HasReset{}) - .WithContracts(CheckHasResetContracts) - .Test(invoker)); -} - -TEST(ExceptionSafetyTesterTest, ResetsCountdown) { - auto test = - testing::MakeExceptionSafetyTester() - .WithInitialValue(ThrowingValue<>()) - .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); }) - .WithOperation([](ThrowingValue<>*) {}); - ASSERT_TRUE(test.Test()); - // If the countdown isn't reset because there were no exceptions thrown, then - // this will fail with a termination from an unhandled exception - EXPECT_TRUE(test.Test()); -} - -struct NonCopyable : public NonNegative { - NonCopyable(const NonCopyable&) = delete; - NonCopyable() : NonNegative{0} {} - - void operator()() { ThrowingValue<> bomb; } -}; - -TEST(ExceptionCheckTest, NonCopyable) { - auto factory = []() { return absl::make_unique<NonCopyable>(); }; - EXPECT_TRUE(tester.WithFactory(factory).Test()); - EXPECT_TRUE(strong_tester.WithFactory(factory).Test()); -} - -struct NonEqualityComparable : public NonNegative { - void operator()() { ThrowingValue<> bomb; } - - void ModifyOnThrow() { - ++i; - ThrowingValue<> bomb; - static_cast<void>(bomb); - --i; - } -}; - -TEST(ExceptionCheckTest, NonEqualityComparable) { - auto nec_is_strong = [](NonEqualityComparable* nec) { - return testing::AssertionResult(nec->i == NonEqualityComparable().i); - }; - auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{}) - .WithContracts(nec_is_strong); - - EXPECT_TRUE(strong_nec_tester.Test()); - EXPECT_FALSE(strong_nec_tester.Test( - [](NonEqualityComparable* n) { n->ModifyOnThrow(); })); -} - -template <typename T> -struct ExhaustivenessTester { - void operator()() { - successes |= 1; - T b1; - static_cast<void>(b1); - successes |= (1 << 1); - T b2; - static_cast<void>(b2); - successes |= (1 << 2); - T b3; - static_cast<void>(b3); - successes |= (1 << 3); - } - - bool operator==(const ExhaustivenessTester<ThrowingValue<>>&) const { - return true; - } - - static unsigned char successes; -}; - -struct { - template <typename T> - testing::AssertionResult operator()(ExhaustivenessTester<T>*) const { - return testing::AssertionSuccess(); - } -} CheckExhaustivenessTesterContracts; - -template <typename T> -unsigned char ExhaustivenessTester<T>::successes = 0; - -TEST(ExceptionCheckTest, Exhaustiveness) { - auto exhaust_tester = testing::MakeExceptionSafetyTester() - .WithContracts(CheckExhaustivenessTesterContracts) - .WithOperation(invoker); - - EXPECT_TRUE( - exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test()); - EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF); - - EXPECT_TRUE( - exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{}) - .WithContracts(testing::strong_guarantee) - .Test()); - EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF); -} - -struct LeaksIfCtorThrows : private exceptions_internal::TrackedObject { - LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) { - ++counter; - ThrowingValue<> v; - static_cast<void>(v); - --counter; - } - LeaksIfCtorThrows(const LeaksIfCtorThrows&) noexcept - : TrackedObject(ABSL_PRETTY_FUNCTION) {} - static int counter; -}; -int LeaksIfCtorThrows::counter = 0; - -TEST(ExceptionCheckTest, TestLeakyCtor) { - testing::TestThrowingCtor<LeaksIfCtorThrows>(); - EXPECT_EQ(LeaksIfCtorThrows::counter, 1); - LeaksIfCtorThrows::counter = 0; -} - -struct Tracked : private exceptions_internal::TrackedObject { - Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {} -}; - -TEST(ConstructorTrackerTest, CreatedBefore) { - Tracked a, b, c; - exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); -} - -TEST(ConstructorTrackerTest, CreatedAfter) { - exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); - Tracked a, b, c; -} - -TEST(ConstructorTrackerTest, NotDestroyedAfter) { - alignas(Tracked) unsigned char storage[sizeof(Tracked)]; - EXPECT_NONFATAL_FAILURE( - { - exceptions_internal::ConstructorTracker ct( - exceptions_internal::countdown); - new (&storage) Tracked(); - }, - "not destroyed"); -} - -TEST(ConstructorTrackerTest, DestroyedTwice) { - exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); - EXPECT_NONFATAL_FAILURE( - { - Tracked t; - t.~Tracked(); - }, - "re-destroyed"); -} - -TEST(ConstructorTrackerTest, ConstructedTwice) { - exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); - alignas(Tracked) unsigned char storage[sizeof(Tracked)]; - EXPECT_NONFATAL_FAILURE( - { - new (&storage) Tracked(); - new (&storage) Tracked(); - reinterpret_cast<Tracked*>(&storage)->~Tracked(); - }, - "re-constructed"); -} - -TEST(ThrowingValueTraitsTest, RelationalOperators) { - ThrowingValue<> a, b; - EXPECT_TRUE((std::is_convertible<decltype(a == b), bool>::value)); - EXPECT_TRUE((std::is_convertible<decltype(a != b), bool>::value)); - EXPECT_TRUE((std::is_convertible<decltype(a < b), bool>::value)); - EXPECT_TRUE((std::is_convertible<decltype(a <= b), bool>::value)); - EXPECT_TRUE((std::is_convertible<decltype(a > b), bool>::value)); - EXPECT_TRUE((std::is_convertible<decltype(a >= b), bool>::value)); -} - -TEST(ThrowingAllocatorTraitsTest, Assignablility) { - EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value); - EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value); -} - -} // namespace - -} // namespace testing - -#endif // ABSL_HAVE_EXCEPTIONS diff --git a/third_party/abseil_cpp/absl/base/inline_variable_test.cc b/third_party/abseil_cpp/absl/base/inline_variable_test.cc deleted file mode 100644 index 37a40e1e40a6..000000000000 --- a/third_party/abseil_cpp/absl/base/inline_variable_test.cc +++ /dev/null @@ -1,64 +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 <type_traits> - -#include "absl/base/internal/inline_variable.h" -#include "absl/base/internal/inline_variable_testing.h" - -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace inline_variable_testing_internal { -namespace { - -TEST(InlineVariableTest, Constexpr) { - static_assert(inline_variable_foo.value == 5, ""); - static_assert(other_inline_variable_foo.value == 5, ""); - static_assert(inline_variable_int == 5, ""); - static_assert(other_inline_variable_int == 5, ""); -} - -TEST(InlineVariableTest, DefaultConstructedIdentityEquality) { - EXPECT_EQ(get_foo_a().value, 5); - EXPECT_EQ(get_foo_b().value, 5); - EXPECT_EQ(&get_foo_a(), &get_foo_b()); -} - -TEST(InlineVariableTest, DefaultConstructedIdentityInequality) { - EXPECT_NE(&inline_variable_foo, &other_inline_variable_foo); -} - -TEST(InlineVariableTest, InitializedIdentityEquality) { - EXPECT_EQ(get_int_a(), 5); - EXPECT_EQ(get_int_b(), 5); - EXPECT_EQ(&get_int_a(), &get_int_b()); -} - -TEST(InlineVariableTest, InitializedIdentityInequality) { - EXPECT_NE(&inline_variable_int, &other_inline_variable_int); -} - -TEST(InlineVariableTest, FunPtrType) { - static_assert( - std::is_same<void(*)(), - std::decay<decltype(inline_variable_fun_ptr)>::type>::value, - ""); -} - -} // namespace -} // namespace inline_variable_testing_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/inline_variable_test_a.cc b/third_party/abseil_cpp/absl/base/inline_variable_test_a.cc deleted file mode 100644 index f96a58d9b422..000000000000 --- a/third_party/abseil_cpp/absl/base/inline_variable_test_a.cc +++ /dev/null @@ -1,27 +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/base/internal/inline_variable_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace inline_variable_testing_internal { - -const Foo& get_foo_a() { return inline_variable_foo; } - -const int& get_int_a() { return inline_variable_int; } - -} // namespace inline_variable_testing_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/inline_variable_test_b.cc b/third_party/abseil_cpp/absl/base/inline_variable_test_b.cc deleted file mode 100644 index 038adc30a9fb..000000000000 --- a/third_party/abseil_cpp/absl/base/inline_variable_test_b.cc +++ /dev/null @@ -1,27 +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/base/internal/inline_variable_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace inline_variable_testing_internal { - -const Foo& get_foo_b() { return inline_variable_foo; } - -const int& get_int_b() { return inline_variable_int; } - -} // namespace inline_variable_testing_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/atomic_hook.h b/third_party/abseil_cpp/absl/base/internal/atomic_hook.h deleted file mode 100644 index ae21cd7fe50a..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/atomic_hook.h +++ /dev/null @@ -1,200 +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. - -#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ -#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ - -#include <atomic> -#include <cassert> -#include <cstdint> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" - -#if defined(_MSC_VER) && !defined(__clang__) -#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0 -#else -#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1 -#endif - -#if defined(_MSC_VER) -#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0 -#else -#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -template <typename T> -class AtomicHook; - -// To workaround AtomicHook not being constant-initializable on some platforms, -// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES` -// instead of `ABSL_CONST_INIT`. -#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT -#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT -#else -#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES -#endif - -// `AtomicHook` is a helper class, templatized on a raw function pointer type, -// for implementing Abseil customization hooks. It is a callable object that -// dispatches to the registered hook. Objects of type `AtomicHook` must have -// static or thread storage duration. -// -// A default constructed object performs a no-op (and returns a default -// constructed object) if no hook has been registered. -// -// Hooks can be pre-registered via constant initialization, for example: -// -// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()> -// my_hook(DefaultAction); -// -// and then changed at runtime via a call to `Store()`. -// -// Reads and writes guarantee memory_order_acquire/memory_order_release -// semantics. -template <typename ReturnType, typename... Args> -class AtomicHook<ReturnType (*)(Args...)> { - public: - using FnPtr = ReturnType (*)(Args...); - - // Constructs an object that by default performs a no-op (and - // returns a default constructed object) when no hook as been registered. - constexpr AtomicHook() : AtomicHook(DummyFunction) {} - - // Constructs an object that by default dispatches to/returns the - // pre-registered default_fn when no hook has been registered at runtime. -#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT - explicit constexpr AtomicHook(FnPtr default_fn) - : hook_(default_fn), default_fn_(default_fn) {} -#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT - explicit constexpr AtomicHook(FnPtr default_fn) - : hook_(kUninitialized), default_fn_(default_fn) {} -#else - // As of January 2020, on all known versions of MSVC this constructor runs in - // the global constructor sequence. If `Store()` is called by a dynamic - // initializer, we want to preserve the value, even if this constructor runs - // after the call to `Store()`. If not, `hook_` will be - // zero-initialized by the linker and we have no need to set it. - // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html - explicit constexpr AtomicHook(FnPtr default_fn) - : /* hook_(deliberately omitted), */ default_fn_(default_fn) { - static_assert(kUninitialized == 0, "here we rely on zero-initialization"); - } -#endif - - // Stores the provided function pointer as the value for this hook. - // - // This is intended to be called once. Multiple calls are legal only if the - // same function pointer is provided for each call. The store is implemented - // as a memory_order_release operation, and read accesses are implemented as - // memory_order_acquire. - void Store(FnPtr fn) { - bool success = DoStore(fn); - static_cast<void>(success); - assert(success); - } - - // Invokes the registered callback. If no callback has yet been registered, a - // default-constructed object of the appropriate type is returned instead. - template <typename... CallArgs> - ReturnType operator()(CallArgs&&... args) const { - return DoLoad()(std::forward<CallArgs>(args)...); - } - - // Returns the registered callback, or nullptr if none has been registered. - // Useful if client code needs to conditionalize behavior based on whether a - // callback was registered. - // - // Note that atomic_hook.Load()() and atomic_hook() have different semantics: - // operator()() will perform a no-op if no callback was registered, while - // Load()() will dereference a null function pointer. Prefer operator()() to - // Load()() unless you must conditionalize behavior on whether a hook was - // registered. - FnPtr Load() const { - FnPtr ptr = DoLoad(); - return (ptr == DummyFunction) ? nullptr : ptr; - } - - private: - static ReturnType DummyFunction(Args...) { - return ReturnType(); - } - - // Current versions of MSVC (as of September 2017) have a broken - // implementation of std::atomic<T*>: Its constructor attempts to do the - // equivalent of a reinterpret_cast in a constexpr context, which is not - // allowed. - // - // This causes an issue when building with LLVM under Windows. To avoid this, - // we use a less-efficient, intptr_t-based implementation on Windows. -#if ABSL_HAVE_WORKING_ATOMIC_POINTER - // Return the stored value, or DummyFunction if no value has been stored. - FnPtr DoLoad() const { return hook_.load(std::memory_order_acquire); } - - // Store the given value. Returns false if a different value was already - // stored to this object. - bool DoStore(FnPtr fn) { - assert(fn); - FnPtr expected = default_fn_; - const bool store_succeeded = hook_.compare_exchange_strong( - expected, fn, std::memory_order_acq_rel, std::memory_order_acquire); - const bool same_value_already_stored = (expected == fn); - return store_succeeded || same_value_already_stored; - } - - std::atomic<FnPtr> hook_; -#else // !ABSL_HAVE_WORKING_ATOMIC_POINTER - // Use a sentinel value unlikely to be the address of an actual function. - static constexpr intptr_t kUninitialized = 0; - - static_assert(sizeof(intptr_t) >= sizeof(FnPtr), - "intptr_t can't contain a function pointer"); - - FnPtr DoLoad() const { - const intptr_t value = hook_.load(std::memory_order_acquire); - if (value == kUninitialized) { - return default_fn_; - } - return reinterpret_cast<FnPtr>(value); - } - - bool DoStore(FnPtr fn) { - assert(fn); - const auto value = reinterpret_cast<intptr_t>(fn); - intptr_t expected = kUninitialized; - const bool store_succeeded = hook_.compare_exchange_strong( - expected, value, std::memory_order_acq_rel, std::memory_order_acquire); - const bool same_value_already_stored = (expected == value); - return store_succeeded || same_value_already_stored; - } - - std::atomic<intptr_t> hook_; -#endif - - const FnPtr default_fn_; -}; - -#undef ABSL_HAVE_WORKING_ATOMIC_POINTER -#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test.cc b/third_party/abseil_cpp/absl/base/internal/atomic_hook_test.cc deleted file mode 100644 index e577a8fd930b..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/base/internal/atomic_hook.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/internal/atomic_hook_test_helper.h" - -namespace { - -using ::testing::Eq; - -int value = 0; -void TestHook(int x) { value = x; } - -TEST(AtomicHookTest, NoDefaultFunction) { - ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook< - void (*)(int)> - hook; - value = 0; - - // Test the default DummyFunction. - EXPECT_TRUE(hook.Load() == nullptr); - EXPECT_EQ(value, 0); - hook(1); - EXPECT_EQ(value, 0); - - // Test a stored hook. - hook.Store(TestHook); - EXPECT_TRUE(hook.Load() == TestHook); - EXPECT_EQ(value, 0); - hook(1); - EXPECT_EQ(value, 1); - - // Calling Store() with the same hook should not crash. - hook.Store(TestHook); - EXPECT_TRUE(hook.Load() == TestHook); - EXPECT_EQ(value, 1); - hook(2); - EXPECT_EQ(value, 2); -} - -TEST(AtomicHookTest, WithDefaultFunction) { - // Set the default value to TestHook at compile-time. - ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook< - void (*)(int)> - hook(TestHook); - value = 0; - - // Test the default value is TestHook. - EXPECT_TRUE(hook.Load() == TestHook); - EXPECT_EQ(value, 0); - hook(1); - EXPECT_EQ(value, 1); - - // Calling Store() with the same hook should not crash. - hook.Store(TestHook); - EXPECT_TRUE(hook.Load() == TestHook); - EXPECT_EQ(value, 1); - hook(2); - EXPECT_EQ(value, 2); -} - -ABSL_CONST_INIT int override_func_calls = 0; -void OverrideFunc() { override_func_calls++; } -static struct OverrideInstaller { - OverrideInstaller() { absl::atomic_hook_internal::func.Store(OverrideFunc); } -} override_installer; - -TEST(AtomicHookTest, DynamicInitFromAnotherTU) { - // MSVC 14.2 doesn't do constexpr static init correctly; in particular it - // tends to sequence static init (i.e. defaults) of `AtomicHook` objects - // after their dynamic init (i.e. overrides), overwriting whatever value was - // written during dynamic init. This regression test validates the fix. - // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html - EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0)); - EXPECT_THAT(override_func_calls, Eq(0)); - absl::atomic_hook_internal::func(); - EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0)); - EXPECT_THAT(override_func_calls, Eq(1)); - EXPECT_THAT(absl::atomic_hook_internal::func.Load(), Eq(OverrideFunc)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.cc b/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.cc deleted file mode 100644 index 537d47cd2d2f..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.cc +++ /dev/null @@ -1,32 +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/base/internal/atomic_hook_test_helper.h" - -#include "absl/base/attributes.h" -#include "absl/base/internal/atomic_hook.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace atomic_hook_internal { - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<VoidF> - func(DefaultFunc); -ABSL_CONST_INIT int default_func_calls = 0; -void DefaultFunc() { default_func_calls++; } -void RegisterFunc(VoidF f) { func.Store(f); } - -} // namespace atomic_hook_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.h b/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.h deleted file mode 100644 index 3e72b4977d2f..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/atomic_hook_test_helper.h +++ /dev/null @@ -1,34 +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. - -#ifndef ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_ -#define ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_ - -#include "absl/base/internal/atomic_hook.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace atomic_hook_internal { - -using VoidF = void (*)(); -extern absl::base_internal::AtomicHook<VoidF> func; -extern int default_func_calls; -void DefaultFunc(); -void RegisterFunc(VoidF func); - -} // namespace atomic_hook_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/bits.h b/third_party/abseil_cpp/absl/base/internal/bits.h deleted file mode 100644 index 81648e2c3957..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/bits.h +++ /dev/null @@ -1,219 +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. - -#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) && !defined(__clang__) -#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) && !defined(__clang__) -// 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(__clang__) && 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) && !defined(__clang__) - // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse - unsigned long result = 0; // NOLINT(runtime/int) - if ((n >> 32) && - _BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) { - return 31 - result; - } - if (_BitScanReverse(&result, static_cast<unsigned long>(n))) { - return 63 - result; - } - return 64; -#elif defined(__GNUC__) || defined(__clang__) - // 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) && !defined(__clang__) - unsigned long result = 0; // NOLINT(runtime/int) - if (_BitScanReverse(&result, n)) { - return 31 - result; - } - return 32; -#elif defined(__GNUC__) || defined(__clang__) - // 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(__clang__) && defined(_M_X64) - unsigned long result = 0; // NOLINT(runtime/int) - _BitScanForward64(&result, n); - return result; -#elif defined(_MSC_VER) && !defined(__clang__) - unsigned long result = 0; // NOLINT(runtime/int) - if (static_cast<uint32_t>(n) == 0) { - _BitScanForward(&result, static_cast<unsigned long>(n >> 32)); - return result + 32; - } - _BitScanForward(&result, static_cast<unsigned long>(n)); - return result; -#elif defined(__GNUC__) || defined(__clang__) - 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) && !defined(__clang__) - unsigned long result = 0; // NOLINT(runtime/int) - _BitScanForward(&result, n); - return result; -#elif defined(__GNUC__) || defined(__clang__) - 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 deleted file mode 100644 index 7855fa629724..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/bits_test.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT 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/cmake_thread_test.cc b/third_party/abseil_cpp/absl/base/internal/cmake_thread_test.cc deleted file mode 100644 index f70bb24eb7b4..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/cmake_thread_test.cc +++ /dev/null @@ -1,22 +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 <iostream> -#include "absl/base/internal/thread_identity.h" - -int main() { - auto* tid = absl::base_internal::CurrentThreadIdentityIfPresent(); - // Make sure the above call can't be optimized out - std::cout << (void*)tid << std::endl; -} diff --git a/third_party/abseil_cpp/absl/base/internal/cycleclock.cc b/third_party/abseil_cpp/absl/base/internal/cycleclock.cc deleted file mode 100644 index 0e65005b8914..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/cycleclock.cc +++ /dev/null @@ -1,107 +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. - -// The implementation of CycleClock::Frequency. -// -// NOTE: only i386 and x86_64 have been well tested. -// PPC, sparc, alpha, and ia64 are based on -// http://peter.kuscsik.com/wordpress/?p=14 -// with modifications by m3b. See also -// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h - -#include "absl/base/internal/cycleclock.h" - -#include <atomic> -#include <chrono> // NOLINT(build/c++11) - -#include "absl/base/internal/unscaledcycleclock.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -#if ABSL_USE_UNSCALED_CYCLECLOCK - -namespace { - -#ifdef NDEBUG -#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY -// Not debug mode and the UnscaledCycleClock frequency is the CPU -// frequency. Scale the CycleClock to prevent overflow if someone -// tries to represent the time as cycles since the Unix epoch. -static constexpr int32_t kShift = 1; -#else -// Not debug mode and the UnscaledCycleClock isn't operating at the -// raw CPU frequency. There is no need to do any scaling, so don't -// needlessly sacrifice precision. -static constexpr int32_t kShift = 0; -#endif -#else -// In debug mode use a different shift to discourage depending on a -// particular shift value. -static constexpr int32_t kShift = 2; -#endif - -static constexpr double kFrequencyScale = 1.0 / (1 << kShift); -static std::atomic<CycleClockSourceFunc> cycle_clock_source; - -CycleClockSourceFunc LoadCycleClockSource() { - // Optimize for the common case (no callback) by first doing a relaxed load; - // this is significantly faster on non-x86 platforms. - if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) { - return nullptr; - } - // This corresponds to the store(std::memory_order_release) in - // CycleClockSource::Register, and makes sure that any updates made prior to - // registering the callback are visible to this thread before the callback is - // invoked. - return cycle_clock_source.load(std::memory_order_acquire); -} - -} // namespace - -int64_t CycleClock::Now() { - auto fn = LoadCycleClockSource(); - if (fn == nullptr) { - return base_internal::UnscaledCycleClock::Now() >> kShift; - } - return fn() >> kShift; -} - -double CycleClock::Frequency() { - return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency(); -} - -void CycleClockSource::Register(CycleClockSourceFunc source) { - // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource. - cycle_clock_source.store(source, std::memory_order_release); -} - -#else - -int64_t CycleClock::Now() { - return std::chrono::duration_cast<std::chrono::nanoseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); -} - -double CycleClock::Frequency() { - return 1e9; -} - -#endif - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/cycleclock.h b/third_party/abseil_cpp/absl/base/internal/cycleclock.h deleted file mode 100644 index a18b58444560..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/cycleclock.h +++ /dev/null @@ -1,94 +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. -// - -// ----------------------------------------------------------------------------- -// File: cycleclock.h -// ----------------------------------------------------------------------------- -// -// This header file defines a `CycleClock`, which yields the value and frequency -// of a cycle counter that increments at a rate that is approximately constant. -// -// NOTE: -// -// The cycle counter frequency is not necessarily related to the core clock -// frequency and should not be treated as such. That is, `CycleClock` cycles are -// not necessarily "CPU cycles" and code should not rely on that behavior, even -// if experimentally observed. -// -// An arbitrary offset may have been added to the counter at power on. -// -// On some platforms, the rate and offset of the counter may differ -// slightly when read from different CPUs of a multiprocessor. Usually, -// we try to ensure that the operating system adjusts values periodically -// so that values agree approximately. If you need stronger guarantees, -// consider using alternate interfaces. -// -// The CPU is not required to maintain the ordering of a cycle counter read -// with respect to surrounding instructions. - -#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_ -#define ABSL_BASE_INTERNAL_CYCLECLOCK_H_ - -#include <cstdint> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// ----------------------------------------------------------------------------- -// CycleClock -// ----------------------------------------------------------------------------- -class CycleClock { - public: - // CycleClock::Now() - // - // Returns the value of a cycle counter that counts at a rate that is - // approximately constant. - static int64_t Now(); - - // CycleClock::Frequency() - // - // Returns the amount by which `CycleClock::Now()` increases per second. Note - // that this value may not necessarily match the core CPU clock frequency. - static double Frequency(); - - private: - CycleClock() = delete; // no instances - CycleClock(const CycleClock&) = delete; - CycleClock& operator=(const CycleClock&) = delete; -}; - -using CycleClockSourceFunc = int64_t (*)(); - -class CycleClockSource { - private: - // CycleClockSource::Register() - // - // Register a function that provides an alternate source for the unscaled CPU - // cycle count value. The source function must be async signal safe, must not - // call CycleClock::Now(), and must have a frequency that matches that of the - // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use - // the default source. - static void Register(CycleClockSourceFunc source); -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/direct_mmap.h b/third_party/abseil_cpp/absl/base/internal/direct_mmap.h deleted file mode 100644 index 16accf096604..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/direct_mmap.h +++ /dev/null @@ -1,166 +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. -// -// Functions for directly invoking mmap() via syscall, avoiding the case where -// mmap() has been locally overridden. - -#ifndef ABSL_BASE_INTERNAL_DIRECT_MMAP_H_ -#define ABSL_BASE_INTERNAL_DIRECT_MMAP_H_ - -#include "absl/base/config.h" - -#if ABSL_HAVE_MMAP - -#include <sys/mman.h> - -#ifdef __linux__ - -#include <sys/types.h> -#ifdef __BIONIC__ -#include <sys/syscall.h> -#else -#include <syscall.h> -#endif - -#include <linux/unistd.h> -#include <unistd.h> -#include <cerrno> -#include <cstdarg> -#include <cstdint> - -#ifdef __mips__ -// Include definitions of the ABI currently in use. -#ifdef __BIONIC__ -// Android doesn't have sgidefs.h, but does have asm/sgidefs.h, which has the -// definitions we need. -#include <asm/sgidefs.h> -#else -#include <sgidefs.h> -#endif // __BIONIC__ -#endif // __mips__ - -// SYS_mmap and SYS_munmap are not defined in Android. -#ifdef __BIONIC__ -extern "C" void* __mmap2(void*, size_t, int, int, int, size_t); -#if defined(__NR_mmap) && !defined(SYS_mmap) -#define SYS_mmap __NR_mmap -#endif -#ifndef SYS_munmap -#define SYS_munmap __NR_munmap -#endif -#endif // __BIONIC__ - -#if defined(__NR_mmap2) && !defined(SYS_mmap2) -#define SYS_mmap2 __NR_mmap2 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Platform specific logic extracted from -// https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h -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(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \ - (defined(__PPC__) && !defined(__PPC64__)) || \ - (defined(__riscv) && __riscv_xlen == 32) || \ - (defined(__s390__) && !defined(__s390x__)) - // On these architectures, implement mmap with mmap2. - static int pagesize = 0; - if (pagesize == 0) { -#if defined(__wasm__) || defined(__asmjs__) - pagesize = getpagesize(); -#else - pagesize = sysconf(_SC_PAGESIZE); -#endif - } - if (offset < 0 || offset % pagesize != 0) { - errno = EINVAL; - return MAP_FAILED; - } -#ifdef __BIONIC__ - // SYS_mmap2 has problems on Android API level <= 16. - // Workaround by invoking __mmap2() instead. - return __mmap2(start, length, prot, flags, fd, offset / pagesize); -#else - return reinterpret_cast<void*>( - syscall(SYS_mmap2, start, length, prot, flags, fd, - static_cast<off_t>(offset / pagesize))); -#endif -#elif defined(__s390x__) - // On s390x, mmap() arguments are passed in memory. - unsigned long buf[6] = {reinterpret_cast<unsigned long>(start), // NOLINT - static_cast<unsigned long>(length), // NOLINT - static_cast<unsigned long>(prot), // NOLINT - static_cast<unsigned long>(flags), // NOLINT - static_cast<unsigned long>(fd), // NOLINT - static_cast<unsigned long>(offset)}; // NOLINT - return reinterpret_cast<void*>(syscall(SYS_mmap, buf)); -#elif defined(__x86_64__) -// The x32 ABI has 32 bit longs, but the syscall interface is 64 bit. -// We need to explicitly cast to an unsigned 64 bit type to avoid implicit -// sign extension. We can't cast pointers directly because those are -// 32 bits, and gcc will dump ugly warnings about casting from a pointer -// to an integer of a different size. We also need to make sure __off64_t -// isn't truncated to 32-bits under x32. -#define MMAP_SYSCALL_ARG(x) ((uint64_t)(uintptr_t)(x)) - return reinterpret_cast<void*>( - syscall(SYS_mmap, MMAP_SYSCALL_ARG(start), MMAP_SYSCALL_ARG(length), - MMAP_SYSCALL_ARG(prot), MMAP_SYSCALL_ARG(flags), - MMAP_SYSCALL_ARG(fd), static_cast<uint64_t>(offset))); -#undef MMAP_SYSCALL_ARG -#else // Remaining 64-bit aritectures. - static_assert(sizeof(unsigned long) == 8, "Platform is not 64-bit"); - return reinterpret_cast<void*>( - syscall(SYS_mmap, start, length, prot, flags, fd, offset)); -#endif -} - -inline int DirectMunmap(void* start, size_t length) { - return static_cast<int>(syscall(SYS_munmap, start, length)); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#else // !__linux__ - -// For non-linux platforms where we have mmap, just dispatch directly to the -// actual mmap()/munmap() methods. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - return mmap(start, length, prot, flags, fd, offset); -} - -inline int DirectMunmap(void* start, size_t length) { - return munmap(start, length); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // __linux__ - -#endif // ABSL_HAVE_MMAP - -#endif // ABSL_BASE_INTERNAL_DIRECT_MMAP_H_ 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 b23c5ec1c41e..000000000000 --- 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 deleted file mode 100644 index 9677530e8de3..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/endian.h +++ /dev/null @@ -1,266 +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. -// - -#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_ -#define ABSL_BASE_INTERNAL_ENDIAN_H_ - -// The following guarantees declaration of the byte swap functions -#ifdef _MSC_VER -#include <stdlib.h> // NOLINT(build/include) -#elif defined(__FreeBSD__) -#include <sys/endian.h> -#elif defined(__GLIBC__) -#include <byteswap.h> // IWYU pragma: export -#endif - -#include <cstdint> -#include "absl/base/config.h" -#include "absl/base/internal/unaligned_access.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Use compiler byte-swapping intrinsics if they are available. 32-bit -// and 64-bit versions are available in Clang and GCC as of GCC 4.3.0. -// The 16-bit version is available in Clang and GCC only as of GCC 4.8.0. -// For simplicity, we enable them all only for GCC 4.8.0 or later. -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5)) -inline uint64_t gbswap_64(uint64_t host_int) { - return __builtin_bswap64(host_int); -} -inline uint32_t gbswap_32(uint32_t host_int) { - return __builtin_bswap32(host_int); -} -inline uint16_t gbswap_16(uint16_t host_int) { - return __builtin_bswap16(host_int); -} - -#elif defined(_MSC_VER) -inline uint64_t gbswap_64(uint64_t host_int) { - return _byteswap_uint64(host_int); -} -inline uint32_t gbswap_32(uint32_t host_int) { - return _byteswap_ulong(host_int); -} -inline uint16_t gbswap_16(uint16_t host_int) { - return _byteswap_ushort(host_int); -} - -#else -inline uint64_t gbswap_64(uint64_t host_int) { -#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__) - // Adapted from /usr/include/byteswap.h. Not available on Mac. - if (__builtin_constant_p(host_int)) { - return __bswap_constant_64(host_int); - } else { - uint64_t result; - __asm__("bswap %0" : "=r"(result) : "0"(host_int)); - return result; - } -#elif defined(__GLIBC__) - return bswap_64(host_int); -#else - return (((host_int & uint64_t{0xFF}) << 56) | - ((host_int & uint64_t{0xFF00}) << 40) | - ((host_int & uint64_t{0xFF0000}) << 24) | - ((host_int & uint64_t{0xFF000000}) << 8) | - ((host_int & uint64_t{0xFF00000000}) >> 8) | - ((host_int & uint64_t{0xFF0000000000}) >> 24) | - ((host_int & uint64_t{0xFF000000000000}) >> 40) | - ((host_int & uint64_t{0xFF00000000000000}) >> 56)); -#endif // bswap_64 -} - -inline uint32_t gbswap_32(uint32_t host_int) { -#if defined(__GLIBC__) - return bswap_32(host_int); -#else - return (((host_int & uint32_t{0xFF}) << 24) | - ((host_int & uint32_t{0xFF00}) << 8) | - ((host_int & uint32_t{0xFF0000}) >> 8) | - ((host_int & uint32_t{0xFF000000}) >> 24)); -#endif -} - -inline uint16_t gbswap_16(uint16_t host_int) { -#if defined(__GLIBC__) - return bswap_16(host_int); -#else - return (((host_int & uint16_t{0xFF}) << 8) | - ((host_int & uint16_t{0xFF00}) >> 8)); -#endif -} - -#endif // intrinsics available - -#ifdef ABSL_IS_LITTLE_ENDIAN - -// Definitions for ntohl etc. that don't require us to include -// netinet/in.h. We wrap gbswap_32 and gbswap_16 in functions rather -// than just #defining them because in debug mode, gcc doesn't -// correctly handle the (rather involved) definitions of bswap_32. -// gcc guarantees that inline functions are as fast as macros, so -// this isn't a performance hit. -inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); } -inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); } -inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); } - -#elif defined ABSL_IS_BIG_ENDIAN - -// These definitions are simpler on big-endian machines -// These are functions instead of macros to avoid self-assignment warnings -// on calls such as "i = ghtnol(i);". This also provides type checking. -inline uint16_t ghtons(uint16_t x) { return x; } -inline uint32_t ghtonl(uint32_t x) { return x; } -inline uint64_t ghtonll(uint64_t x) { return x; } - -#else -#error \ - "Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or " \ - "ABSL_IS_LITTLE_ENDIAN must be defined" -#endif // byte order - -inline uint16_t gntohs(uint16_t x) { return ghtons(x); } -inline uint32_t gntohl(uint32_t x) { return ghtonl(x); } -inline uint64_t gntohll(uint64_t x) { return ghtonll(x); } - -// Utilities to convert numbers between the current hosts's native byte -// order and little-endian byte order -// -// Load/Store methods are alignment safe -namespace little_endian { -// Conversion functions. -#ifdef ABSL_IS_LITTLE_ENDIAN - -inline uint16_t FromHost16(uint16_t x) { return x; } -inline uint16_t ToHost16(uint16_t x) { return x; } - -inline uint32_t FromHost32(uint32_t x) { return x; } -inline uint32_t ToHost32(uint32_t x) { return x; } - -inline uint64_t FromHost64(uint64_t x) { return x; } -inline uint64_t ToHost64(uint64_t x) { return x; } - -inline constexpr bool IsLittleEndian() { return true; } - -#elif defined ABSL_IS_BIG_ENDIAN - -inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); } -inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); } - -inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); } -inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); } - -inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); } -inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); } - -inline constexpr bool IsLittleEndian() { return false; } - -#endif /* ENDIAN */ - -// 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)); -} - -inline void Store16(void *p, uint16_t v) { - ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); -} - -inline uint32_t Load32(const void *p) { - return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); -} - -inline void Store32(void *p, uint32_t v) { - ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); -} - -inline uint64_t Load64(const void *p) { - return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); -} - -inline void Store64(void *p, uint64_t v) { - ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); -} - -} // namespace little_endian - -// Utilities to convert numbers between the current hosts's native byte -// order and big-endian byte order (same as network byte order) -// -// Load/Store methods are alignment safe -namespace big_endian { -#ifdef ABSL_IS_LITTLE_ENDIAN - -inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); } -inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); } - -inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); } -inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); } - -inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); } -inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); } - -inline constexpr bool IsLittleEndian() { return true; } - -#elif defined ABSL_IS_BIG_ENDIAN - -inline uint16_t FromHost16(uint16_t x) { return x; } -inline uint16_t ToHost16(uint16_t x) { return x; } - -inline uint32_t FromHost32(uint32_t x) { return x; } -inline uint32_t ToHost32(uint32_t x) { return x; } - -inline uint64_t FromHost64(uint64_t x) { return x; } -inline uint64_t ToHost64(uint64_t x) { return x; } - -inline constexpr bool IsLittleEndian() { return false; } - -#endif /* ENDIAN */ - -// 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)); -} - -inline void Store16(void *p, uint16_t v) { - ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); -} - -inline uint32_t Load32(const void *p) { - return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); -} - -inline void Store32(void *p, uint32_t v) { - ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); -} - -inline uint64_t Load64(const void *p) { - return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); -} - -inline void Store64(void *p, uint64_t v) { - ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); -} - -} // namespace big_endian - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_ENDIAN_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/endian_test.cc b/third_party/abseil_cpp/absl/base/internal/endian_test.cc deleted file mode 100644 index a1691b1f82c0..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/endian_test.cc +++ /dev/null @@ -1,263 +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/base/internal/endian.h" - -#include <algorithm> -#include <cstdint> -#include <limits> -#include <random> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -const uint64_t kInitialNumber{0x0123456789abcdef}; -const uint64_t k64Value{kInitialNumber}; -const uint32_t k32Value{0x01234567}; -const uint16_t k16Value{0x0123}; -const int kNumValuesToTest = 1000000; -const int kRandomSeed = 12345; - -#if defined(ABSL_IS_BIG_ENDIAN) -const uint64_t kInitialInNetworkOrder{kInitialNumber}; -const uint64_t k64ValueLE{0xefcdab8967452301}; -const uint32_t k32ValueLE{0x67452301}; -const uint16_t k16ValueLE{0x2301}; - -const uint64_t k64ValueBE{kInitialNumber}; -const uint32_t k32ValueBE{k32Value}; -const uint16_t k16ValueBE{k16Value}; -#elif defined(ABSL_IS_LITTLE_ENDIAN) -const uint64_t kInitialInNetworkOrder{0xefcdab8967452301}; -const uint64_t k64ValueLE{kInitialNumber}; -const uint32_t k32ValueLE{k32Value}; -const uint16_t k16ValueLE{k16Value}; - -const uint64_t k64ValueBE{0xefcdab8967452301}; -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)); - } - return result; -} - -template<typename T> -std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) { - std::vector<T> result; - result.reserve(num_values_to_test); - std::mt19937_64 rng(kRandomSeed); - for (size_t i = 0; i < num_values_to_test; ++i) { - result.push_back(rng()); - } - return result; -} - -void ManualByteSwap(char* bytes, int length) { - if (length == 1) - return; - - EXPECT_EQ(0, length % 2); - for (int i = 0; i < length / 2; ++i) { - int j = (length - 1) - i; - using std::swap; - swap(bytes[i], bytes[j]); - } -} - -template<typename T> -inline T UnalignedLoad(const char* p) { - static_assert( - sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, - "Unexpected type size"); - - switch (sizeof(T)) { - case 1: return *reinterpret_cast<const T*>(p); - case 2: - return ABSL_INTERNAL_UNALIGNED_LOAD16(p); - case 4: - return ABSL_INTERNAL_UNALIGNED_LOAD32(p); - case 8: - return ABSL_INTERNAL_UNALIGNED_LOAD64(p); - default: - // Suppresses invalid "not all control paths return a value" on MSVC - return {}; - } -} - -template <typename T, typename ByteSwapper> -static void GBSwapHelper(const std::vector<T>& host_values_to_test, - const ByteSwapper& byte_swapper) { - // Test byte_swapper against a manual byte swap. - for (typename std::vector<T>::const_iterator it = host_values_to_test.begin(); - it != host_values_to_test.end(); ++it) { - T host_value = *it; - - char actual_value[sizeof(host_value)]; - memcpy(actual_value, &host_value, sizeof(host_value)); - byte_swapper(actual_value); - - char expected_value[sizeof(host_value)]; - memcpy(expected_value, &host_value, sizeof(host_value)); - ManualByteSwap(expected_value, sizeof(host_value)); - - ASSERT_EQ(0, memcmp(actual_value, expected_value, sizeof(host_value))) - << "Swap output for 0x" << std::hex << host_value << " does not match. " - << "Expected: 0x" << UnalignedLoad<T>(expected_value) << "; " - << "actual: 0x" << UnalignedLoad<T>(actual_value); - } -} - -void Swap16(char* bytes) { - ABSL_INTERNAL_UNALIGNED_STORE16( - bytes, gbswap_16(ABSL_INTERNAL_UNALIGNED_LOAD16(bytes))); -} - -void Swap32(char* bytes) { - ABSL_INTERNAL_UNALIGNED_STORE32( - bytes, gbswap_32(ABSL_INTERNAL_UNALIGNED_LOAD32(bytes))); -} - -void Swap64(char* bytes) { - ABSL_INTERNAL_UNALIGNED_STORE64( - bytes, gbswap_64(ABSL_INTERNAL_UNALIGNED_LOAD64(bytes))); -} - -TEST(EndianessTest, Uint16) { - GBSwapHelper(GenerateAllUint16Values(), &Swap16); -} - -TEST(EndianessTest, Uint32) { - GBSwapHelper(GenerateRandomIntegers<uint32_t>(kNumValuesToTest), &Swap32); -} - -TEST(EndianessTest, Uint64) { - GBSwapHelper(GenerateRandomIntegers<uint64_t>(kNumValuesToTest), &Swap64); -} - -TEST(EndianessTest, ghtonll_gntohll) { - // Test that absl::ghtonl compiles correctly - uint32_t test = 0x01234567; - EXPECT_EQ(absl::gntohl(absl::ghtonl(test)), test); - - uint64_t comp = absl::ghtonll(kInitialNumber); - EXPECT_EQ(comp, kInitialInNetworkOrder); - comp = absl::gntohll(kInitialInNetworkOrder); - EXPECT_EQ(comp, kInitialNumber); - - // Test that htonll and ntohll are each others' inverse functions on a - // somewhat assorted batch of numbers. 37 is chosen to not be anything - // particularly nice base 2. - uint64_t value = 1; - for (int i = 0; i < 100; ++i) { - comp = absl::ghtonll(absl::gntohll(value)); - EXPECT_EQ(value, comp); - comp = absl::gntohll(absl::ghtonll(value)); - EXPECT_EQ(value, comp); - value *= 37; - } -} - -TEST(EndianessTest, little_endian) { - // Check little_endian uint16_t. - uint64_t comp = little_endian::FromHost16(k16Value); - EXPECT_EQ(comp, k16ValueLE); - comp = little_endian::ToHost16(k16ValueLE); - EXPECT_EQ(comp, k16Value); - - // Check little_endian uint32_t. - comp = little_endian::FromHost32(k32Value); - EXPECT_EQ(comp, k32ValueLE); - comp = little_endian::ToHost32(k32ValueLE); - EXPECT_EQ(comp, k32Value); - - // Check little_endian uint64_t. - comp = little_endian::FromHost64(k64Value); - EXPECT_EQ(comp, k64ValueLE); - comp = little_endian::ToHost64(k64ValueLE); - EXPECT_EQ(comp, k64Value); - - // Check little-endian Load and store functions. - uint16_t u16Buf; - uint32_t u32Buf; - uint64_t u64Buf; - - little_endian::Store16(&u16Buf, k16Value); - EXPECT_EQ(u16Buf, k16ValueLE); - comp = little_endian::Load16(&u16Buf); - EXPECT_EQ(comp, k16Value); - - little_endian::Store32(&u32Buf, k32Value); - EXPECT_EQ(u32Buf, k32ValueLE); - comp = little_endian::Load32(&u32Buf); - EXPECT_EQ(comp, k32Value); - - little_endian::Store64(&u64Buf, k64Value); - EXPECT_EQ(u64Buf, k64ValueLE); - comp = little_endian::Load64(&u64Buf); - EXPECT_EQ(comp, k64Value); -} - -TEST(EndianessTest, big_endian) { - // Check big-endian Load and store functions. - uint16_t u16Buf; - uint32_t u32Buf; - uint64_t u64Buf; - - unsigned char buffer[10]; - big_endian::Store16(&u16Buf, k16Value); - EXPECT_EQ(u16Buf, k16ValueBE); - uint64_t comp = big_endian::Load16(&u16Buf); - EXPECT_EQ(comp, k16Value); - - big_endian::Store32(&u32Buf, k32Value); - EXPECT_EQ(u32Buf, k32ValueBE); - comp = big_endian::Load32(&u32Buf); - EXPECT_EQ(comp, k32Value); - - big_endian::Store64(&u64Buf, k64Value); - EXPECT_EQ(u64Buf, k64ValueBE); - comp = big_endian::Load64(&u64Buf); - EXPECT_EQ(comp, k64Value); - - big_endian::Store16(buffer + 1, k16Value); - EXPECT_EQ(u16Buf, k16ValueBE); - comp = big_endian::Load16(buffer + 1); - EXPECT_EQ(comp, k16Value); - - big_endian::Store32(buffer + 1, k32Value); - EXPECT_EQ(u32Buf, k32ValueBE); - comp = big_endian::Load32(buffer + 1); - EXPECT_EQ(comp, k32Value); - - big_endian::Store64(buffer + 1, k64Value); - EXPECT_EQ(u64Buf, k64ValueBE); - comp = big_endian::Load64(buffer + 1); - EXPECT_EQ(comp, k64Value); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/errno_saver.h b/third_party/abseil_cpp/absl/base/internal/errno_saver.h deleted file mode 100644 index 251de510fc93..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/errno_saver.h +++ /dev/null @@ -1,43 +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. - -#ifndef ABSL_BASE_INTERNAL_ERRNO_SAVER_H_ -#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_ - -#include <cerrno> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// `ErrnoSaver` captures the value of `errno` upon construction and restores it -// upon deletion. It is used in low-level code and must be super fast. Do not -// add instrumentation, even in debug modes. -class ErrnoSaver { - public: - ErrnoSaver() : saved_errno_(errno) {} - ~ErrnoSaver() { errno = saved_errno_; } - int operator()() const { return saved_errno_; } - - private: - const int saved_errno_; -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/errno_saver_test.cc b/third_party/abseil_cpp/absl/base/internal/errno_saver_test.cc deleted file mode 100644 index e9b742c588b0..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/errno_saver_test.cc +++ /dev/null @@ -1,45 +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/base/internal/errno_saver.h" - -#include <cerrno> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/strerror.h" - -namespace { -using ::testing::Eq; - -struct ErrnoPrinter { - int no; -}; -std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) { - return os << absl::base_internal::StrError(ep.no) << " [" << ep.no << "]"; -} -bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; } - -TEST(ErrnoSaverTest, Works) { - errno = EDOM; - { - absl::base_internal::ErrnoSaver errno_saver; - EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM})); - errno = ERANGE; - EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{ERANGE})); - EXPECT_THAT(ErrnoPrinter{errno_saver()}, Eq(ErrnoPrinter{EDOM})); - } - EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM})); -} -} // namespace diff --git a/third_party/abseil_cpp/absl/base/internal/exception_safety_testing.cc b/third_party/abseil_cpp/absl/base/internal/exception_safety_testing.cc deleted file mode 100644 index 6ccac41864b1..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exception_safety_testing.cc +++ /dev/null @@ -1,79 +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/base/internal/exception_safety_testing.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" - -namespace testing { - -exceptions_internal::NoThrowTag nothrow_ctor; - -exceptions_internal::StrongGuaranteeTagType strong_guarantee; - -exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester() { - return {}; -} - -namespace exceptions_internal { - -int countdown = -1; - -ConstructorTracker* ConstructorTracker::current_tracker_instance_ = nullptr; - -void MaybeThrow(absl::string_view msg, bool throw_bad_alloc) { - if (countdown-- == 0) { - if (throw_bad_alloc) throw TestBadAllocException(msg); - throw TestException(msg); - } -} - -testing::AssertionResult FailureMessage(const TestException& e, - int countdown) noexcept { - return testing::AssertionFailure() << "Exception thrown from " << e.what(); -} - -std::string GetSpecString(TypeSpec spec) { - std::string out; - absl::string_view sep; - const auto append = [&](absl::string_view s) { - absl::StrAppend(&out, sep, s); - sep = " | "; - }; - if (static_cast<bool>(TypeSpec::kNoThrowCopy & spec)) { - append("kNoThrowCopy"); - } - if (static_cast<bool>(TypeSpec::kNoThrowMove & spec)) { - append("kNoThrowMove"); - } - if (static_cast<bool>(TypeSpec::kNoThrowNew & spec)) { - append("kNoThrowNew"); - } - return out; -} - -std::string GetSpecString(AllocSpec spec) { - return static_cast<bool>(AllocSpec::kNoThrowAllocate & spec) - ? "kNoThrowAllocate" - : ""; -} - -} // namespace exceptions_internal - -} // namespace testing - -#endif // ABSL_HAVE_EXCEPTIONS 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 deleted file mode 100644 index 6ba89d05dfca..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exception_safety_testing.h +++ /dev/null @@ -1,1101 +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. - -// Utilities for testing exception-safety - -#ifndef ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_ -#define ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_ - -#include "absl/base/config.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include <cstddef> -#include <cstdint> -#include <functional> -#include <initializer_list> -#include <iosfwd> -#include <string> -#include <tuple> -#include <unordered_map> - -#include "gtest/gtest.h" -#include "absl/base/internal/pretty_function.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" -#include "absl/strings/substitute.h" -#include "absl/utility/utility.h" - -namespace testing { - -enum class TypeSpec; -enum class AllocSpec; - -constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) { - using T = absl::underlying_type_t<TypeSpec>; - return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b)); -} - -constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) { - using T = absl::underlying_type_t<TypeSpec>; - return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b)); -} - -constexpr AllocSpec operator|(AllocSpec a, AllocSpec b) { - using T = absl::underlying_type_t<AllocSpec>; - return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b)); -} - -constexpr AllocSpec operator&(AllocSpec a, AllocSpec b) { - using T = absl::underlying_type_t<AllocSpec>; - return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b)); -} - -namespace exceptions_internal { - -std::string GetSpecString(TypeSpec); -std::string GetSpecString(AllocSpec); - -struct NoThrowTag {}; -struct StrongGuaranteeTagType {}; - -// A simple exception class. We throw this so that test code can catch -// exceptions specifically thrown by ThrowingValue. -class TestException { - public: - explicit TestException(absl::string_view msg) : msg_(msg) {} - virtual ~TestException() {} - virtual const char* what() const noexcept { return msg_.c_str(); } - - private: - std::string msg_; -}; - -// TestBadAllocException exists because allocation functions must throw an -// exception which can be caught by a handler of std::bad_alloc. We use a child -// class of std::bad_alloc so we can customise the error message, and also -// derive from TestException so we don't accidentally end up catching an actual -// bad_alloc exception in TestExceptionSafety. -class TestBadAllocException : public std::bad_alloc, public TestException { - public: - explicit TestBadAllocException(absl::string_view msg) : TestException(msg) {} - using TestException::what; -}; - -extern int countdown; - -// Allows the countdown variable to be set manually (defaulting to the initial -// value of 0) -inline void SetCountdown(int i = 0) { countdown = i; } -// Sets the countdown to the terminal value -1 -inline void UnsetCountdown() { SetCountdown(-1); } - -void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false); - -testing::AssertionResult FailureMessage(const TestException& e, - int countdown) noexcept; - -struct TrackedAddress { - bool is_alive; - std::string description; -}; - -// Inspects the constructions and destructions of anything inheriting from -// TrackedObject. This allows us to safely "leak" TrackedObjects, as -// ConstructorTracker will destroy everything left over in its destructor. -class ConstructorTracker { - public: - explicit ConstructorTracker(int count) : countdown_(count) { - assert(current_tracker_instance_ == nullptr); - current_tracker_instance_ = this; - } - - ~ConstructorTracker() { - assert(current_tracker_instance_ == this); - current_tracker_instance_ = nullptr; - - for (auto& it : address_map_) { - void* address = it.first; - TrackedAddress& tracked_address = it.second; - if (tracked_address.is_alive) { - ADD_FAILURE() << ErrorMessage(address, tracked_address.description, - countdown_, "Object was not destroyed."); - } - } - } - - static void ObjectConstructed(void* address, std::string description) { - if (!CurrentlyTracking()) return; - - TrackedAddress& tracked_address = - current_tracker_instance_->address_map_[address]; - if (tracked_address.is_alive) { - ADD_FAILURE() << ErrorMessage( - address, tracked_address.description, - current_tracker_instance_->countdown_, - "Object was re-constructed. Current object was constructed by " + - description); - } - tracked_address = {true, std::move(description)}; - } - - static void ObjectDestructed(void* address) { - if (!CurrentlyTracking()) return; - - auto it = current_tracker_instance_->address_map_.find(address); - // Not tracked. Ignore. - if (it == current_tracker_instance_->address_map_.end()) return; - - TrackedAddress& tracked_address = it->second; - if (!tracked_address.is_alive) { - ADD_FAILURE() << ErrorMessage(address, tracked_address.description, - current_tracker_instance_->countdown_, - "Object was re-destroyed."); - } - tracked_address.is_alive = false; - } - - private: - static bool CurrentlyTracking() { - return current_tracker_instance_ != nullptr; - } - - static std::string ErrorMessage(void* address, - const std::string& address_description, - int countdown, - const std::string& error_description) { - return absl::Substitute( - "With coundtown at $0:\n" - " $1\n" - " Object originally constructed by $2\n" - " Object address: $3\n", - countdown, error_description, address_description, address); - } - - std::unordered_map<void*, TrackedAddress> address_map_; - int countdown_; - - static ConstructorTracker* current_tracker_instance_; -}; - -class TrackedObject { - public: - TrackedObject(const TrackedObject&) = delete; - TrackedObject(TrackedObject&&) = delete; - - protected: - explicit TrackedObject(std::string description) { - ConstructorTracker::ObjectConstructed(this, std::move(description)); - } - - ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); } -}; -} // namespace exceptions_internal - -extern exceptions_internal::NoThrowTag nothrow_ctor; - -extern exceptions_internal::StrongGuaranteeTagType strong_guarantee; - -// A test class which is convertible to bool. The conversion can be -// instrumented to throw at a controlled time. -class ThrowingBool { - public: - ThrowingBool(bool b) noexcept : b_(b) {} // NOLINT(runtime/explicit) - operator bool() const { // NOLINT - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return b_; - } - - private: - bool b_; -}; - -/* - * Configuration enum for the ThrowingValue type that defines behavior for the - * lifetime of the instance. Use testing::nothrow_ctor to prevent the integer - * constructor from throwing. - * - * kEverythingThrows: Every operation can throw an exception - * kNoThrowCopy: Copy construction and copy assignment will not throw - * kNoThrowMove: Move construction and move assignment will not throw - * kNoThrowNew: Overloaded operators new and new[] will not throw - */ -enum class TypeSpec { - kEverythingThrows = 0, - kNoThrowCopy = 1, - kNoThrowMove = 1 << 1, - kNoThrowNew = 1 << 2, -}; - -/* - * A testing class instrumented to throw an exception at a controlled time. - * - * ThrowingValue implements a slightly relaxed version of the Regular concept -- - * that is it's a value type with the expected semantics. It also implements - * arithmetic operations. It doesn't implement member and pointer operators - * like operator-> or operator[]. - * - * ThrowingValue can be instrumented to have certain operations be noexcept by - * using compile-time bitfield template arguments. That is, to make an - * ThrowingValue which has noexcept move construction/assignment and noexcept - * copy construction/assignment, use the following: - * ThrowingValue<testing::kNoThrowMove | testing::kNoThrowCopy> my_thrwr{val}; - */ -template <TypeSpec Spec = TypeSpec::kEverythingThrows> -class ThrowingValue : private exceptions_internal::TrackedObject { - static constexpr bool IsSpecified(TypeSpec spec) { - return static_cast<bool>(Spec & spec); - } - - static constexpr int kDefaultValue = 0; - static constexpr int kBadValue = 938550620; - - public: - ThrowingValue() : TrackedObject(GetInstanceString(kDefaultValue)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ = kDefaultValue; - } - - ThrowingValue(const ThrowingValue& other) noexcept( - IsSpecified(TypeSpec::kNoThrowCopy)) - : TrackedObject(GetInstanceString(other.dummy_)) { - if (!IsSpecified(TypeSpec::kNoThrowCopy)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - } - dummy_ = other.dummy_; - } - - ThrowingValue(ThrowingValue&& other) noexcept( - IsSpecified(TypeSpec::kNoThrowMove)) - : TrackedObject(GetInstanceString(other.dummy_)) { - if (!IsSpecified(TypeSpec::kNoThrowMove)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - } - dummy_ = other.dummy_; - } - - explicit ThrowingValue(int i) : TrackedObject(GetInstanceString(i)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ = i; - } - - ThrowingValue(int i, exceptions_internal::NoThrowTag) noexcept - : TrackedObject(GetInstanceString(i)), dummy_(i) {} - - // absl expects nothrow destructors - ~ThrowingValue() noexcept = default; - - ThrowingValue& operator=(const ThrowingValue& other) noexcept( - IsSpecified(TypeSpec::kNoThrowCopy)) { - dummy_ = kBadValue; - if (!IsSpecified(TypeSpec::kNoThrowCopy)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - } - dummy_ = other.dummy_; - return *this; - } - - ThrowingValue& operator=(ThrowingValue&& other) noexcept( - IsSpecified(TypeSpec::kNoThrowMove)) { - dummy_ = kBadValue; - if (!IsSpecified(TypeSpec::kNoThrowMove)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - } - dummy_ = other.dummy_; - return *this; - } - - // Arithmetic Operators - ThrowingValue operator+(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor); - } - - ThrowingValue operator+() const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_, nothrow_ctor); - } - - ThrowingValue operator-(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor); - } - - ThrowingValue operator-() const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(-dummy_, nothrow_ctor); - } - - ThrowingValue& operator++() { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - ++dummy_; - return *this; - } - - ThrowingValue operator++(int) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - auto out = ThrowingValue(dummy_, nothrow_ctor); - ++dummy_; - return out; - } - - ThrowingValue& operator--() { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - --dummy_; - return *this; - } - - ThrowingValue operator--(int) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - auto out = ThrowingValue(dummy_, nothrow_ctor); - --dummy_; - return out; - } - - ThrowingValue operator*(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ * other.dummy_, nothrow_ctor); - } - - ThrowingValue operator/(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ / other.dummy_, nothrow_ctor); - } - - ThrowingValue operator%(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ % other.dummy_, nothrow_ctor); - } - - ThrowingValue operator<<(int shift) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ << shift, nothrow_ctor); - } - - ThrowingValue operator>>(int shift) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ >> shift, nothrow_ctor); - } - - // Comparison Operators - // NOTE: We use `ThrowingBool` instead of `bool` because most STL - // types/containers requires T to be convertible to bool. - friend ThrowingBool operator==(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ == b.dummy_; - } - friend ThrowingBool operator!=(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ != b.dummy_; - } - friend ThrowingBool operator<(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ < b.dummy_; - } - friend ThrowingBool operator<=(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ <= b.dummy_; - } - friend ThrowingBool operator>(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ > b.dummy_; - } - friend ThrowingBool operator>=(const ThrowingValue& a, - const ThrowingValue& b) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return a.dummy_ >= b.dummy_; - } - - // Logical Operators - ThrowingBool operator!() const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return !dummy_; - } - - ThrowingBool operator&&(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return dummy_ && other.dummy_; - } - - ThrowingBool operator||(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return dummy_ || other.dummy_; - } - - // Bitwise Logical Operators - ThrowingValue operator~() const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(~dummy_, nothrow_ctor); - } - - ThrowingValue operator&(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ & other.dummy_, nothrow_ctor); - } - - ThrowingValue operator|(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ | other.dummy_, nothrow_ctor); - } - - ThrowingValue operator^(const ThrowingValue& other) const { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor); - } - - // Compound Assignment operators - ThrowingValue& operator+=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ += other.dummy_; - return *this; - } - - ThrowingValue& operator-=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ -= other.dummy_; - return *this; - } - - ThrowingValue& operator*=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ *= other.dummy_; - return *this; - } - - ThrowingValue& operator/=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ /= other.dummy_; - return *this; - } - - ThrowingValue& operator%=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ %= other.dummy_; - return *this; - } - - ThrowingValue& operator&=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ &= other.dummy_; - return *this; - } - - ThrowingValue& operator|=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ |= other.dummy_; - return *this; - } - - ThrowingValue& operator^=(const ThrowingValue& other) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ ^= other.dummy_; - return *this; - } - - ThrowingValue& operator<<=(int shift) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ <<= shift; - return *this; - } - - ThrowingValue& operator>>=(int shift) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ >>= shift; - return *this; - } - - // Pointer operators - void operator&() const = delete; // NOLINT(runtime/operator) - - // Stream operators - friend std::ostream& operator<<(std::ostream& os, const ThrowingValue& tv) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return os << GetInstanceString(tv.dummy_); - } - - friend std::istream& operator>>(std::istream& is, const ThrowingValue&) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - return is; - } - - // Memory management operators - // 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)) { - if (!IsSpecified(TypeSpec::kNoThrowNew)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); - } - return ::operator new(s, std::forward<Args>(args)...); - } - - template <typename... Args> - static void* operator new[](size_t s, Args&&... args) noexcept( - IsSpecified(TypeSpec::kNoThrowNew)) { - if (!IsSpecified(TypeSpec::kNoThrowNew)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true); - } - return ::operator new[](s, std::forward<Args>(args)...); - } - - // Abseil doesn't support throwing overloaded operator delete. These are - // provided so a throwing operator-new can clean up after itself. - // - // 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> - void operator delete(void* p, Args&&... args) noexcept { - ::operator delete(p, std::forward<Args>(args)...); - } - - void operator delete[](void* p) noexcept { return ::operator delete[](p); } - - template <typename... Args> - void operator delete[](void* p, Args&&... args) noexcept { - return ::operator delete[](p, std::forward<Args>(args)...); - } - - // Non-standard access to the actual contained value. No need for this to - // throw. - int& Get() noexcept { return dummy_; } - const int& Get() const noexcept { return dummy_; } - - private: - static std::string GetInstanceString(int dummy) { - return absl::StrCat("ThrowingValue<", - exceptions_internal::GetSpecString(Spec), ">(", dummy, - ")"); - } - - int dummy_; -}; -// While not having to do with exceptions, explicitly delete comma operator, to -// make sure we don't use it on user-supplied types. -template <TypeSpec Spec, typename T> -void operator,(const ThrowingValue<Spec>&, T&&) = delete; -template <TypeSpec Spec, typename T> -void operator,(T&&, const ThrowingValue<Spec>&) = delete; - -/* - * Configuration enum for the ThrowingAllocator type that defines behavior for - * the lifetime of the instance. - * - * kEverythingThrows: Calls to the member functions may throw - * kNoThrowAllocate: Calls to the member functions will not throw - */ -enum class AllocSpec { - kEverythingThrows = 0, - kNoThrowAllocate = 1, -}; - -/* - * An allocator type which is instrumented to throw at a controlled time, or not - * to throw, using AllocSpec. The supported settings are the default of every - * function which is allowed to throw in a conforming allocator possibly - * throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS - * configuration macro. - */ -template <typename T, AllocSpec Spec = AllocSpec::kEverythingThrows> -class ThrowingAllocator : private exceptions_internal::TrackedObject { - static constexpr bool IsSpecified(AllocSpec spec) { - return static_cast<bool>(Spec & spec); - } - - public: - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using void_pointer = void*; - using const_void_pointer = const void*; - using value_type = T; - using size_type = size_t; - using difference_type = ptrdiff_t; - - using is_nothrow = - std::integral_constant<bool, Spec == AllocSpec::kNoThrowAllocate>; - using propagate_on_container_copy_assignment = std::true_type; - using propagate_on_container_move_assignment = std::true_type; - using propagate_on_container_swap = std::true_type; - using is_always_equal = std::false_type; - - ThrowingAllocator() : TrackedObject(GetInstanceString(next_id_)) { - exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION); - dummy_ = std::make_shared<const int>(next_id_++); - } - - template <typename U> - ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept // NOLINT - : TrackedObject(GetInstanceString(*other.State())), - dummy_(other.State()) {} - - // According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of - // allocator shall not exit via an exception, thus they are marked noexcept. - ThrowingAllocator(const ThrowingAllocator& other) noexcept - : TrackedObject(GetInstanceString(*other.State())), - dummy_(other.State()) {} - - template <typename U> - ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept // NOLINT - : TrackedObject(GetInstanceString(*other.State())), - dummy_(std::move(other.State())) {} - - ThrowingAllocator(ThrowingAllocator&& other) noexcept - : TrackedObject(GetInstanceString(*other.State())), - dummy_(std::move(other.State())) {} - - ~ThrowingAllocator() noexcept = default; - - ThrowingAllocator& operator=(const ThrowingAllocator& other) noexcept { - dummy_ = other.State(); - return *this; - } - - template <typename U> - ThrowingAllocator& operator=( - const ThrowingAllocator<U, Spec>& other) noexcept { - dummy_ = other.State(); - return *this; - } - - template <typename U> - ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept { - dummy_ = std::move(other.State()); - return *this; - } - - template <typename U> - struct rebind { - using other = ThrowingAllocator<U, Spec>; - }; - - pointer allocate(size_type n) noexcept( - IsSpecified(AllocSpec::kNoThrowAllocate)) { - ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); - return static_cast<pointer>(::operator new(n * sizeof(T))); - } - - pointer allocate(size_type n, const_void_pointer) noexcept( - IsSpecified(AllocSpec::kNoThrowAllocate)) { - return allocate(n); - } - - void deallocate(pointer ptr, size_type) noexcept { - ReadState(); - ::operator delete(static_cast<void*>(ptr)); - } - - template <typename U, typename... Args> - void construct(U* ptr, Args&&... args) noexcept( - IsSpecified(AllocSpec::kNoThrowAllocate)) { - ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); - ::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...); - } - - template <typename U> - void destroy(U* p) noexcept { - ReadState(); - p->~U(); - } - - size_type max_size() const noexcept { - return (std::numeric_limits<difference_type>::max)() / sizeof(value_type); - } - - ThrowingAllocator select_on_container_copy_construction() noexcept( - IsSpecified(AllocSpec::kNoThrowAllocate)) { - auto& out = *this; - ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION); - return out; - } - - template <typename U> - bool operator==(const ThrowingAllocator<U, Spec>& other) const noexcept { - return dummy_ == other.dummy_; - } - - template <typename U> - bool operator!=(const ThrowingAllocator<U, Spec>& other) const noexcept { - return dummy_ != other.dummy_; - } - - template <typename, AllocSpec> - friend class ThrowingAllocator; - - private: - static std::string GetInstanceString(int dummy) { - return absl::StrCat("ThrowingAllocator<", - exceptions_internal::GetSpecString(Spec), ">(", dummy, - ")"); - } - - const std::shared_ptr<const int>& State() const { return dummy_; } - std::shared_ptr<const int>& State() { return dummy_; } - - void ReadState() { - // we know that this will never be true, but the compiler doesn't, so this - // should safely force a read of the value. - if (*dummy_ < 0) std::abort(); - } - - void ReadStateAndMaybeThrow(absl::string_view msg) const { - if (!IsSpecified(AllocSpec::kNoThrowAllocate)) { - exceptions_internal::MaybeThrow( - absl::Substitute("Allocator id $0 threw from $1", *dummy_, msg)); - } - } - - static int next_id_; - std::shared_ptr<const int> dummy_; -}; - -template <typename T, AllocSpec Spec> -int ThrowingAllocator<T, Spec>::next_id_ = 0; - -// Tests for resource leaks by attempting to construct a T using args repeatedly -// until successful, using the countdown method. Side effects can then be -// tested for resource leaks. -template <typename T, typename... Args> -void TestThrowingCtor(Args&&... args) { - struct Cleanup { - ~Cleanup() { exceptions_internal::UnsetCountdown(); } - } c; - for (int count = 0;; ++count) { - exceptions_internal::ConstructorTracker ct(count); - exceptions_internal::SetCountdown(count); - try { - T temp(std::forward<Args>(args)...); - static_cast<void>(temp); - break; - } catch (const exceptions_internal::TestException&) { - } - } -} - -// Tests the nothrow guarantee of the provided nullary operation. If the an -// exception is thrown, the result will be AssertionFailure(). Otherwise, it -// will be AssertionSuccess(). -template <typename Operation> -testing::AssertionResult TestNothrowOp(const Operation& operation) { - struct Cleanup { - Cleanup() { exceptions_internal::SetCountdown(); } - ~Cleanup() { exceptions_internal::UnsetCountdown(); } - } c; - try { - operation(); - return testing::AssertionSuccess(); - } catch (const exceptions_internal::TestException&) { - return testing::AssertionFailure() - << "TestException thrown during call to operation() when nothrow " - "guarantee was expected."; - } catch (...) { - return testing::AssertionFailure() - << "Unknown exception thrown during call to operation() when " - "nothrow guarantee was expected."; - } -} - -namespace exceptions_internal { - -// Dummy struct for ExceptionSafetyTestBuilder<> partial state. -struct UninitializedT {}; - -template <typename T> -class DefaultFactory { - public: - explicit DefaultFactory(const T& t) : t_(t) {} - std::unique_ptr<T> operator()() const { return absl::make_unique<T>(t_); } - - private: - T t_; -}; - -template <size_t LazyContractsCount, typename LazyFactory, - typename LazyOperation> -using EnableIfTestable = typename absl::enable_if_t< - LazyContractsCount != 0 && - !std::is_same<LazyFactory, UninitializedT>::value && - !std::is_same<LazyOperation, UninitializedT>::value>; - -template <typename Factory = UninitializedT, - typename Operation = UninitializedT, typename... Contracts> -class ExceptionSafetyTestBuilder; - -} // namespace exceptions_internal - -/* - * Constructs an empty ExceptionSafetyTestBuilder. All - * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation - * methods return new instances of ExceptionSafetyTestBuilder. - * - * In order to test a T for exception safety, a factory for that T, a testable - * operation, and at least one contract callback returning an assertion - * result must be applied using the respective methods. - */ -exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester(); - -namespace exceptions_internal { -template <typename T> -struct IsUniquePtr : std::false_type {}; - -template <typename T, typename D> -struct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {}; - -template <typename Factory> -struct FactoryPtrTypeHelper { - using type = decltype(std::declval<const Factory&>()()); - - static_assert(IsUniquePtr<type>::value, "Factories must return a unique_ptr"); -}; - -template <typename Factory> -using FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type; - -template <typename Factory> -using FactoryElementType = typename FactoryPtrType<Factory>::element_type; - -template <typename T> -class ExceptionSafetyTest { - using Factory = std::function<std::unique_ptr<T>()>; - using Operation = std::function<void(T*)>; - using Contract = std::function<AssertionResult(T*)>; - - public: - template <typename... Contracts> - explicit ExceptionSafetyTest(const Factory& f, const Operation& op, - const Contracts&... contracts) - : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {} - - AssertionResult Test() const { - for (int count = 0;; ++count) { - exceptions_internal::ConstructorTracker ct(count); - - for (const auto& contract : contracts_) { - auto t_ptr = factory_(); - try { - SetCountdown(count); - operation_(t_ptr.get()); - // Unset for the case that the operation throws no exceptions, which - // would leave the countdown set and break the *next* exception safety - // test after this one. - UnsetCountdown(); - return AssertionSuccess(); - } catch (const exceptions_internal::TestException& e) { - if (!contract(t_ptr.get())) { - return AssertionFailure() << e.what() << " failed contract check"; - } - } - } - } - } - - private: - template <typename ContractFn> - Contract WrapContract(const ContractFn& contract) { - return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); }; - } - - Contract WrapContract(StrongGuaranteeTagType) { - return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); }; - } - - Factory factory_; - Operation operation_; - std::vector<Contract> contracts_; -}; - -/* - * Builds a tester object that tests if performing a operation on a T follows - * exception safety guarantees. Verification is done via contract assertion - * callbacks applied to T instances post-throw. - * - * Template parameters for ExceptionSafetyTestBuilder: - * - * - Factory: The factory object (passed in via tester.WithFactory(...) or - * tester.WithInitialValue(...)) must be invocable with the signature - * `std::unique_ptr<T> operator()() const` where T is the type being tested. - * It is used for reliably creating identical T instances to test on. - * - * - Operation: The operation object (passsed in via tester.WithOperation(...) - * or tester.Test(...)) must be invocable with the signature - * `void operator()(T*) const` where T is the type being tested. It is used - * for performing steps on a T instance that may throw and that need to be - * checked for exception safety. Each call to the operation will receive a - * fresh T instance so it's free to modify and destroy the T instances as it - * pleases. - * - * - Contracts...: The contract assertion callback objects (passed in via - * tester.WithContracts(...)) must be invocable with the signature - * `testing::AssertionResult operator()(T*) const` where T is the type being - * tested. Contract assertion callbacks are provided T instances post-throw. - * They must return testing::AssertionSuccess when the type contracts of the - * provided T instance hold. If the type contracts of the T instance do not - * hold, they must return testing::AssertionFailure. Execution order of - * Contracts... is unspecified. They will each individually get a fresh T - * instance so they are free to modify and destroy the T instances as they - * please. - */ -template <typename Factory, typename Operation, typename... Contracts> -class ExceptionSafetyTestBuilder { - public: - /* - * Returns a new ExceptionSafetyTestBuilder with an included T factory based - * on the provided T instance. The existing factory will not be included in - * the newly created tester instance. The created factory returns a new T - * instance by copy-constructing the provided const T& t. - * - * Preconditions for tester.WithInitialValue(const T& t): - * - * - The const T& t object must be copy-constructible where T is the type - * being tested. For non-copy-constructible objects, use the method - * tester.WithFactory(...). - */ - template <typename T> - ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...> - WithInitialValue(const T& t) const { - return WithFactory(DefaultFactory<T>(t)); - } - - /* - * Returns a new ExceptionSafetyTestBuilder with the provided T factory - * included. The existing factory will not be included in the newly-created - * tester instance. This method is intended for use with types lacking a copy - * constructor. Types that can be copy-constructed should instead use the - * method tester.WithInitialValue(...). - */ - template <typename NewFactory> - ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...> - WithFactory(const NewFactory& new_factory) const { - return {new_factory, operation_, contracts_}; - } - - /* - * Returns a new ExceptionSafetyTestBuilder with the provided testable - * operation included. The existing operation will not be included in the - * newly created tester. - */ - template <typename NewOperation> - ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...> - WithOperation(const NewOperation& new_operation) const { - return {factory_, new_operation, contracts_}; - } - - /* - * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts... - * combined with the Contracts... that were already included in the instance - * on which the method was called. Contracts... cannot be removed or replaced - * once added to an ExceptionSafetyTestBuilder instance. A fresh object must - * be created in order to get an empty Contracts... list. - * - * In addition to passing in custom contract assertion callbacks, this method - * accepts `testing::strong_guarantee` as an argument which checks T instances - * post-throw against freshly created T instances via operator== to verify - * that any state changes made during the execution of the operation were - * properly rolled back. - */ - template <typename... MoreContracts> - ExceptionSafetyTestBuilder<Factory, Operation, Contracts..., - absl::decay_t<MoreContracts>...> - WithContracts(const MoreContracts&... more_contracts) const { - return { - factory_, operation_, - std::tuple_cat(contracts_, std::tuple<absl::decay_t<MoreContracts>...>( - more_contracts...))}; - } - - /* - * Returns a testing::AssertionResult that is the reduced result of the - * exception safety algorithm. The algorithm short circuits and returns - * AssertionFailure after the first contract callback returns an - * AssertionFailure. Otherwise, if all contract callbacks return an - * AssertionSuccess, the reduced result is AssertionSuccess. - * - * The passed-in testable operation will not be saved in a new tester instance - * nor will it modify/replace the existing tester instance. This is useful - * when each operation being tested is unique and does not need to be reused. - * - * Preconditions for tester.Test(const NewOperation& new_operation): - * - * - May only be called after at least one contract assertion callback and a - * factory or initial value have been provided. - */ - template < - typename NewOperation, - typename = EnableIfTestable<sizeof...(Contracts), Factory, NewOperation>> - testing::AssertionResult Test(const NewOperation& new_operation) const { - return TestImpl(new_operation, absl::index_sequence_for<Contracts...>()); - } - - /* - * Returns a testing::AssertionResult that is the reduced result of the - * exception safety algorithm. The algorithm short circuits and returns - * AssertionFailure after the first contract callback returns an - * AssertionFailure. Otherwise, if all contract callbacks return an - * AssertionSuccess, the reduced result is AssertionSuccess. - * - * Preconditions for tester.Test(): - * - * - May only be called after at least one contract assertion callback, a - * factory or initial value and a testable operation have been provided. - */ - template < - typename LazyOperation = Operation, - typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>> - testing::AssertionResult Test() const { - return Test(operation_); - } - - private: - template <typename, typename, typename...> - friend class ExceptionSafetyTestBuilder; - - friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester(); - - ExceptionSafetyTestBuilder() {} - - ExceptionSafetyTestBuilder(const Factory& f, const Operation& o, - const std::tuple<Contracts...>& i) - : factory_(f), operation_(o), contracts_(i) {} - - template <typename SelectedOperation, size_t... Indices> - testing::AssertionResult TestImpl(SelectedOperation selected_operation, - absl::index_sequence<Indices...>) const { - return ExceptionSafetyTest<FactoryElementType<Factory>>( - factory_, selected_operation, std::get<Indices>(contracts_)...) - .Test(); - } - - Factory factory_; - Operation operation_; - std::tuple<Contracts...> contracts_; -}; - -} // namespace exceptions_internal - -} // namespace testing - -#endif // ABSL_HAVE_EXCEPTIONS - -#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/exception_testing.h b/third_party/abseil_cpp/absl/base/internal/exception_testing.h deleted file mode 100644 index 01b546557117..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exception_testing.h +++ /dev/null @@ -1,42 +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. - -// Testing utilities for ABSL types which throw exceptions. - -#ifndef ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_ -#define ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_ - -#include "gtest/gtest.h" -#include "absl/base/config.h" - -// ABSL_BASE_INTERNAL_EXPECT_FAIL tests either for a specified thrown exception -// if exceptions are enabled, or for death with a specified text in the error -// message -#ifdef ABSL_HAVE_EXCEPTIONS - -#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_THROW(expr, exception_t) - -#elif defined(__ANDROID__) -// Android asserts do not log anywhere that gtest can currently inspect. -// So we expect exit, but cannot match the message. -#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_DEATH(expr, ".*") -#else -#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_DEATH_IF_SUPPORTED(expr, text) - -#endif - -#endif // ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/exponential_biased.cc b/third_party/abseil_cpp/absl/base/internal/exponential_biased.cc deleted file mode 100644 index 1b30c061e3bd..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exponential_biased.cc +++ /dev/null @@ -1,93 +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/internal/exponential_biased.h" - -#include <stdint.h> - -#include <algorithm> -#include <atomic> -#include <cmath> -#include <limits> - -#include "absl/base/attributes.h" -#include "absl/base/optimization.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// The algorithm generates a random number between 0 and 1 and applies the -// inverse cumulative distribution function for an exponential. Specifically: -// Let m be the inverse of the sample period, then the probability -// distribution function is m*exp(-mx) so the CDF is -// p = 1 - exp(-mx), so -// q = 1 - p = exp(-mx) -// log_e(q) = -mx -// -log_e(q)/m = x -// log_2(q) * (-log_e(2) * 1/m) = x -// In the code, q is actually in the range 1 to 2**26, hence the -26 below -int64_t ExponentialBiased::GetSkipCount(int64_t mean) { - if (ABSL_PREDICT_FALSE(!initialized_)) { - Initialize(); - } - - uint64_t rng = NextRandom(rng_); - rng_ = rng; - - // Take the top 26 bits as the random number - // (This plus the 1<<58 sampling bound give a max possible step of - // 5194297183973780480 bytes.) - // The uint32_t cast is to prevent a (hard-to-reproduce) NAN - // under piii debug for some binaries. - double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0; - // Put the computed p-value through the CDF of a geometric. - double interval = bias_ + (std::log2(q) - 26) * (-std::log(2.0) * mean); - // Very large values of interval overflow int64_t. To avoid that, we will - // cheat and clamp any huge values to (int64_t max)/2. This is a potential - // source of bias, but the mean would need to be such a large value that it's - // not likely to come up. For example, with a mean of 1e18, the probability of - // hitting this condition is about 1/1000. For a mean of 1e17, standard - // calculators claim that this event won't happen. - if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) { - // Assume huge values are bias neutral, retain bias for next call. - return std::numeric_limits<int64_t>::max() / 2; - } - double value = std::round(interval); - bias_ = interval - value; - return value; -} - -int64_t ExponentialBiased::GetStride(int64_t mean) { - return GetSkipCount(mean - 1) + 1; -} - -void ExponentialBiased::Initialize() { - // We don't get well distributed numbers from `this` so we call NextRandom() a - // bunch to mush the bits around. We use a global_rand to handle the case - // where the same thread (by memory address) gets created and destroyed - // repeatedly. - ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0); - uint64_t r = reinterpret_cast<uint64_t>(this) + - global_rand.fetch_add(1, std::memory_order_relaxed); - for (int i = 0; i < 20; ++i) { - r = NextRandom(r); - } - rng_ = r; - initialized_ = true; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/exponential_biased.h b/third_party/abseil_cpp/absl/base/internal/exponential_biased.h deleted file mode 100644 index 94f79a3378db..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exponential_biased.h +++ /dev/null @@ -1,130 +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_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ -#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ - -#include <stdint.h> - -#include "absl/base/config.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// ExponentialBiased provides a small and fast random number generator for a -// rounded exponential distribution. This generator manages very little state, -// and imposes no synchronization overhead. This makes it useful in specialized -// scenarios requiring minimum overhead, such as stride based periodic sampling. -// -// ExponentialBiased provides two closely related functions, GetSkipCount() and -// GetStride(), both returning a rounded integer defining a number of events -// required before some event with a given mean probability occurs. -// -// The distribution is useful to generate a random wait time or some periodic -// event with a given mean probability. For example, if an action is supposed to -// happen on average once every 'N' events, then we can get a random 'stride' -// counting down how long before the event to happen. For example, if we'd want -// to sample one in every 1000 'Frobber' calls, our code could look like this: -// -// Frobber::Frobber() { -// stride_ = exponential_biased_.GetStride(1000); -// } -// -// void Frobber::Frob(int arg) { -// if (--stride == 0) { -// SampleFrob(arg); -// stride_ = exponential_biased_.GetStride(1000); -// } -// ... -// } -// -// The rounding of the return value creates a bias, especially for smaller means -// where the distribution of the fraction is not evenly distributed. We correct -// this bias by tracking the fraction we rounded up or down on each iteration, -// effectively tracking the distance between the cumulative value, and the -// rounded cumulative value. For example, given a mean of 2: -// -// raw = 1.63076, cumulative = 1.63076, rounded = 2, bias = -0.36923 -// raw = 0.14624, cumulative = 1.77701, rounded = 2, bias = 0.14624 -// raw = 4.93194, cumulative = 6.70895, rounded = 7, bias = -0.06805 -// raw = 0.24206, cumulative = 6.95101, rounded = 7, bias = 0.24206 -// etc... -// -// Adjusting with rounding bias is relatively trivial: -// -// double value = bias_ + exponential_distribution(mean)(); -// double rounded_value = std::round(value); -// bias_ = value - rounded_value; -// return rounded_value; -// -// This class is thread-compatible. -class ExponentialBiased { - public: - // The number of bits set by NextRandom. - static constexpr int kPrngNumBits = 48; - - // `GetSkipCount()` returns the number of events to skip before some chosen - // event happens. For example, randomly tossing a coin, we will on average - // throw heads once before we get tails. We can simulate random coin tosses - // using GetSkipCount() as: - // - // ExponentialBiased eb; - // for (...) { - // int number_of_heads_before_tail = eb.GetSkipCount(1); - // for (int flips = 0; flips < number_of_heads_before_tail; ++flips) { - // printf("head..."); - // } - // printf("tail\n"); - // } - // - int64_t GetSkipCount(int64_t mean); - - // GetStride() returns the number of events required for a specific event to - // happen. See the class comments for a usage example. `GetStride()` is - // equivalent to `GetSkipCount(mean - 1) + 1`. When to use `GetStride()` or - // `GetSkipCount()` depends mostly on what best fits the use case. - int64_t GetStride(int64_t mean); - - // Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1] - // - // This is public to enable testing. - static uint64_t NextRandom(uint64_t rnd); - - private: - void Initialize(); - - uint64_t rng_{0}; - double bias_{0}; - bool initialized_{false}; -}; - -// Returns the next prng value. -// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48 -// This is the lrand64 generator. -inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) { - const uint64_t prng_mult = uint64_t{0x5DEECE66D}; - const uint64_t prng_add = 0xB; - const uint64_t prng_mod_power = 48; - const uint64_t prng_mod_mask = - ~((~static_cast<uint64_t>(0)) << prng_mod_power); - return (prng_mult * rnd + prng_add) & prng_mod_mask; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/exponential_biased_test.cc b/third_party/abseil_cpp/absl/base/internal/exponential_biased_test.cc deleted file mode 100644 index 075583ca6fd4..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/exponential_biased_test.cc +++ /dev/null @@ -1,199 +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/internal/exponential_biased.h" - -#include <stddef.h> - -#include <cmath> -#include <cstdint> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" - -using ::testing::Ge; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -MATCHER_P2(IsBetween, a, b, - absl::StrCat(std::string(negation ? "isn't" : "is"), " between ", a, - " and ", b)) { - return a <= arg && arg <= b; -} - -// Tests of the quality of the random numbers generated -// This uses the Anderson Darling test for uniformity. -// See "Evaluating the Anderson-Darling Distribution" by Marsaglia -// for details. - -// Short cut version of ADinf(z), z>0 (from Marsaglia) -// This returns the p-value for Anderson Darling statistic in -// the limit as n-> infinity. For finite n, apply the error fix below. -double AndersonDarlingInf(double z) { - if (z < 2) { - return exp(-1.2337141 / z) / sqrt(z) * - (2.00012 + - (0.247105 - - (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 * z) * z) * z) * - z) * - z); - } - return exp( - -exp(1.0776 - - (2.30695 - - (0.43424 - (0.082433 - (0.008056 - 0.0003146 * z) * z) * z) * z) * - z)); -} - -// Corrects the approximation error in AndersonDarlingInf for small values of n -// Add this to AndersonDarlingInf to get a better approximation -// (from Marsaglia) -double AndersonDarlingErrFix(int n, double x) { - if (x > 0.8) { - return (-130.2137 + - (745.2337 - - (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) * - x) / - n; - } - double cutoff = 0.01265 + 0.1757 / n; - if (x < cutoff) { - double t = x / cutoff; - t = sqrt(t) * (1 - t) * (49 * t - 102); - return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n; - } else { - double t = (x - cutoff) / (0.8 - cutoff); - t = -0.00022633 + - (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * t) * t) * t) * t) * - t; - return t * (0.04213 + 0.01365 / n) / n; - } -} - -// Returns the AndersonDarling p-value given n and the value of the statistic -double AndersonDarlingPValue(int n, double z) { - double ad = AndersonDarlingInf(z); - double errfix = AndersonDarlingErrFix(n, ad); - return ad + errfix; -} - -double AndersonDarlingStatistic(const std::vector<double>& random_sample) { - int n = random_sample.size(); - double ad_sum = 0; - for (int i = 0; i < n; i++) { - ad_sum += (2 * i + 1) * - std::log(random_sample[i] * (1 - random_sample[n - 1 - i])); - } - double ad_statistic = -n - 1 / static_cast<double>(n) * ad_sum; - return ad_statistic; -} - -// Tests if the array of doubles is uniformly distributed. -// Returns the p-value of the Anderson Darling Statistic -// for the given set of sorted random doubles -// See "Evaluating the Anderson-Darling Distribution" by -// Marsaglia and Marsaglia for details. -double AndersonDarlingTest(const std::vector<double>& random_sample) { - double ad_statistic = AndersonDarlingStatistic(random_sample); - double p = AndersonDarlingPValue(random_sample.size(), ad_statistic); - return p; -} - -TEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount) { - ExponentialBiased eb; - for (int runs = 0; runs < 10; ++runs) { - for (int flips = eb.GetSkipCount(1); flips > 0; --flips) { - printf("head..."); - } - printf("tail\n"); - } - int heads = 0; - for (int i = 0; i < 10000000; i += 1 + eb.GetSkipCount(1)) { - ++heads; - } - printf("Heads = %d (%f%%)\n", heads, 100.0 * heads / 10000000); -} - -TEST(ExponentialBiasedTest, SampleDemoWithStride) { - ExponentialBiased eb; - int stride = eb.GetStride(10); - int samples = 0; - for (int i = 0; i < 10000000; ++i) { - if (--stride == 0) { - ++samples; - stride = eb.GetStride(10); - } - } - printf("Samples = %d (%f%%)\n", samples, 100.0 * samples / 10000000); -} - - -// Testing that NextRandom generates uniform random numbers. Applies the -// Anderson-Darling test for uniformity -TEST(ExponentialBiasedTest, TestNextRandom) { - for (auto n : std::vector<int>({ - 10, // Check short-range correlation - 100, 1000, - 10000 // Make sure there's no systemic error - })) { - uint64_t x = 1; - // This assumes that the prng returns 48 bit numbers - uint64_t max_prng_value = static_cast<uint64_t>(1) << 48; - // Initialize. - for (int i = 1; i <= 20; i++) { - x = ExponentialBiased::NextRandom(x); - } - std::vector<uint64_t> int_random_sample(n); - // Collect samples - for (int i = 0; i < n; i++) { - int_random_sample[i] = x; - x = ExponentialBiased::NextRandom(x); - } - // First sort them... - std::sort(int_random_sample.begin(), int_random_sample.end()); - std::vector<double> random_sample(n); - // Convert them to uniform randoms (in the range [0,1]) - for (int i = 0; i < n; i++) { - random_sample[i] = - static_cast<double>(int_random_sample[i]) / max_prng_value; - } - // Now compute the Anderson-Darling statistic - double ad_pvalue = AndersonDarlingTest(random_sample); - EXPECT_GT(std::min(ad_pvalue, 1 - ad_pvalue), 0.0001) - << "prng is not uniform: n = " << n << " p = " << ad_pvalue; - } -} - -// The generator needs to be available as a thread_local and as a static -// variable. -TEST(ExponentialBiasedTest, InitializationModes) { - ABSL_CONST_INIT static ExponentialBiased eb_static; - EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0)); - -#ifdef ABSL_HAVE_THREAD_LOCAL - thread_local ExponentialBiased eb_thread; - EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0)); -#endif - - ExponentialBiased eb_stack; - EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0)); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/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 3db59e83745b..000000000000 --- 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 16f3c1458bdf..000000000000 --- 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/hide_ptr.h b/third_party/abseil_cpp/absl/base/internal/hide_ptr.h deleted file mode 100644 index 1dba80909a9b..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/hide_ptr.h +++ /dev/null @@ -1,51 +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. - -#ifndef ABSL_BASE_INTERNAL_HIDE_PTR_H_ -#define ABSL_BASE_INTERNAL_HIDE_PTR_H_ - -#include <cstdint> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Arbitrary value with high bits set. Xor'ing with it is unlikely -// to map one valid pointer to another valid pointer. -constexpr uintptr_t HideMask() { - return (uintptr_t{0xF03A5F7BU} << (sizeof(uintptr_t) - 4) * 8) | 0xF03A5F7BU; -} - -// Hide a pointer from the leak checker. For internal use only. -// Differs from absl::IgnoreLeak(ptr) in that absl::IgnoreLeak(ptr) causes ptr -// and all objects reachable from ptr to be ignored by the leak checker. -template <class T> -inline uintptr_t HidePtr(T* ptr) { - return reinterpret_cast<uintptr_t>(ptr) ^ HideMask(); -} - -// Return a pointer that has been hidden from the leak checker. -// For internal use only. -template <class T> -inline T* UnhidePtr(uintptr_t hidden) { - return reinterpret_cast<T*>(hidden ^ HideMask()); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_HIDE_PTR_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/identity.h b/third_party/abseil_cpp/absl/base/internal/identity.h deleted file mode 100644 index a3154ed7bc59..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/identity.h +++ /dev/null @@ -1,37 +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. -// - -#ifndef ABSL_BASE_INTERNAL_IDENTITY_H_ -#define ABSL_BASE_INTERNAL_IDENTITY_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace internal { - -template <typename T> -struct identity { - typedef T type; -}; - -template <typename T> -using identity_t = typename identity<T>::type; - -} // namespace internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_IDENTITY_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/inline_variable.h b/third_party/abseil_cpp/absl/base/internal/inline_variable.h deleted file mode 100644 index 130d8c2476dd..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/inline_variable.h +++ /dev/null @@ -1,107 +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. - -#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ -#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ - -#include <type_traits> - -#include "absl/base/internal/identity.h" - -// File: -// This file define a macro that allows the creation of or emulation of C++17 -// inline variables based on whether or not the feature is supported. - -//////////////////////////////////////////////////////////////////////////////// -// Macro: ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) -// -// Description: -// Expands to the equivalent of an inline constexpr instance of the specified -// `type` and `name`, initialized to the value `init`. If the compiler being -// used is detected as supporting actual inline variables as a language -// feature, then the macro expands to an actual inline variable definition. -// -// Requires: -// `type` is a type that is usable in an extern variable declaration. -// -// Requires: `name` is a valid identifier -// -// Requires: -// `init` is an expression that can be used in the following definition: -// constexpr type name = init; -// -// Usage: -// -// // Equivalent to: `inline constexpr size_t variant_npos = -1;` -// ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); -// -// Differences in implementation: -// For a direct, language-level inline variable, decltype(name) will be the -// type that was specified along with const qualification, whereas for -// emulated inline variables, decltype(name) may be different (in practice -// it will likely be a reference type). -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cpp_inline_variables - -// Clang's -Wmissing-variable-declarations option erroneously warned that -// inline constexpr objects need to be pre-declared. This has now been fixed, -// but we will need to support this workaround for people building with older -// versions of clang. -// -// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862 -// -// Note: -// identity_t is used here so that the const and name are in the -// appropriate place for pointer types, reference types, function pointer -// types, etc.. -#if defined(__clang__) -#define ABSL_INTERNAL_EXTERN_DECL(type, name) \ - extern const ::absl::internal::identity_t<type> name; -#else // Otherwise, just define the macro to do nothing. -#define ABSL_INTERNAL_EXTERN_DECL(type, name) -#endif // defined(__clang__) - -// See above comment at top of file for details. -#define ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \ - ABSL_INTERNAL_EXTERN_DECL(type, name) \ - inline constexpr ::absl::internal::identity_t<type> name = init - -#else - -// See above comment at top of file for details. -// -// Note: -// identity_t is used here so that the const and name are in the -// appropriate place for pointer types, reference types, function pointer -// types, etc.. -#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \ - template <class /*AbslInternalDummy*/ = void> \ - struct AbslInternalInlineVariableHolder##name { \ - static constexpr ::absl::internal::identity_t<var_type> kInstance = init; \ - }; \ - \ - template <class AbslInternalDummy> \ - constexpr ::absl::internal::identity_t<var_type> \ - AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \ - \ - static constexpr const ::absl::internal::identity_t<var_type>& \ - name = /* NOLINT */ \ - AbslInternalInlineVariableHolder##name<>::kInstance; \ - static_assert(sizeof(void (*)(decltype(name))) != 0, \ - "Silence unused variable warnings.") - -#endif // __cpp_inline_variables - -#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/inline_variable_testing.h b/third_party/abseil_cpp/absl/base/internal/inline_variable_testing.h deleted file mode 100644 index 3856b9f80f20..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/inline_variable_testing.h +++ /dev/null @@ -1,46 +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. - -#ifndef ABSL_BASE_INLINE_VARIABLE_TESTING_H_ -#define ABSL_BASE_INLINE_VARIABLE_TESTING_H_ - -#include "absl/base/internal/inline_variable.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace inline_variable_testing_internal { - -struct Foo { - int value = 5; -}; - -ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, inline_variable_foo, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, other_inline_variable_foo, {}); - -ABSL_INTERNAL_INLINE_CONSTEXPR(int, inline_variable_int, 5); -ABSL_INTERNAL_INLINE_CONSTEXPR(int, other_inline_variable_int, 5); - -ABSL_INTERNAL_INLINE_CONSTEXPR(void(*)(), inline_variable_fun_ptr, nullptr); - -const Foo& get_foo_a(); -const Foo& get_foo_b(); - -const int& get_int_a(); -const int& get_int_b(); - -} // namespace inline_variable_testing_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/invoke.h b/third_party/abseil_cpp/absl/base/internal/invoke.h deleted file mode 100644 index 5c71f328234f..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/invoke.h +++ /dev/null @@ -1,187 +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. -// -// absl::base_internal::invoke(f, args...) is an implementation of -// INVOKE(f, args...) from section [func.require] of the C++ standard. -// -// [func.require] -// Define INVOKE (f, t1, t2, ..., tN) as follows: -// 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T -// and t1 is an object of type T or a reference to an object of type T or a -// reference to an object of a type derived from T; -// 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a -// class T and t1 is not one of the types described in the previous item; -// 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is -// an object of type T or a reference to an object of type T or a reference -// to an object of a type derived from T; -// 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 -// 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() -// isn't an error. - -#ifndef ABSL_BASE_INTERNAL_INVOKE_H_ -#define ABSL_BASE_INTERNAL_INVOKE_H_ - -#include <algorithm> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" - -// The following code is internal implementation detail. See the comment at the -// top of this file for the API documentation. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// The five classes below each implement one of the clauses from the definition -// of INVOKE. The inner class template Accept<F, Args...> checks whether the -// clause is applicable; static function template Invoke(f, args...) does the -// invocation. -// -// By separating the clause selection logic from invocation we make sure that -// Invoke() does exactly what the standard says. - -template <typename Derived> -struct StrippedAccept { - template <typename... Args> - struct Accept : Derived::template AcceptImpl<typename std::remove_cv< - typename std::remove_reference<Args>::type>::type...> {}; -}; - -// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T -// and t1 is an object of type T or a reference to an object of type T or a -// reference to an object of a type derived from T. -struct MemFunAndRef : StrippedAccept<MemFunAndRef> { - template <typename... Args> - struct AcceptImpl : std::false_type {}; - - template <typename MemFunType, typename C, typename Obj, typename... Args> - struct AcceptImpl<MemFunType C::*, Obj, Args...> - : std::integral_constant<bool, std::is_base_of<C, Obj>::value && - absl::is_function<MemFunType>::value> { - }; - - template <typename MemFun, typename Obj, typename... Args> - static decltype((std::declval<Obj>().* - std::declval<MemFun>())(std::declval<Args>()...)) - Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) { - return (std::forward<Obj>(obj).* - std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); - } -}; - -// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a -// class T and t1 is not one of the types described in the previous item. -struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> { - template <typename... Args> - struct AcceptImpl : std::false_type {}; - - template <typename MemFunType, typename C, typename Ptr, typename... Args> - struct AcceptImpl<MemFunType C::*, Ptr, Args...> - : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && - absl::is_function<MemFunType>::value> { - }; - - template <typename MemFun, typename Ptr, typename... Args> - static decltype(((*std::declval<Ptr>()).* - std::declval<MemFun>())(std::declval<Args>()...)) - Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) { - return ((*std::forward<Ptr>(ptr)).* - std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); - } -}; - -// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is -// an object of type T or a reference to an object of type T or a reference -// to an object of a type derived from T. -struct DataMemAndRef : StrippedAccept<DataMemAndRef> { - template <typename... Args> - struct AcceptImpl : std::false_type {}; - - template <typename R, typename C, typename Obj> - struct AcceptImpl<R C::*, Obj> - : std::integral_constant<bool, std::is_base_of<C, Obj>::value && - !absl::is_function<R>::value> {}; - - template <typename DataMem, typename Ref> - static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke( - DataMem&& data_mem, Ref&& ref) { - return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem); - } -}; - -// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 -// is not one of the types described in the previous item. -struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> { - template <typename... Args> - struct AcceptImpl : std::false_type {}; - - template <typename R, typename C, typename Ptr> - struct AcceptImpl<R C::*, Ptr> - : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && - !absl::is_function<R>::value> {}; - - template <typename DataMem, typename Ptr> - static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke( - DataMem&& data_mem, Ptr&& ptr) { - return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem); - } -}; - -// f(t1, t2, ..., tN) in all other cases. -struct Callable { - // Callable doesn't have Accept because it's the last clause that gets picked - // when none of the previous clauses are applicable. - template <typename F, typename... Args> - static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke( - F&& f, Args&&... args) { - return std::forward<F>(f)(std::forward<Args>(args)...); - } -}; - -// Resolves to the first matching clause. -template <typename... Args> -struct Invoker { - typedef typename std::conditional< - MemFunAndRef::Accept<Args...>::value, MemFunAndRef, - typename std::conditional< - MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr, - typename std::conditional< - DataMemAndRef::Accept<Args...>::value, DataMemAndRef, - typename std::conditional<DataMemAndPtr::Accept<Args...>::value, - DataMemAndPtr, Callable>::type>::type>:: - type>::type type; -}; - -// The result type of Invoke<F, Args...>. -template <typename F, typename... Args> -using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke( - std::declval<F>(), std::declval<Args>()...)); - -// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section -// [func.require] of the C++ standard. -template <typename F, typename... Args> -invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) { - return Invoker<F, Args...>::type::Invoke(std::forward<F>(f), - std::forward<Args>(args)...); -} -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_INVOKE_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/low_level_alloc.cc b/third_party/abseil_cpp/absl/base/internal/low_level_alloc.cc deleted file mode 100644 index 229ab9162d12..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/low_level_alloc.cc +++ /dev/null @@ -1,620 +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. - -// A low-level allocator that can be used by other low-level -// modules without introducing dependency cycles. -// This allocator is slow and wasteful of memory; -// it should not be used when performance is key. - -#include "absl/base/internal/low_level_alloc.h" - -#include <type_traits> - -#include "absl/base/call_once.h" -#include "absl/base/config.h" -#include "absl/base/internal/direct_mmap.h" -#include "absl/base/internal/scheduling_mode.h" -#include "absl/base/macros.h" -#include "absl/base/thread_annotations.h" - -// LowLevelAlloc requires that the platform support low-level -// allocation of virtual memory. Platforms lacking this cannot use -// LowLevelAlloc. -#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING - -#ifndef _WIN32 -#include <pthread.h> -#include <signal.h> -#include <sys/mman.h> -#include <unistd.h> -#else -#include <windows.h> -#endif - -#include <string.h> -#include <algorithm> -#include <atomic> -#include <cerrno> -#include <cstddef> -#include <new> // for placement-new - -#include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" - -// MAP_ANONYMOUS -#if defined(__APPLE__) -// For mmap, Linux defines both MAP_ANONYMOUS and MAP_ANON and says MAP_ANON is -// deprecated. In Darwin, MAP_ANON is all there is. -#if !defined MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif // !MAP_ANONYMOUS -#endif // __APPLE__ - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// A first-fit allocator with amortized logarithmic free() time. - -// --------------------------------------------------------------------------- -static const int kMaxLevel = 30; - -namespace { -// This struct describes one allocated block, or one free block. -struct AllocList { - struct Header { - // Size of entire region, including this field. Must be - // first. Valid in both allocated and unallocated blocks. - uintptr_t size; - - // kMagicAllocated or kMagicUnallocated xor this. - uintptr_t magic; - - // Pointer to parent arena. - LowLevelAlloc::Arena *arena; - - // Aligns regions to 0 mod 2*sizeof(void*). - void *dummy_for_alignment; - } header; - - // Next two fields: in unallocated blocks: freelist skiplist data - // in allocated blocks: overlaps with client data - - // Levels in skiplist used. - int levels; - - // Actually has levels elements. The AllocList node may not have room - // for all kMaxLevel entries. See max_fit in LLA_SkiplistLevels(). - AllocList *next[kMaxLevel]; -}; -} // namespace - -// --------------------------------------------------------------------------- -// A trivial skiplist implementation. This is used to keep the freelist -// in address order while taking only logarithmic time per insert and delete. - -// An integer approximation of log2(size/base) -// Requires size >= base. -static int IntLog2(size_t size, size_t base) { - int result = 0; - for (size_t i = size; i > base; i >>= 1) { // i == floor(size/2**result) - result++; - } - // floor(size / 2**result) <= base < floor(size / 2**(result-1)) - // => log2(size/(base+1)) <= result < 1+log2(size/base) - // => result ~= log2(size/base) - return result; -} - -// Return a random integer n: p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1. -static int Random(uint32_t *state) { - uint32_t r = *state; - int result = 1; - while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) { - result++; - } - *state = r; - return result; -} - -// Return a number of skiplist levels for a node of size bytes, where -// base is the minimum node size. Compute level=log2(size / base)+n -// where n is 1 if random is false and otherwise a random number generated with -// the standard distribution for a skiplist: See Random() above. -// Bigger nodes tend to have more skiplist levels due to the log2(size / base) -// term, so first-fit searches touch fewer nodes. "level" is clipped so -// level<kMaxLevel and next[level-1] will fit in the node. -// 0 < LLA_SkiplistLevels(x,y,false) <= LLA_SkiplistLevels(x,y,true) < kMaxLevel -static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) { - // max_fit is the maximum number of levels that will fit in a node for the - // given size. We can't return more than max_fit, no matter what the - // random number generator says. - size_t max_fit = (size - offsetof(AllocList, next)) / sizeof(AllocList *); - int level = IntLog2(size, base) + (random != nullptr ? Random(random) : 1); - if (static_cast<size_t>(level) > max_fit) level = static_cast<int>(max_fit); - if (level > kMaxLevel-1) level = kMaxLevel - 1; - ABSL_RAW_CHECK(level >= 1, "block not big enough for even one level"); - return level; -} - -// Return "atleast", the first element of AllocList *head s.t. *atleast >= *e. -// For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater -// points to the last element at level i in the AllocList less than *e, or is -// head if no such element exists. -static AllocList *LLA_SkiplistSearch(AllocList *head, - AllocList *e, AllocList **prev) { - AllocList *p = head; - for (int level = head->levels - 1; level >= 0; level--) { - for (AllocList *n; (n = p->next[level]) != nullptr && n < e; p = n) { - } - prev[level] = p; - } - return (head->levels == 0) ? nullptr : prev[0]->next[0]; -} - -// Insert element *e into AllocList *head. Set prev[] as LLA_SkiplistSearch. -// Requires that e->levels be previously set by the caller (using -// LLA_SkiplistLevels()) -static void LLA_SkiplistInsert(AllocList *head, AllocList *e, - AllocList **prev) { - LLA_SkiplistSearch(head, e, prev); - for (; head->levels < e->levels; head->levels++) { // extend prev pointers - prev[head->levels] = head; // to all *e's levels - } - for (int i = 0; i != e->levels; i++) { // add element to list - e->next[i] = prev[i]->next[i]; - prev[i]->next[i] = e; - } -} - -// Remove element *e from AllocList *head. Set prev[] as LLA_SkiplistSearch(). -// Requires that e->levels be previous set by the caller (using -// LLA_SkiplistLevels()) -static void LLA_SkiplistDelete(AllocList *head, AllocList *e, - AllocList **prev) { - AllocList *found = LLA_SkiplistSearch(head, e, prev); - ABSL_RAW_CHECK(e == found, "element not in freelist"); - for (int i = 0; i != e->levels && prev[i]->next[i] == e; i++) { - prev[i]->next[i] = e->next[i]; - } - while (head->levels > 0 && head->next[head->levels - 1] == nullptr) { - head->levels--; // reduce head->levels if level unused - } -} - -// --------------------------------------------------------------------------- -// Arena implementation - -// Metadata for an LowLevelAlloc arena instance. -struct LowLevelAlloc::Arena { - // Constructs an arena with the given LowLevelAlloc flags. - explicit Arena(uint32_t flags_value); - - base_internal::SpinLock mu; - // Head of free list, sorted by address - AllocList freelist ABSL_GUARDED_BY(mu); - // Count of allocated blocks - int32_t allocation_count ABSL_GUARDED_BY(mu); - // flags passed to NewArena - const uint32_t flags; - // Result of sysconf(_SC_PAGESIZE) - const size_t pagesize; - // Lowest power of two >= max(16, sizeof(AllocList)) - const size_t round_up; - // Smallest allocation block size - const size_t min_size; - // PRNG state - uint32_t random ABSL_GUARDED_BY(mu); -}; - -namespace { -// Static storage space for the lazily-constructed, default global arena -// instances. We require this space because the whole point of LowLevelAlloc -// is to avoid relying on malloc/new. -alignas(LowLevelAlloc::Arena) unsigned char default_arena_storage[sizeof( - LowLevelAlloc::Arena)]; -alignas(LowLevelAlloc::Arena) unsigned char unhooked_arena_storage[sizeof( - LowLevelAlloc::Arena)]; -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING -alignas( - LowLevelAlloc::Arena) unsigned char unhooked_async_sig_safe_arena_storage - [sizeof(LowLevelAlloc::Arena)]; -#endif - -// We must use LowLevelCallOnce here to construct the global arenas, rather than -// using function-level statics, to avoid recursively invoking the scheduler. -absl::once_flag create_globals_once; - -void CreateGlobalArenas() { - new (&default_arena_storage) - LowLevelAlloc::Arena(LowLevelAlloc::kCallMallocHook); - new (&unhooked_arena_storage) LowLevelAlloc::Arena(0); -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - new (&unhooked_async_sig_safe_arena_storage) - LowLevelAlloc::Arena(LowLevelAlloc::kAsyncSignalSafe); -#endif -} - -// Returns a global arena that does not call into hooks. Used by NewArena() -// when kCallMallocHook is not set. -LowLevelAlloc::Arena* UnhookedArena() { - base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas); - return reinterpret_cast<LowLevelAlloc::Arena*>(&unhooked_arena_storage); -} - -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING -// Returns a global arena that is async-signal safe. Used by NewArena() when -// kAsyncSignalSafe is set. -LowLevelAlloc::Arena *UnhookedAsyncSigSafeArena() { - base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas); - return reinterpret_cast<LowLevelAlloc::Arena *>( - &unhooked_async_sig_safe_arena_storage); -} -#endif - -} // namespace - -// Returns the default arena, as used by LowLevelAlloc::Alloc() and friends. -LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() { - base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas); - return reinterpret_cast<LowLevelAlloc::Arena*>(&default_arena_storage); -} - -// magic numbers to identify allocated and unallocated blocks -static const uintptr_t kMagicAllocated = 0x4c833e95U; -static const uintptr_t kMagicUnallocated = ~kMagicAllocated; - -namespace { -class ABSL_SCOPED_LOCKABLE ArenaLock { - public: - explicit ArenaLock(LowLevelAlloc::Arena *arena) - ABSL_EXCLUSIVE_LOCK_FUNCTION(arena->mu) - : arena_(arena) { -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { - sigset_t all; - sigfillset(&all); - mask_valid_ = pthread_sigmask(SIG_BLOCK, &all, &mask_) == 0; - } -#endif - arena_->mu.Lock(); - } - ~ArenaLock() { ABSL_RAW_CHECK(left_, "haven't left Arena region"); } - void Leave() ABSL_UNLOCK_FUNCTION() { - arena_->mu.Unlock(); -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if (mask_valid_) { - const int err = pthread_sigmask(SIG_SETMASK, &mask_, nullptr); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_sigmask failed: %d", err); - } - } -#endif - left_ = true; - } - - private: - bool left_ = false; // whether left region -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - bool mask_valid_ = false; - sigset_t mask_; // old mask of blocked signals -#endif - LowLevelAlloc::Arena *arena_; - ArenaLock(const ArenaLock &) = delete; - ArenaLock &operator=(const ArenaLock &) = delete; -}; -} // namespace - -// create an appropriate magic number for an object at "ptr" -// "magic" should be kMagicAllocated or kMagicUnallocated -inline static uintptr_t Magic(uintptr_t magic, AllocList::Header *ptr) { - return magic ^ reinterpret_cast<uintptr_t>(ptr); -} - -namespace { -size_t GetPageSize() { -#ifdef _WIN32 - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity); -#elif defined(__wasm__) || defined(__asmjs__) - return getpagesize(); -#else - return sysconf(_SC_PAGESIZE); -#endif -} - -size_t RoundedUpBlockSize() { - // Round up block sizes to a power of two close to the header size. - size_t round_up = 16; - while (round_up < sizeof(AllocList::Header)) { - round_up += round_up; - } - return round_up; -} - -} // namespace - -LowLevelAlloc::Arena::Arena(uint32_t flags_value) - : mu(base_internal::SCHEDULE_KERNEL_ONLY), - allocation_count(0), - flags(flags_value), - pagesize(GetPageSize()), - round_up(RoundedUpBlockSize()), - min_size(2 * round_up), - random(0) { - freelist.header.size = 0; - freelist.header.magic = - Magic(kMagicUnallocated, &freelist.header); - freelist.header.arena = this; - freelist.levels = 0; - memset(freelist.next, 0, sizeof(freelist.next)); -} - -// L < meta_data_arena->mu -LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32_t flags) { - Arena *meta_data_arena = DefaultArena(); -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { - meta_data_arena = UnhookedAsyncSigSafeArena(); - } else // NOLINT(readability/braces) -#endif - if ((flags & LowLevelAlloc::kCallMallocHook) == 0) { - meta_data_arena = UnhookedArena(); - } - Arena *result = - new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(flags); - return result; -} - -// L < arena->mu, L < arena->arena->mu -bool LowLevelAlloc::DeleteArena(Arena *arena) { - ABSL_RAW_CHECK( - arena != nullptr && arena != DefaultArena() && arena != UnhookedArena(), - "may not delete default arena"); - ArenaLock section(arena); - if (arena->allocation_count != 0) { - section.Leave(); - return false; - } - while (arena->freelist.next[0] != nullptr) { - AllocList *region = arena->freelist.next[0]; - size_t size = region->header.size; - arena->freelist.next[0] = region->next[0]; - ABSL_RAW_CHECK( - region->header.magic == Magic(kMagicUnallocated, ®ion->header), - "bad magic number in DeleteArena()"); - ABSL_RAW_CHECK(region->header.arena == arena, - "bad arena pointer in DeleteArena()"); - ABSL_RAW_CHECK(size % arena->pagesize == 0, - "empty arena has non-page-aligned block size"); - ABSL_RAW_CHECK(reinterpret_cast<uintptr_t>(region) % arena->pagesize == 0, - "empty arena has non-page-aligned block"); - int munmap_result; -#ifdef _WIN32 - munmap_result = VirtualFree(region, 0, MEM_RELEASE); - ABSL_RAW_CHECK(munmap_result != 0, - "LowLevelAlloc::DeleteArena: VitualFree failed"); -#else -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) == 0) { - munmap_result = munmap(region, size); - } else { - munmap_result = base_internal::DirectMunmap(region, size); - } -#else - munmap_result = munmap(region, size); -#endif // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if (munmap_result != 0) { - ABSL_RAW_LOG(FATAL, "LowLevelAlloc::DeleteArena: munmap failed: %d", - errno); - } -#endif // _WIN32 - } - section.Leave(); - arena->~Arena(); - Free(arena); - return true; -} - -// --------------------------------------------------------------------------- - -// Addition, checking for overflow. The intent is to die if an external client -// manages to push through a request that would cause arithmetic to fail. -static inline uintptr_t CheckedAdd(uintptr_t a, uintptr_t b) { - uintptr_t sum = a + b; - ABSL_RAW_CHECK(sum >= a, "LowLevelAlloc arithmetic overflow"); - return sum; -} - -// Return value rounded up to next multiple of align. -// align must be a power of two. -static inline uintptr_t RoundUp(uintptr_t addr, uintptr_t align) { - return CheckedAdd(addr, align - 1) & ~(align - 1); -} - -// Equivalent to "return prev->next[i]" but with sanity checking -// that the freelist is in the correct order, that it -// consists of regions marked "unallocated", and that no two regions -// are adjacent in memory (they should have been coalesced). -// L >= arena->mu -static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) { - ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()"); - AllocList *next = prev->next[i]; - if (next != nullptr) { - ABSL_RAW_CHECK( - next->header.magic == Magic(kMagicUnallocated, &next->header), - "bad magic number in Next()"); - ABSL_RAW_CHECK(next->header.arena == arena, "bad arena pointer in Next()"); - if (prev != &arena->freelist) { - ABSL_RAW_CHECK(prev < next, "unordered freelist"); - ABSL_RAW_CHECK(reinterpret_cast<char *>(prev) + prev->header.size < - reinterpret_cast<char *>(next), - "malformed freelist"); - } - } - return next; -} - -// Coalesce list item "a" with its successor if they are adjacent. -static void Coalesce(AllocList *a) { - AllocList *n = a->next[0]; - if (n != nullptr && reinterpret_cast<char *>(a) + a->header.size == - reinterpret_cast<char *>(n)) { - LowLevelAlloc::Arena *arena = a->header.arena; - a->header.size += n->header.size; - n->header.magic = 0; - n->header.arena = nullptr; - AllocList *prev[kMaxLevel]; - LLA_SkiplistDelete(&arena->freelist, n, prev); - LLA_SkiplistDelete(&arena->freelist, a, prev); - a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size, - &arena->random); - LLA_SkiplistInsert(&arena->freelist, a, prev); - } -} - -// Adds block at location "v" to the free list -// L >= arena->mu -static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) { - AllocList *f = reinterpret_cast<AllocList *>( - reinterpret_cast<char *>(v) - sizeof (f->header)); - ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header), - "bad magic number in AddToFreelist()"); - ABSL_RAW_CHECK(f->header.arena == arena, - "bad arena pointer in AddToFreelist()"); - f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size, - &arena->random); - AllocList *prev[kMaxLevel]; - LLA_SkiplistInsert(&arena->freelist, f, prev); - f->header.magic = Magic(kMagicUnallocated, &f->header); - Coalesce(f); // maybe coalesce with successor - Coalesce(prev[0]); // maybe coalesce with predecessor -} - -// Frees storage allocated by LowLevelAlloc::Alloc(). -// L < arena->mu -void LowLevelAlloc::Free(void *v) { - if (v != nullptr) { - AllocList *f = reinterpret_cast<AllocList *>( - reinterpret_cast<char *>(v) - sizeof (f->header)); - LowLevelAlloc::Arena *arena = f->header.arena; - ArenaLock section(arena); - AddToFreelist(v, arena); - ABSL_RAW_CHECK(arena->allocation_count > 0, "nothing in arena to free"); - arena->allocation_count--; - section.Leave(); - } -} - -// allocates and returns a block of size bytes, to be freed with Free() -// L < arena->mu -static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { - void *result = nullptr; - if (request != 0) { - AllocList *s; // will point to region that satisfies request - ArenaLock section(arena); - // round up with header - size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)), - arena->round_up); - for (;;) { // loop until we find a suitable region - // find the minimum levels that a block of this size must have - int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1; - if (i < arena->freelist.levels) { // potential blocks exist - AllocList *before = &arena->freelist; // predecessor of s - while ((s = Next(i, before, arena)) != nullptr && - s->header.size < req_rnd) { - before = s; - } - if (s != nullptr) { // we found a region - break; - } - } - // we unlock before mmap() both because mmap() may call a callback hook, - // and because it may be slow. - arena->mu.Unlock(); - // mmap generous 64K chunks to decrease - // the chances/impact of fragmentation: - size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16); - void *new_pages; -#ifdef _WIN32 - new_pages = VirtualAlloc(0, new_pages_size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - ABSL_RAW_CHECK(new_pages != nullptr, "VirtualAlloc failed"); -#else -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { - new_pages = base_internal::DirectMmap(nullptr, new_pages_size, - PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - } else { - new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - } -#else - new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); -#endif // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - if (new_pages == MAP_FAILED) { - ABSL_RAW_LOG(FATAL, "mmap error: %d", errno); - } - -#endif // _WIN32 - arena->mu.Lock(); - s = reinterpret_cast<AllocList *>(new_pages); - s->header.size = new_pages_size; - // Pretend the block is allocated; call AddToFreelist() to free it. - s->header.magic = Magic(kMagicAllocated, &s->header); - s->header.arena = arena; - AddToFreelist(&s->levels, arena); // insert new region into free list - } - AllocList *prev[kMaxLevel]; - LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list - // s points to the first free region that's big enough - if (CheckedAdd(req_rnd, arena->min_size) <= s->header.size) { - // big enough to split - AllocList *n = reinterpret_cast<AllocList *> - (req_rnd + reinterpret_cast<char *>(s)); - n->header.size = s->header.size - req_rnd; - n->header.magic = Magic(kMagicAllocated, &n->header); - n->header.arena = arena; - s->header.size = req_rnd; - AddToFreelist(&n->levels, arena); - } - s->header.magic = Magic(kMagicAllocated, &s->header); - ABSL_RAW_CHECK(s->header.arena == arena, ""); - arena->allocation_count++; - section.Leave(); - result = &s->levels; - } - ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request); - return result; -} - -void *LowLevelAlloc::Alloc(size_t request) { - void *result = DoAllocWithArena(request, DefaultArena()); - return result; -} - -void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) { - ABSL_RAW_CHECK(arena != nullptr, "must pass a valid arena"); - void *result = DoAllocWithArena(request, arena); - return result; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/third_party/abseil_cpp/absl/base/internal/low_level_alloc.h b/third_party/abseil_cpp/absl/base/internal/low_level_alloc.h deleted file mode 100644 index db91951c825f..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/low_level_alloc.h +++ /dev/null @@ -1,126 +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. -// - -#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ -#define ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ - -// A simple thread-safe memory allocator that does not depend on -// mutexes or thread-specific data. It is intended to be used -// sparingly, and only when malloc() would introduce an unwanted -// dependency, such as inside the heap-checker, or the Mutex -// implementation. - -// IWYU pragma: private, include "base/low_level_alloc.h" - -#include <sys/types.h> - -#include <cstdint> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" - -// LowLevelAlloc requires that the platform support low-level -// allocation of virtual memory. Platforms lacking this cannot use -// LowLevelAlloc. -#ifdef ABSL_LOW_LEVEL_ALLOC_MISSING -#error ABSL_LOW_LEVEL_ALLOC_MISSING cannot be directly set -#elif !defined(ABSL_HAVE_MMAP) && !defined(_WIN32) -#define ABSL_LOW_LEVEL_ALLOC_MISSING 1 -#endif - -// Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows or -// asm.js / WebAssembly. -// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html -// for more information. -#ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING -#error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set -#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) -#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1 -#endif - -#include <cstddef> - -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -class LowLevelAlloc { - public: - struct Arena; // an arena from which memory may be allocated - - // Returns a pointer to a block of at least "request" bytes - // that have been newly allocated from the specific arena. - // for Alloc() call the DefaultArena() is used. - // Returns 0 if passed request==0. - // Does not return 0 under other circumstances; it crashes if memory - // is not available. - static void *Alloc(size_t request) ABSL_ATTRIBUTE_SECTION(malloc_hook); - static void *AllocWithArena(size_t request, Arena *arena) - ABSL_ATTRIBUTE_SECTION(malloc_hook); - - // Deallocates a region of memory that was previously allocated with - // Alloc(). Does nothing if passed 0. "s" must be either 0, - // or must have been returned from a call to Alloc() and not yet passed to - // Free() since that call to Alloc(). The space is returned to the arena - // from which it was allocated. - static void Free(void *s) ABSL_ATTRIBUTE_SECTION(malloc_hook); - - // ABSL_ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free - // are to put all callers of MallocHook::Invoke* in this module - // into special section, - // so that MallocHook::GetCallerStackTrace can function accurately. - - // Create a new arena. - // The root metadata for the new arena is allocated in the - // meta_data_arena; the DefaultArena() can be passed for meta_data_arena. - // These values may be ored into flags: - enum { - // Report calls to Alloc() and Free() via the MallocHook interface. - // Set in the DefaultArena. - kCallMallocHook = 0x0001, - -#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING - // Make calls to Alloc(), Free() be async-signal-safe. Not set in - // DefaultArena(). Not supported on all platforms. - kAsyncSignalSafe = 0x0002, -#endif - }; - // Construct a new arena. The allocation of the underlying metadata honors - // the provided flags. For example, the call NewArena(kAsyncSignalSafe) - // is itself async-signal-safe, as well as generatating an arena that provides - // async-signal-safe Alloc/Free. - static Arena *NewArena(int32_t flags); - - // Destroys an arena allocated by NewArena and returns true, - // provided no allocated blocks remain in the arena. - // If allocated blocks remain in the arena, does nothing and - // returns false. - // It is illegal to attempt to destroy the DefaultArena(). - static bool DeleteArena(Arena *arena); - - // The default arena that always exists. - static Arena *DefaultArena(); - - private: - LowLevelAlloc(); // no instances -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ 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 deleted file mode 100644 index 2f2eaffa032e..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/low_level_alloc_test.cc +++ /dev/null @@ -1,162 +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/base/internal/low_level_alloc.h" - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <thread> // NOLINT(build/c++11) -#include <unordered_map> -#include <utility> - -#include "absl/container/node_hash_map.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -// This test doesn't use gtest since it needs to test that everything -// works before main(). -#define TEST_ASSERT(x) \ - if (!(x)) { \ - printf("TEST_ASSERT(%s) FAILED ON LINE %d\n", #x, __LINE__); \ - abort(); \ - } - -// a block of memory obtained from the allocator -struct BlockDesc { - char *ptr; // pointer to memory - int len; // number of bytes - int fill; // filled with data starting with this -}; - -// Check that the pattern placed in the block d -// by RandomizeBlockDesc is still there. -static void CheckBlockDesc(const BlockDesc &d) { - for (int i = 0; i != d.len; i++) { - TEST_ASSERT((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff)); - } -} - -// Fill the block "*d" with a pattern -// starting with a random byte. -static void RandomizeBlockDesc(BlockDesc *d) { - d->fill = rand() & 0xff; - for (int i = 0; i != d->len; i++) { - d->ptr[i] = (d->fill + i) & 0xff; - } -} - -// Use to indicate to the malloc hooks that -// this calls is from LowLevelAlloc. -static bool using_low_level_alloc = false; - -// n times, toss a coin, and based on the outcome -// either allocate a new block or deallocate an old block. -// New blocks are placed in a std::unordered_map with a random key -// and initialized with RandomizeBlockDesc(). -// If keys conflict, the older block is freed. -// Old blocks are always checked with CheckBlockDesc() -// before being freed. At the end of the run, -// all remaining allocated blocks are freed. -// If use_new_arena is true, use a fresh arena, and then delete it. -// If call_malloc_hook is true and user_arena is true, -// 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; - AllocMap allocated; - AllocMap::iterator it; - BlockDesc block_desc; - int rnd; - LowLevelAlloc::Arena *arena = 0; - if (use_new_arena) { - int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0; - arena = LowLevelAlloc::NewArena(flags); - } - for (int i = 0; i != n; i++) { - if (i != 0 && i % 10000 == 0) { - printf("."); - fflush(stdout); - } - - switch (rand() & 1) { // toss a coin - case 0: // coin came up heads: add a block - using_low_level_alloc = true; - block_desc.len = rand() & 0x3fff; - block_desc.ptr = - reinterpret_cast<char *>( - arena == 0 - ? LowLevelAlloc::Alloc(block_desc.len) - : LowLevelAlloc::AllocWithArena(block_desc.len, arena)); - using_low_level_alloc = false; - RandomizeBlockDesc(&block_desc); - rnd = rand(); - it = allocated.find(rnd); - if (it != allocated.end()) { - CheckBlockDesc(it->second); - using_low_level_alloc = true; - LowLevelAlloc::Free(it->second.ptr); - using_low_level_alloc = false; - it->second = block_desc; - } else { - allocated[rnd] = block_desc; - } - break; - case 1: // coin came up tails: remove a block - it = allocated.begin(); - if (it != allocated.end()) { - CheckBlockDesc(it->second); - using_low_level_alloc = true; - LowLevelAlloc::Free(it->second.ptr); - using_low_level_alloc = false; - allocated.erase(it); - } - break; - } - } - // remove all remaining blocks - while ((it = allocated.begin()) != allocated.end()) { - CheckBlockDesc(it->second); - using_low_level_alloc = true; - LowLevelAlloc::Free(it->second.ptr); - using_low_level_alloc = false; - allocated.erase(it); - } - if (use_new_arena) { - TEST_ASSERT(LowLevelAlloc::DeleteArena(arena)); - } -} - -// LowLevelAlloc is designed to be safe to call before main(). -static struct BeforeMain { - BeforeMain() { - Test(false, false, 50000); - Test(true, false, 50000); - Test(true, true, 50000); - } -} before_main; - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -int main(int argc, char *argv[]) { - // The actual test runs in the global constructor of `before_main`. - printf("PASS\n"); - 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 deleted file mode 100644 index 9baccc0659be..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/low_level_scheduling.h +++ /dev/null @@ -1,134 +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. -// -// Core interfaces and definitions used by by low-level interfaces such as -// SpinLock. - -#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" - -// The following two declarations exist so SchedulingGuard may friend them with -// the appropriate language linkage. These callbacks allow libc internals, such -// as function level statics, to schedule cooperatively when locking. -extern "C" bool __google_disable_rescheduling(void); -extern "C" void __google_enable_rescheduling(bool disable_result); - -namespace absl { -ABSL_NAMESPACE_BEGIN -class CondVar; -class Mutex; - -namespace synchronization_internal { -int MutexDelay(int32_t c, int mode); -} // namespace synchronization_internal - -namespace base_internal { - -class SchedulingHelper; // To allow use of SchedulingGuard. -class SpinLock; // To allow use of SchedulingGuard. - -// SchedulingGuard -// Provides guard semantics that may be used to disable cooperative rescheduling -// of the calling thread within specific program blocks. This is used to -// protect resources (e.g. low-level SpinLocks or Domain code) that cooperative -// scheduling depends on. -// -// Domain implementations capable of rescheduling in reaction to involuntary -// kernel thread actions (e.g blocking due to a pagefault or syscall) must -// guarantee that an annotated thread is not allowed to (cooperatively) -// reschedule until the annotated region is complete. -// -// It is an error to attempt to use a cooperatively scheduled resource (e.g. -// Mutex) within a rescheduling-disabled region. -// -// All methods are async-signal safe. -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 - // initiate scheduling operations (e.g. wake-ups), however, it may not itself - // reschedule. Nestable. The returned result is opaque, clients should not - // attempt to interpret it. - // REQUIRES: Result must be passed to a pairing EnableScheduling(). - static bool DisableRescheduling(); - - // Marks the end of a rescheduling disabled region, previously started by - // DisableRescheduling(). - // REQUIRES: Pairs with innermost call (and result) of DisableRescheduling(). - static void EnableRescheduling(bool disable_result); - - // A scoped helper for {Disable, Enable}Rescheduling(). - // REQUIRES: destructor must run in same thread as constructor. - struct ScopedDisable { - ScopedDisable() { disabled = SchedulingGuard::DisableRescheduling(); } - ~ScopedDisable() { SchedulingGuard::EnableRescheduling(disabled); } - - 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; - friend class SchedulingHelper; - friend class SpinLock; - friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode); -}; - -//------------------------------------------------------------------------------ -// End of public interfaces. -//------------------------------------------------------------------------------ - -inline bool SchedulingGuard::ReschedulingIsAllowed() { - return false; -} - -inline bool SchedulingGuard::DisableRescheduling() { - return false; -} - -inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { - return; -} - -inline SchedulingGuard::ScopedEnable::ScopedEnable() - : scheduling_disabled_depth_(0) {} -inline SchedulingGuard::ScopedEnable::~ScopedEnable() { - ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning"); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/per_thread_tls.h b/third_party/abseil_cpp/absl/base/internal/per_thread_tls.h deleted file mode 100644 index cf5e97a0470e..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/per_thread_tls.h +++ /dev/null @@ -1,52 +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. - -#ifndef ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_ -#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_ - -// This header defines two macros: -// -// If the platform supports thread-local storage: -// -// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a -// thread-local variable -// * ABSL_PER_THREAD_TLS is 1 -// -// Otherwise: -// -// * ABSL_PER_THREAD_TLS_KEYWORD is empty -// * ABSL_PER_THREAD_TLS is 0 -// -// Microsoft C supports thread-local storage. -// GCC supports it if the appropriate version of glibc is available, -// which the programmer can indicate by defining ABSL_HAVE_TLS - -#include "absl/base/port.h" // For ABSL_HAVE_TLS - -#if defined(ABSL_PER_THREAD_TLS) -#error ABSL_PER_THREAD_TLS cannot be directly set -#elif defined(ABSL_PER_THREAD_TLS_KEYWORD) -#error ABSL_PER_THREAD_TLS_KEYWORD cannot be directly set -#elif defined(ABSL_HAVE_TLS) -#define ABSL_PER_THREAD_TLS_KEYWORD __thread -#define ABSL_PER_THREAD_TLS 1 -#elif defined(_MSC_VER) -#define ABSL_PER_THREAD_TLS_KEYWORD __declspec(thread) -#define ABSL_PER_THREAD_TLS 1 -#else -#define ABSL_PER_THREAD_TLS_KEYWORD -#define ABSL_PER_THREAD_TLS 0 -#endif - -#endif // ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/periodic_sampler.cc b/third_party/abseil_cpp/absl/base/internal/periodic_sampler.cc deleted file mode 100644 index 520dabbaa006..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/periodic_sampler.cc +++ /dev/null @@ -1,53 +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/internal/periodic_sampler.h" - -#include <atomic> - -#include "absl/base/internal/exponential_biased.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept { - return rng_.GetStride(period); -} - -bool PeriodicSamplerBase::SubtleConfirmSample() noexcept { - int current_period = period(); - - // Deal with period case 0 (always off) and 1 (always on) - if (ABSL_PREDICT_FALSE(current_period < 2)) { - stride_ = 0; - return current_period == 1; - } - - // Check if this is the first call to Sample() - if (ABSL_PREDICT_FALSE(stride_ == 1)) { - stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period)); - if (static_cast<int64_t>(stride_) < -1) { - ++stride_; - return false; - } - } - - stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period)); - return true; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/periodic_sampler.h b/third_party/abseil_cpp/absl/base/internal/periodic_sampler.h deleted file mode 100644 index f8a86796b117..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/periodic_sampler.h +++ /dev/null @@ -1,211 +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_BASE_INTERNAL_PERIODIC_SAMPLER_H_ -#define ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_ - -#include <stdint.h> - -#include <atomic> - -#include "absl/base/internal/exponential_biased.h" -#include "absl/base/optimization.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// PeriodicSamplerBase provides the basic period sampler implementation. -// -// This is the base class for the templated PeriodicSampler class, which holds -// a global std::atomic value identified by a user defined tag, such that -// each specific PeriodSampler implementation holds its own global period. -// -// PeriodicSamplerBase is thread-compatible except where stated otherwise. -class PeriodicSamplerBase { - public: - // PeriodicSamplerBase is trivial / copyable / movable / destructible. - PeriodicSamplerBase() = default; - PeriodicSamplerBase(PeriodicSamplerBase&&) = default; - PeriodicSamplerBase(const PeriodicSamplerBase&) = default; - - // Returns true roughly once every `period` calls. This is established by a - // randomly picked `stride` that is counted down on each call to `Sample`. - // This stride is picked such that the probability of `Sample()` returning - // true is 1 in `period`. - inline bool Sample() noexcept; - - // The below methods are intended for optimized use cases where the - // size of the inlined fast path code is highly important. Applications - // should use the `Sample()` method unless they have proof that their - // specific use case requires the optimizations offered by these methods. - // - // An example of such a use case is SwissTable sampling. All sampling checks - // are in inlined SwissTable methods, and the number of call sites is huge. - // In this case, the inlined code size added to each translation unit calling - // SwissTable methods is non-trivial. - // - // The `SubtleMaybeSample()` function spuriously returns true even if the - // function should not be sampled, applications MUST match each call to - // 'SubtleMaybeSample()' returning true with a `SubtleConfirmSample()` call, - // and use the result of the latter as the sampling decision. - // In other words: the code should logically be equivalent to: - // - // if (SubtleMaybeSample() && SubtleConfirmSample()) { - // // Sample this call - // } - // - // In the 'inline-size' optimized case, the `SubtleConfirmSample()` call can - // be placed out of line, for example, the typical use case looks as follows: - // - // // --- frobber.h ----------- - // void FrobberSampled(); - // - // inline void FrobberImpl() { - // // ... - // } - // - // inline void Frobber() { - // if (ABSL_PREDICT_FALSE(sampler.SubtleMaybeSample())) { - // FrobberSampled(); - // } else { - // FrobberImpl(); - // } - // } - // - // // --- frobber.cc ----------- - // void FrobberSampled() { - // if (!sampler.SubtleConfirmSample())) { - // // Spurious false positive - // FrobberImpl(); - // return; - // } - // - // // Sampled execution - // // ... - // } - inline bool SubtleMaybeSample() noexcept; - bool SubtleConfirmSample() noexcept; - - protected: - // We explicitly don't use a virtual destructor as this class is never - // virtually destroyed, and it keeps the class trivial, which avoids TLS - // prologue and epilogue code for our TLS instances. - ~PeriodicSamplerBase() = default; - - // Returns the next stride for our sampler. - // This function is virtual for testing purposes only. - virtual int64_t GetExponentialBiased(int period) noexcept; - - private: - // Returns the current period of this sampler. Thread-safe. - virtual int period() const noexcept = 0; - - // Keep and decrement stride_ as an unsigned integer, but compare the value - // to zero casted as a signed int. clang and msvc do not create optimum code - // if we use signed for the combined decrement and sign comparison. - // - // Below 3 alternative options, all compiles generate the best code - // using the unsigned increment <---> signed int comparison option. - // - // Option 1: - // int64_t stride_; - // if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... } - // - // GCC x64 (OK) : https://gcc.godbolt.org/z/R5MzzA - // GCC ppc (OK) : https://gcc.godbolt.org/z/z7NZAt - // Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd - // ICC x64 (OK) : https://gcc.godbolt.org/z/rE6s8W - // MSVC x64 (OK) : https://gcc.godbolt.org/z/ARMXqS - // - // Option 2: - // int64_t stride_ = 0; - // if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... } - // - // GCC x64 (OK) : https://gcc.godbolt.org/z/jSQxYK - // GCC ppc (OK) : https://gcc.godbolt.org/z/VJdYaA - // Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX - // ICC x64 (OK) : https://gcc.godbolt.org/z/4snaFd - // MSVC x64 (BAD): https://gcc.godbolt.org/z/BgnEKE - // - // Option 3: - // uint64_t stride_; - // if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { ... } - // - // GCC x64 (OK) : https://gcc.godbolt.org/z/bFbfPy - // GCC ppc (OK) : https://gcc.godbolt.org/z/S9KkUE - // Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4 - // ICC x64 (OK) : https://gcc.godbolt.org/z/ptTNfD - // MSVC x64 (OK) : https://gcc.godbolt.org/z/76j4-5 - uint64_t stride_ = 0; - ExponentialBiased rng_; -}; - -inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept { - // See comments on `stride_` for the unsigned increment / signed compare. - if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { - return false; - } - return true; -} - -inline bool PeriodicSamplerBase::Sample() noexcept { - return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample() - : false; -} - -// PeriodicSampler is a concreted periodic sampler implementation. -// The user provided Tag identifies the implementation, and is required to -// isolate the global state of this instance from other instances. -// -// Typical use case: -// -// struct HashTablezTag {}; -// thread_local PeriodicSampler sampler; -// -// void HashTableSamplingLogic(...) { -// if (sampler.Sample()) { -// HashTableSlowSamplePath(...); -// } -// } -// -template <typename Tag, int default_period = 0> -class PeriodicSampler final : public PeriodicSamplerBase { - public: - ~PeriodicSampler() = default; - - int period() const noexcept final { - return period_.load(std::memory_order_relaxed); - } - - // Sets the global period for this sampler. Thread-safe. - // Setting a period of 0 disables the sampler, i.e., every call to Sample() - // will return false. Setting a period of 1 puts the sampler in 'always on' - // mode, i.e., every call to Sample() returns true. - static void SetGlobalPeriod(int period) { - period_.store(period, std::memory_order_relaxed); - } - - private: - static std::atomic<int> period_; -}; - -template <typename Tag, int default_period> -std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period); - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/periodic_sampler_benchmark.cc b/third_party/abseil_cpp/absl/base/internal/periodic_sampler_benchmark.cc deleted file mode 100644 index 5ad469ce79c2..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/periodic_sampler_benchmark.cc +++ /dev/null @@ -1,79 +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 "benchmark/benchmark.h" -#include "absl/base/internal/periodic_sampler.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -template <typename Sampler> -void BM_Sample(Sampler* sampler, benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(sampler); - benchmark::DoNotOptimize(sampler->Sample()); - } -} - -template <typename Sampler> -void BM_SampleMinunumInlined(Sampler* sampler, benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(sampler); - if (ABSL_PREDICT_FALSE(sampler->SubtleMaybeSample())) { - benchmark::DoNotOptimize(sampler->SubtleConfirmSample()); - } - } -} - -void BM_PeriodicSampler_TinySample(benchmark::State& state) { - struct Tag {}; - PeriodicSampler<Tag, 10> sampler; - BM_Sample(&sampler, state); -} -BENCHMARK(BM_PeriodicSampler_TinySample); - -void BM_PeriodicSampler_ShortSample(benchmark::State& state) { - struct Tag {}; - PeriodicSampler<Tag, 1024> sampler; - BM_Sample(&sampler, state); -} -BENCHMARK(BM_PeriodicSampler_ShortSample); - -void BM_PeriodicSampler_LongSample(benchmark::State& state) { - struct Tag {}; - PeriodicSampler<Tag, 1024 * 1024> sampler; - BM_Sample(&sampler, state); -} -BENCHMARK(BM_PeriodicSampler_LongSample); - -void BM_PeriodicSampler_LongSampleMinunumInlined(benchmark::State& state) { - struct Tag {}; - PeriodicSampler<Tag, 1024 * 1024> sampler; - BM_SampleMinunumInlined(&sampler, state); -} -BENCHMARK(BM_PeriodicSampler_LongSampleMinunumInlined); - -void BM_PeriodicSampler_Disabled(benchmark::State& state) { - struct Tag {}; - PeriodicSampler<Tag, 0> sampler; - BM_Sample(&sampler, state); -} -BENCHMARK(BM_PeriodicSampler_Disabled); - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/periodic_sampler_test.cc b/third_party/abseil_cpp/absl/base/internal/periodic_sampler_test.cc deleted file mode 100644 index 3b301e37ab98..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/periodic_sampler_test.cc +++ /dev/null @@ -1,177 +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/internal/periodic_sampler.h" - -#include <thread> // NOLINT(build/c++11) - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -using testing::Eq; -using testing::Return; -using testing::StrictMock; - -class MockPeriodicSampler : public PeriodicSamplerBase { - public: - virtual ~MockPeriodicSampler() = default; - - MOCK_METHOD(int, period, (), (const, noexcept)); - MOCK_METHOD(int64_t, GetExponentialBiased, (int), (noexcept)); -}; - -TEST(PeriodicSamplerBaseTest, Sample) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(16)); - EXPECT_CALL(sampler, GetExponentialBiased(16)) - .WillOnce(Return(2)) - .WillOnce(Return(3)) - .WillOnce(Return(4)); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); -} - -TEST(PeriodicSamplerBaseTest, ImmediatelySample) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16)); - EXPECT_CALL(sampler, GetExponentialBiased(16)) - .WillOnce(Return(1)) - .WillOnce(Return(2)) - .WillOnce(Return(3)); - - EXPECT_TRUE(sampler.Sample()); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); -} - -TEST(PeriodicSamplerBaseTest, Disabled) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(0)); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); -} - -TEST(PeriodicSamplerBaseTest, AlwaysOn) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(1)); - - EXPECT_TRUE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); -} - -TEST(PeriodicSamplerBaseTest, Disable) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).WillOnce(Return(16)); - EXPECT_CALL(sampler, GetExponentialBiased(16)).WillOnce(Return(3)); - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); - - EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(0)); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); -} - -TEST(PeriodicSamplerBaseTest, Enable) { - StrictMock<MockPeriodicSampler> sampler; - - EXPECT_CALL(sampler, period()).WillOnce(Return(0)); - EXPECT_FALSE(sampler.Sample()); - - EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16)); - EXPECT_CALL(sampler, GetExponentialBiased(16)) - .Times(2) - .WillRepeatedly(Return(3)); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); - EXPECT_TRUE(sampler.Sample()); - - EXPECT_FALSE(sampler.Sample()); - EXPECT_FALSE(sampler.Sample()); -} - -TEST(PeriodicSamplerTest, ConstructConstInit) { - struct Tag {}; - ABSL_CONST_INIT static PeriodicSampler<Tag> sampler; - (void)sampler; -} - -TEST(PeriodicSamplerTest, DefaultPeriod0) { - struct Tag {}; - PeriodicSampler<Tag> sampler; - EXPECT_THAT(sampler.period(), Eq(0)); -} - -TEST(PeriodicSamplerTest, DefaultPeriod) { - struct Tag {}; - PeriodicSampler<Tag, 100> sampler; - EXPECT_THAT(sampler.period(), Eq(100)); -} - -TEST(PeriodicSamplerTest, SetGlobalPeriod) { - struct Tag1 {}; - struct Tag2 {}; - PeriodicSampler<Tag1, 25> sampler1; - PeriodicSampler<Tag2, 50> sampler2; - - EXPECT_THAT(sampler1.period(), Eq(25)); - EXPECT_THAT(sampler2.period(), Eq(50)); - - std::thread thread([] { - PeriodicSampler<Tag1, 25> sampler1; - PeriodicSampler<Tag2, 50> sampler2; - EXPECT_THAT(sampler1.period(), Eq(25)); - EXPECT_THAT(sampler2.period(), Eq(50)); - sampler1.SetGlobalPeriod(10); - sampler2.SetGlobalPeriod(20); - }); - thread.join(); - - EXPECT_THAT(sampler1.period(), Eq(10)); - EXPECT_THAT(sampler2.period(), Eq(20)); -} - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/pretty_function.h b/third_party/abseil_cpp/absl/base/internal/pretty_function.h deleted file mode 100644 index 35d51676dc2e..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/pretty_function.h +++ /dev/null @@ -1,33 +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. - -#ifndef ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_ -#define ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_ - -// ABSL_PRETTY_FUNCTION -// -// In C++11, __func__ gives the undecorated name of the current function. That -// is, "main", not "int main()". Various compilers give extra macros to get the -// decorated function name, including return type and arguments, to -// differentiate between overload sets. ABSL_PRETTY_FUNCTION is a portable -// version of these macros which forwards to the correct macro on each compiler. -#if defined(_MSC_VER) -#define ABSL_PRETTY_FUNCTION __FUNCSIG__ -#elif defined(__GNUC__) -#define ABSL_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#else -#error "Unsupported compiler" -#endif - -#endif // ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/raw_logging.cc b/third_party/abseil_cpp/absl/base/internal/raw_logging.cc deleted file mode 100644 index ae8754c6a132..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/raw_logging.cc +++ /dev/null @@ -1,240 +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/base/internal/raw_logging.h" - -#include <stddef.h> -#include <cstdarg> -#include <cstdio> -#include <cstdlib> -#include <cstring> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/internal/atomic_hook.h" -#include "absl/base/log_severity.h" - -// We know how to perform low-level writes to stderr in POSIX and Windows. For -// these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED. -// Much of raw_logging.cc becomes a no-op when we can't output messages, -// although a FATAL ABSL_RAW_LOG message will still abort the process. - -// ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write() -// (as from unistd.h) -// -// This preprocessor token is also defined in raw_io.cc. If you need to copy -// this, consider moving both to config.h instead. -#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__Fuchsia__) || defined(__native_client__) || \ - defined(__EMSCRIPTEN__) || defined(__ASYLO__) - -#include <unistd.h> - -#define ABSL_HAVE_POSIX_WRITE 1 -#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1 -#else -#undef ABSL_HAVE_POSIX_WRITE -#endif - -// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall -// syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len); -// for low level operations that want to avoid libc. -#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__) -#include <sys/syscall.h> -#define ABSL_HAVE_SYSCALL_WRITE 1 -#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1 -#else -#undef ABSL_HAVE_SYSCALL_WRITE -#endif - -#ifdef _WIN32 -#include <io.h> - -#define ABSL_HAVE_RAW_IO 1 -#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1 -#else -#undef ABSL_HAVE_RAW_IO -#endif - -// 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. - -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 -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[]. -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) { - result = false; - if (static_cast<size_t>(*size) > sizeof(kTruncated)) { - n = *size - sizeof(kTruncated); // room for truncation message - } else { - n = 0; // no room for truncation message - } - } - *size -= n; - *buf += n; - return result; -} -#endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED - -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. - -// Helper for RawLog below. -// *DoRawLog writes to *buf of *size and move them past the written portion. -// It returns true iff there was no overflow or error. -bool DoRawLog(char** buf, int* size, const char* format, ...) - ABSL_PRINTF_ATTRIBUTE(3, 4); -bool DoRawLog(char** buf, int* size, const char* format, ...) { - va_list ap; - va_start(ap, format); - int n = vsnprintf(*buf, *size, format, ap); - va_end(ap); - if (n < 0 || n > *size) return false; - *size -= n; - *buf += n; - return true; -} - -void RawLogVA(absl::LogSeverity severity, const char* file, int line, - const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0); -void RawLogVA(absl::LogSeverity severity, const char* file, int line, - const char* format, va_list ap) { - char buffer[kLogBufSize]; - char* buf = buffer; - int size = sizeof(buffer); -#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED - bool enabled = true; -#else - bool enabled = false; -#endif - -#ifdef ABSL_MIN_LOG_LEVEL - if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) && - severity < absl::LogSeverity::kFatal) { - enabled = false; - } -#endif - - auto log_prefix_hook_ptr = log_prefix_hook.Load(); - if (log_prefix_hook_ptr) { - enabled = log_prefix_hook_ptr(severity, file, line, &buf, &size); - } else { - if (enabled) { - DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line); - } - } - const char* const prefix_end = buf; - -#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED - if (enabled) { - bool no_chop = VADoRawLog(&buf, &size, format, ap); - if (no_chop) { - DoRawLog(&buf, &size, "\n"); - } else { - DoRawLog(&buf, &size, "%s", kTruncated); - } - absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer)); - } -#else - static_cast<void>(format); - static_cast<void>(ap); -#endif - - // Abort the process after logging a FATAL message, even if the output itself - // was suppressed. - if (severity == absl::LogSeverity::kFatal) { - abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize); - abort(); - } -} - -} // 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); -#elif defined(ABSL_HAVE_POSIX_WRITE) - write(STDERR_FILENO, s, len); -#elif defined(ABSL_HAVE_RAW_IO) - _write(/* stderr */ 2, s, len); -#else - // stderr logging unsupported on this platform - (void) s; - (void) len; -#endif -} - -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); - RawLogVA(severity, file, line, format, ap); - 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; -#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED - return false; -#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED -} - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL - absl::base_internal::AtomicHook<InternalLogFunction> - internal_log_function(DefaultInternalLog); - -void RegisterInternalLogFunction(InternalLogFunction func) { - internal_log_function.Store(func); -} - -} // namespace raw_logging_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/raw_logging.h b/third_party/abseil_cpp/absl/base/internal/raw_logging.h deleted file mode 100644 index 20f4291b162b..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/raw_logging.h +++ /dev/null @@ -1,187 +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. -// -// Thread-safe logging routines that do not allocate any memory or -// acquire any locks, and can therefore be used by low-level memory -// allocation, synchronization, and signal-handling code. - -#ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_ -#define ABSL_BASE_INTERNAL_RAW_LOGGING_H_ - -#include <string> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/internal/atomic_hook.h" -#include "absl/base/log_severity.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" - -// This is similar to LOG(severity) << format..., but -// * it is to be used ONLY by low-level modules that can't use normal LOG() -// * it is designed to be a low-level logger that does not allocate any -// memory and does not need any locks, hence: -// * it logs straight and ONLY to STDERR w/o buffering -// * it uses an explicit printf-format and arguments list -// * it will silently chop off really long message strings -// Usage example: -// ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error); -// This will print an almost standard log line like this to stderr only: -// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file - -#define ABSL_RAW_LOG(severity, ...) \ - do { \ - constexpr const char* absl_raw_logging_internal_basename = \ - ::absl::raw_logging_internal::Basename(__FILE__, \ - sizeof(__FILE__) - 1); \ - ::absl::raw_logging_internal::RawLog(ABSL_RAW_LOGGING_INTERNAL_##severity, \ - absl_raw_logging_internal_basename, \ - __LINE__, __VA_ARGS__); \ - } while (0) - -// Similar to CHECK(condition) << message, but for low-level modules: -// we use only ABSL_RAW_LOG that does not allocate memory. -// We do not want to provide args list here to encourage this usage: -// if (!cond) ABSL_RAW_LOG(FATAL, "foo ...", hard_to_compute_args); -// so that the args are not computed when not needed. -#define ABSL_RAW_CHECK(condition, message) \ - do { \ - if (ABSL_PREDICT_FALSE(!(condition))) { \ - ABSL_RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \ - } \ - } while (0) - -// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above, -// except that if the richer log library is linked into the binary, we dispatch -// to that instead. This is potentially useful for internal logging and -// assertions, where we are using RAW_LOG neither for its async-signal-safety -// nor for its non-allocating nature, but rather because raw logging has very -// few other dependencies. -// -// 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; \ - } while (0) - -#define ABSL_INTERNAL_CHECK(condition, message) \ - do { \ - if (ABSL_PREDICT_FALSE(!(condition))) { \ - std::string death_message = "Check " #condition " failed: "; \ - death_message += std::string(message); \ - ABSL_INTERNAL_LOG(FATAL, death_message); \ - } \ - } while (0) - -#define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo -#define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning -#define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError -#define ABSL_RAW_LOGGING_INTERNAL_FATAL ::absl::LogSeverity::kFatal -#define ABSL_RAW_LOGGING_INTERNAL_LEVEL(severity) \ - ::absl::NormalizeLogSeverity(severity) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace raw_logging_internal { - -// Helper function to implement ABSL_RAW_LOG -// Logs format... at "severity" level, reporting it -// as called from file:line. -// This does not allocate memory or acquire locks. -void RawLog(absl::LogSeverity severity, const char* file, int line, - const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5); - -// Writes the provided buffer directly to stderr, in a safe, low-level manner. -// -// In POSIX this means calling write(), which is async-signal safe and does -// not malloc. If the platform supports the SYS_write syscall, we invoke that -// directly to side-step any libc interception. -void SafeWriteToStderr(const char *s, size_t len); - -// compile-time function to get the "base" filename, that is, the part of -// a filename after the last "/" or "\" path separator. The search starts at -// the end of the string; the second parameter is the length of the string. -constexpr const char* Basename(const char* fname, int offset) { - return offset == 0 || fname[offset - 1] == '/' || fname[offset - 1] == '\\' - ? fname + offset - : Basename(fname, offset - 1); -} - -// For testing only. -// Returns true if raw logging is fully supported. When it is not -// fully supported, no messages will be emitted, but a log at FATAL -// severity will cause an abort. -// -// TODO(gfalcon): Come up with a better name for this method. -bool RawLoggingFullySupported(); - -// Function type for a raw_logging customization hook for suppressing messages -// by severity, and for writing custom prefixes on non-suppressed messages. -// -// The installed hook is called for every raw log invocation. The message will -// be logged to stderr only if the hook returns true. FATAL errors will cause -// the process to abort, even if writing to stderr is suppressed. The hook is -// also provided with an output buffer, where it can write a custom log message -// prefix. -// -// The raw_logging system does not allocate memory or grab locks. User-provided -// hooks must avoid these operations, and must not throw exceptions. -// -// 'severity' is the severity level of the message being written. -// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro -// was located. -// 'buffer' and 'buf_size' are pointers to the buffer and buffer size. If the -// hook writes a prefix, it must increment *buffer and decrement *buf_size -// accordingly. -using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file, - int line, char** buffer, int* buf_size); - -// Function type for a raw_logging customization hook called to abort a process -// when a FATAL message is logged. If the provided AbortHook() returns, the -// logging system will call abort(). -// -// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro -// was located. -// The NUL-terminated logged message lives in the buffer between 'buf_start' -// and 'buf_end'. 'prefix_end' points to the first non-prefix character of the -// buffer (as written by the LogPrefixHook.) -using AbortHook = void (*)(const char* file, int line, const char* buf_start, - const char* prefix_end, const char* buf_end); - -// Internal logging function for ABSL_INTERNAL_LOG to dispatch to. -// -// TODO(gfalcon): When string_view no longer depends on base, change this -// interface to take its message as a string_view instead. -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< - InternalLogFunction> - internal_log_function; - -void RegisterInternalLogFunction(InternalLogFunction func); - -} // namespace raw_logging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_RAW_LOGGING_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/scheduling_mode.h b/third_party/abseil_cpp/absl/base/internal/scheduling_mode.h deleted file mode 100644 index 8be5ab6dd3c0..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/scheduling_mode.h +++ /dev/null @@ -1,58 +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. -// -// Core interfaces and definitions used by by low-level interfaces such as -// SpinLock. - -#ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ -#define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Used to describe how a thread may be scheduled. Typically associated with -// the declaration of a resource supporting synchronized access. -// -// SCHEDULE_COOPERATIVE_AND_KERNEL: -// Specifies that when waiting, a cooperative thread (e.g. a Fiber) may -// reschedule (using base::scheduling semantics); allowing other cooperative -// threads to proceed. -// -// SCHEDULE_KERNEL_ONLY: (Also described as "non-cooperative") -// Specifies that no cooperative scheduling semantics may be used, even if the -// current thread is itself cooperatively scheduled. This means that -// cooperative threads will NOT allow other cooperative threads to execute in -// their place while waiting for a resource of this type. Host operating system -// semantics (e.g. a futex) may still be used. -// -// When optional, clients should strongly prefer SCHEDULE_COOPERATIVE_AND_KERNEL -// by default. SCHEDULE_KERNEL_ONLY should only be used for resources on which -// base::scheduling (e.g. the implementation of a Scheduler) may depend. -// -// NOTE: Cooperative resources may not be nested below non-cooperative ones. -// This means that it is invalid to to acquire a SCHEDULE_COOPERATIVE_AND_KERNEL -// resource if a SCHEDULE_KERNEL_ONLY resource is already held. -enum SchedulingMode { - SCHEDULE_KERNEL_ONLY = 0, // Allow scheduling only the host OS. - SCHEDULE_COOPERATIVE_AND_KERNEL, // Also allow cooperative scheduling. -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/scoped_set_env.cc b/third_party/abseil_cpp/absl/base/internal/scoped_set_env.cc deleted file mode 100644 index 8a934cb51191..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/scoped_set_env.cc +++ /dev/null @@ -1,81 +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/internal/scoped_set_env.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include <cstdlib> - -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -namespace { - -#ifdef _WIN32 -const int kMaxEnvVarValueSize = 1024; -#endif - -void SetEnvVar(const char* name, const char* value) { -#ifdef _WIN32 - SetEnvironmentVariableA(name, value); -#else - if (value == nullptr) { - ::unsetenv(name); - } else { - ::setenv(name, value, 1); - } -#endif -} - -} // namespace - -ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value) - : var_name_(var_name), was_unset_(false) { -#ifdef _WIN32 - char buf[kMaxEnvVarValueSize]; - auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf)); - ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size"); - - if (get_res == 0) { - was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND); - } else { - old_value_.assign(buf, get_res); - } - - SetEnvironmentVariableA(var_name_.c_str(), new_value); -#else - const char* val = ::getenv(var_name_.c_str()); - if (val == nullptr) { - was_unset_ = true; - } else { - old_value_ = val; - } -#endif - - SetEnvVar(var_name_.c_str(), new_value); -} - -ScopedSetEnv::~ScopedSetEnv() { - SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str()); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/scoped_set_env.h b/third_party/abseil_cpp/absl/base/internal/scoped_set_env.h deleted file mode 100644 index 19ec7b5d8a04..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/scoped_set_env.h +++ /dev/null @@ -1,45 +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_BASE_INTERNAL_SCOPED_SET_ENV_H_ -#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_ - -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -class ScopedSetEnv { - public: - ScopedSetEnv(const char* var_name, const char* new_value); - ~ScopedSetEnv(); - - private: - std::string var_name_; - std::string old_value_; - - // True if the environment variable was initially not set. - bool was_unset_; -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/scoped_set_env_test.cc b/third_party/abseil_cpp/absl/base/internal/scoped_set_env_test.cc deleted file mode 100644 index 5cbad246c647..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/scoped_set_env_test.cc +++ /dev/null @@ -1,99 +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. - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include "gtest/gtest.h" -#include "absl/base/internal/scoped_set_env.h" - -namespace { - -using absl::base_internal::ScopedSetEnv; - -std::string GetEnvVar(const char* name) { -#ifdef _WIN32 - char buf[1024]; - auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf)); - if (get_res >= sizeof(buf)) { - return "TOO_BIG"; - } - - if (get_res == 0) { - return "UNSET"; - } - - return std::string(buf, get_res); -#else - const char* val = ::getenv(name); - if (val == nullptr) { - return "UNSET"; - } - - return val; -#endif -} - -TEST(ScopedSetEnvTest, SetNonExistingVarToString) { - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); - - { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value"); - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value"); - } - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); -} - -TEST(ScopedSetEnvTest, SetNonExistingVarToNull) { - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); - - { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr); - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); - } - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); -} - -TEST(ScopedSetEnvTest, SetExistingVarToString) { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value"); - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value"); - - { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "new_value"); - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "new_value"); - } - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value"); -} - -TEST(ScopedSetEnvTest, SetExistingVarToNull) { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value"); - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value"); - - { - ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr); - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET"); - } - - EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value"); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock.cc b/third_party/abseil_cpp/absl/base/internal/spinlock.cc deleted file mode 100644 index a7d44f3eb091..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock.cc +++ /dev/null @@ -1,220 +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/base/internal/spinlock.h" - -#include <algorithm> -#include <atomic> -#include <limits> - -#include "absl/base/attributes.h" -#include "absl/base/internal/atomic_hook.h" -#include "absl/base/internal/cycleclock.h" -#include "absl/base/internal/spinlock_wait.h" -#include "absl/base/internal/sysinfo.h" /* For NumCPUs() */ -#include "absl/base/call_once.h" - -// Description of lock-word: -// 31..00: [............................3][2][1][0] -// -// [0]: kSpinLockHeld -// [1]: kSpinLockCooperative -// [2]: kSpinLockDisabledScheduling -// [31..3]: ONLY kSpinLockSleeper OR -// Wait time in cycles >> PROFILE_TIMESTAMP_SHIFT -// -// Detailed descriptions: -// -// Bit [0]: The lock is considered held iff kSpinLockHeld is set. -// -// Bit [1]: Eligible waiters (e.g. Fibers) may co-operatively reschedule when -// contended iff kSpinLockCooperative is set. -// -// Bit [2]: This bit is exclusive from bit [1]. It is used only by a -// non-cooperative lock. When set, indicates that scheduling was -// successfully disabled when the lock was acquired. May be unset, -// even if non-cooperative, if a ThreadIdentity did not yet exist at -// time of acquisition. -// -// Bit [3]: If this is the only upper bit ([31..3]) set then this lock was -// acquired without contention, however, at least one waiter exists. -// -// Otherwise, bits [31..3] represent the time spent by the current lock -// holder to acquire the lock. There may be outstanding waiter(s). - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static base_internal::AtomicHook<void (*)( - const void *lock, int64_t wait_cycles)> - submit_profile_data; - -void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock, - int64_t wait_cycles)) { - 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); -} - -// 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. -uint32_t SpinLock::SpinLoop() { - // We are already in the slow path of SpinLock, initialize the - // adaptive_spin_count here. - ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count; - ABSL_CONST_INIT static int adaptive_spin_count = 0; - base_internal::LowLevelCallOnce(&init_adaptive_spin_count, []() { - adaptive_spin_count = base_internal::NumCPUs() > 1 ? 1000 : 1; - }); - - int c = adaptive_spin_count; - uint32_t lock_value; - do { - lock_value = lockword_.load(std::memory_order_relaxed); - } while ((lock_value & kSpinLockHeld) != 0 && --c > 0); - return lock_value; -} - -void SpinLock::SlowLock() { - uint32_t lock_value = SpinLoop(); - lock_value = TryLockInternal(lock_value, 0); - 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 - // obtains the lock. - int64_t wait_start_time = CycleClock::Now(); - uint32_t wait_cycles = 0; - int lock_wait_call_count = 0; - while ((lock_value & kSpinLockHeld) != 0) { - // If the lock is currently held, but not marked as having a sleeper, mark - // it as having a sleeper. - if ((lock_value & kWaitTimeMask) == 0) { - // Here, just "mark" that the thread is going to sleep. Don't store the - // lock wait time in the lock as that will cause the current lock - // owner to think it experienced contention. - if (lockword_.compare_exchange_strong( - lock_value, lock_value | kSpinLockSleeper, - std::memory_order_relaxed, std::memory_order_relaxed)) { - // Successfully transitioned to kSpinLockSleeper. Pass - // kSpinLockSleeper to the SpinLockWait routine to properly indicate - // the last lock_value observed. - lock_value |= kSpinLockSleeper; - } else if ((lock_value & kSpinLockHeld) == 0) { - // Lock is free again, so try and acquire it before sleeping. The - // new lock state will be the number of cycles this thread waited if - // this thread obtains the lock. - lock_value = TryLockInternal(lock_value, wait_cycles); - continue; // Skip the delay at the end of the loop. - } - } - - // SpinLockDelay() calls into fiber scheduler, we need to see - // synchronization there to avoid false positives. - ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); - // Wait for an OS specific delay. - base_internal::SpinLockDelay(&lockword_, lock_value, ++lock_wait_call_count, - scheduling_mode); - ABSL_TSAN_MUTEX_POST_DIVERT(this, 0); - // Spin again after returning from the wait routine to give this thread - // some chance of obtaining the lock. - lock_value = SpinLoop(); - wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now()); - lock_value = TryLockInternal(lock_value, wait_cycles); - } -} - -void SpinLock::SlowUnlock(uint32_t lock_value) { - base_internal::SpinLockWake(&lockword_, - false); // wake waiter if necessary - - // If our acquisition was contended, collect contentionz profile info. We - // reserve a unitary wait time to represent that a waiter exists without our - // own acquisition having been contended. - if ((lock_value & kWaitTimeMask) != kSpinLockSleeper) { - const uint64_t wait_cycles = DecodeWaitCycles(lock_value); - ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); - submit_profile_data(this, wait_cycles); - ABSL_TSAN_MUTEX_POST_DIVERT(this, 0); - } -} - -// 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 -// 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; - -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; - int64_t scaled_wait_time = - (wait_end_time - wait_start_time) >> kProfileTimestampShift; - - // Return a representation of the time spent waiting that can be stored in - // the lock word's upper bits. - uint32_t clamped = static_cast<uint32_t>( - std::min(scaled_wait_time, kMaxWaitTime) << kLockwordReservedShift); - - if (clamped == 0) { - return kSpinLockSleeper; // Just wake waiters, but don't record contention. - } - // Bump up value if necessary to avoid returning kSpinLockSleeper. - const uint32_t kMinWaitTime = - kSpinLockSleeper + (1 << kLockwordReservedShift); - if (clamped == kSpinLockSleeper) { - return kMinWaitTime; - } - return clamped; -} - -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); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock.h b/third_party/abseil_cpp/absl/base/internal/spinlock.h deleted file mode 100644 index e6ac9e6400b2..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock.h +++ /dev/null @@ -1,237 +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. -// - -// Most users requiring mutual exclusion should use Mutex. -// 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. - -#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_ -#define ABSL_BASE_INTERNAL_SPINLOCK_H_ - -#include <stdint.h> -#include <sys/types.h> - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/const_init.h" -#include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/low_level_scheduling.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/scheduling_mode.h" -#include "absl/base/internal/tsan_mutex_interface.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/base/thread_annotations.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -class ABSL_LOCKABLE SpinLock { - public: - SpinLock() : lockword_(kSpinLockCooperative) { - ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); - } - - // 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); - - // 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() { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - if (!TryLockImpl()) { - SlowLock(); - } - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); - } - - // Try to acquire this SpinLock without blocking and return true if the - // acquisition was successful. If the lock was not acquired, false is - // returned. If this SpinLock is free at the time of the call, TryLock - // will return true with high probability. - inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock); - bool res = TryLockImpl(); - ABSL_TSAN_MUTEX_POST_LOCK( - this, __tsan_mutex_try_lock | (res ? 0 : __tsan_mutex_try_lock_failed), - 0); - return res; - } - - // Release this SpinLock, which must be held by the calling thread. - inline void Unlock() ABSL_UNLOCK_FUNCTION() { - ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0); - uint32_t lock_value = lockword_.load(std::memory_order_relaxed); - lock_value = lockword_.exchange(lock_value & kSpinLockCooperative, - std::memory_order_release); - - if ((lock_value & kSpinLockDisabledScheduling) != 0) { - base_internal::SchedulingGuard::EnableRescheduling(true); - } - if ((lock_value & kWaitTimeMask) != 0) { - // Collect contentionz profile info, and speed the wakeup of any waiter. - // The wait_cycles value indicates how long this thread spent waiting - // for the lock. - SlowUnlock(lock_value); - } - ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0); - } - - // Determine if the lock is held. When the lock is held by the invoking - // thread, true will always be returned. Intended to be used as - // CHECK(lock.IsHeld()). - inline bool IsHeld() const { - return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0; - } - - protected: - // These should not be exported except for testing. - - // Store number of cycles between wait_start_time and wait_end_time in a - // lock value. - static uint32_t EncodeWaitCycles(int64_t wait_start_time, - int64_t wait_end_time); - - // Extract number of wait cycles in a lock value. - static uint64_t DecodeWaitCycles(uint32_t lock_value); - - // Provide access to protected method above. Use for testing only. - friend struct SpinLockTest; - - private: - // lockword_ is used to store the following: - // - // bit[0] encodes whether a lock is being held. - // bit[1] encodes whether a lock uses cooperative scheduling. - // bit[2] encodes whether a lock disables scheduling. - // bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int. - static constexpr uint32_t kSpinLockHeld = 1; - static constexpr uint32_t kSpinLockCooperative = 2; - static constexpr uint32_t kSpinLockDisabledScheduling = 4; - static constexpr uint32_t kSpinLockSleeper = 8; - // Includes kSpinLockSleeper. - static constexpr uint32_t kWaitTimeMask = - ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling); - - // Returns true if the provided scheduling mode is cooperative. - static constexpr bool IsCooperative( - base_internal::SchedulingMode scheduling_mode) { - return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; - } - - uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles); - void SlowLock() ABSL_ATTRIBUTE_COLD; - void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD; - uint32_t SpinLoop(); - - inline bool TryLockImpl() { - uint32_t lock_value = lockword_.load(std::memory_order_relaxed); - return (TryLockInternal(lock_value, 0) & kSpinLockHeld) == 0; - } - - std::atomic<uint32_t> lockword_; - - SpinLock(const SpinLock&) = delete; - SpinLock& operator=(const SpinLock&) = delete; -}; - -// Corresponding locker object that arranges to acquire a spinlock for -// the duration of a C++ scope. -class ABSL_SCOPED_LOCKABLE SpinLockHolder { - public: - inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l) - : lock_(l) { - l->Lock(); - } - inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); } - - SpinLockHolder(const SpinLockHolder&) = delete; - SpinLockHolder& operator=(const SpinLockHolder&) = delete; - - private: - SpinLock* lock_; -}; - -// Register a hook for profiling support. -// -// The function pointer registered here will be called whenever a spinlock is -// contended. The callback is given an opaque handle to the contended spinlock -// and the number of wait cycles. This is thread-safe, but only a single -// profiler can be registered. It is an error to call this function multiple -// times with different arguments. -void RegisterSpinLockProfiler(void (*fn)(const void* lock, - int64_t wait_cycles)); - -//------------------------------------------------------------------------------ -// Public interface ends here. -//------------------------------------------------------------------------------ - -// If (result & kSpinLockHeld) == 0, then *this was successfully locked. -// Otherwise, returns last observed value for lockword_. -inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, - uint32_t wait_cycles) { - if ((lock_value & kSpinLockHeld) != 0) { - return lock_value; - } - - uint32_t sched_disabled_bit = 0; - if ((lock_value & kSpinLockCooperative) == 0) { - // For non-cooperative locks we must make sure we mark ourselves as - // non-reschedulable before we attempt to CompareAndSwap. - if (base_internal::SchedulingGuard::DisableRescheduling()) { - sched_disabled_bit = kSpinLockDisabledScheduling; - } - } - - if (!lockword_.compare_exchange_strong( - lock_value, - kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit, - std::memory_order_acquire, std::memory_order_relaxed)) { - base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0); - } - - return lock_value; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_SPINLOCK_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock_akaros.inc b/third_party/abseil_cpp/absl/base/internal/spinlock_akaros.inc deleted file mode 100644 index bc468940fc5d..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_akaros.inc +++ /dev/null @@ -1,35 +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 is an Akaros-specific part of spinlock_wait.cc - -#include <atomic> - -#include "absl/base/internal/scheduling_mode.h" - -extern "C" { - -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 - // malloc(), a blocking system call, or a uthread_yield() while holding a - // spinlock. Our callers assume will not call into libraries or other - // arbitrary code. -} - -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_benchmark.cc b/third_party/abseil_cpp/absl/base/internal/spinlock_benchmark.cc deleted file mode 100644 index 0451c65f9559..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_benchmark.cc +++ /dev/null @@ -1,52 +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. - -// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock -// and Mutex performance under varying levels of contention. - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/scheduling_mode.h" -#include "absl/base/internal/spinlock.h" -#include "absl/synchronization/internal/create_thread_identity.h" -#include "benchmark/benchmark.h" - -namespace { - -template <absl::base_internal::SchedulingMode scheduling_mode> -static void BM_SpinLock(benchmark::State& state) { - // Ensure a ThreadIdentity is installed. - ABSL_INTERNAL_CHECK( - absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() != - nullptr, - "GetOrCreateCurrentThreadIdentity() failed"); - - static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode); - for (auto _ : state) { - absl::base_internal::SpinLockHolder holder(spinlock); - } -} - -BENCHMARK_TEMPLATE(BM_SpinLock, - absl::base_internal::SCHEDULE_KERNEL_ONLY) - ->UseRealTime() - ->Threads(1) - ->ThreadPerCpu(); - -BENCHMARK_TEMPLATE(BM_SpinLock, - absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL) - ->UseRealTime() - ->Threads(1) - ->ThreadPerCpu(); - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock_linux.inc b/third_party/abseil_cpp/absl/base/internal/spinlock_linux.inc deleted file mode 100644 index e31c6ed477c0..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_linux.inc +++ /dev/null @@ -1,74 +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. -// -// This file is a Linux-specific part of spinlock_wait.cc - -#include <linux/futex.h> -#include <sys/syscall.h> -#include <unistd.h> - -#include <atomic> -#include <climits> -#include <cstdint> -#include <ctime> - -#include "absl/base/attributes.h" -#include "absl/base/internal/errno_saver.h" - -// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that -// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected -// by SYS_futex. We also assume that reads/writes done to the lockword -// by SYS_futex have rational semantics with regard to the -// std::atomic<> API. C++ provides no guarantees of these assumptions, -// but they are believed to hold in practice. -static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int), - "SpinLock lockword has the wrong size for a 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_PRIVATE_FLAG -#define FUTEX_PRIVATE_FLAG 128 -#endif -#endif - -#if defined(__NR_futex_time64) && !defined(SYS_futex_time64) -#define SYS_futex_time64 __NR_futex_time64 -#endif - -#if defined(SYS_futex_time64) && !defined(SYS_futex) -#define SYS_futex SYS_futex_time64 -#endif - -extern "C" { - -ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay( - std::atomic<uint32_t> *w, uint32_t value, int loop, - absl::base_internal::SchedulingMode) { - absl::base_internal::ErrnoSaver errno_saver; - struct timespec tm; - tm.tv_sec = 0; - tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop); - syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm); -} - -ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, - bool all) { - syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0); -} - -} // extern "C" diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock_posix.inc b/third_party/abseil_cpp/absl/base/internal/spinlock_posix.inc deleted file mode 100644 index fcd21b151b6e..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_posix.inc +++ /dev/null @@ -1,46 +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 is a Posix-specific part of spinlock_wait.cc - -#include <sched.h> - -#include <atomic> -#include <ctime> - -#include "absl/base/internal/errno_saver.h" -#include "absl/base/internal/scheduling_mode.h" -#include "absl/base/port.h" - -extern "C" { - -ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay( - std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop, - absl::base_internal::SchedulingMode /* mode */) { - absl::base_internal::ErrnoSaver errno_saver; - if (loop == 0) { - } else if (loop == 1) { - sched_yield(); - } else { - struct timespec tm; - tm.tv_sec = 0; - tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop); - nanosleep(&tm, nullptr); - } -} - -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.cc b/third_party/abseil_cpp/absl/base/internal/spinlock_wait.cc deleted file mode 100644 index fa824be1c008..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_wait.cc +++ /dev/null @@ -1,81 +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. - -// The OS-specific header included below must provide two calls: -// AbslInternalSpinLockDelay() and AbslInternalSpinLockWake(). -// See spinlock_wait.h for the specs. - -#include <atomic> -#include <cstdint> - -#include "absl/base/internal/spinlock_wait.h" - -#if defined(_WIN32) -#include "absl/base/internal/spinlock_win32.inc" -#elif defined(__linux__) -#include "absl/base/internal/spinlock_linux.inc" -#elif defined(__akaros__) -#include "absl/base/internal/spinlock_akaros.inc" -#else -#include "absl/base/internal/spinlock_posix.inc" -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// See spinlock_wait.h for spec. -uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n, - const SpinLockWaitTransition trans[], - base_internal::SchedulingMode scheduling_mode) { - int loop = 0; - for (;;) { - uint32_t v = w->load(std::memory_order_acquire); - int i; - for (i = 0; i != n && v != trans[i].from; i++) { - } - if (i == n) { - SpinLockDelay(w, v, ++loop, scheduling_mode); // no matching transition - } else if (trans[i].to == v || // null transition - w->compare_exchange_strong(v, trans[i].to, - std::memory_order_acquire, - std::memory_order_relaxed)) { - if (trans[i].done) return v; - } - } -} - -static std::atomic<uint64_t> delay_rand; - -// Return a suggested delay in nanoseconds for iteration number "loop" -int SpinLockSuggestedDelayNS(int loop) { - // Weak pseudo-random number generator to get some spread between threads - // when many are spinning. - uint64_t r = delay_rand.load(std::memory_order_relaxed); - r = 0x5deece66dLL * r + 0xb; // numbers from nrand48() - delay_rand.store(r, std::memory_order_relaxed); - - if (loop < 0 || loop > 32) { // limit loop to 0..32 - loop = 32; - } - const int kMinDelay = 128 << 10; // 128us - // Double delay every 8 iterations, up to 16x (2ms). - int delay = kMinDelay << (loop / 8); - // Randomize in delay..2*delay range, for resulting 128us..4ms range. - return delay | ((delay - 1) & static_cast<int>(r)); -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/spinlock_wait.h b/third_party/abseil_cpp/absl/base/internal/spinlock_wait.h deleted file mode 100644 index 169bc749fbc5..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_wait.h +++ /dev/null @@ -1,93 +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. - -#ifndef ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_ -#define ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_ - -// Operations to make atomic transitions on a word, and to allow -// waiting for those transitions to become possible. - -#include <stdint.h> -#include <atomic> - -#include "absl/base/internal/scheduling_mode.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// SpinLockWait() waits until it can perform one of several transitions from -// "from" to "to". It returns when it performs a transition where done==true. -struct SpinLockWaitTransition { - uint32_t from; - uint32_t to; - bool done; -}; - -// Wait until *w can transition from trans[i].from to trans[i].to for some i -// 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. -uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n, - const SpinLockWaitTransition trans[], - SchedulingMode scheduling_mode); - -// If possible, wake some thread that has called SpinLockDelay(w, ...). If -// "all" is true, wake all such threads. This call is a hint, and on some -// systems it may be a no-op; threads calling SpinLockDelay() will always wake -// eventually even if SpinLockWake() is never called. -void SpinLockWake(std::atomic<uint32_t> *w, bool all); - -// Wait for an appropriate spin delay on iteration "loop" of a -// spin loop on location *w, whose previously observed value was "value". -// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick, -// or may wait for a delay that can be truncated by a call to SpinLockWake(w). -// In all cases, it must return in bounded time even if SpinLockWake() is not -// called. -void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop, - base_internal::SchedulingMode scheduling_mode); - -// Helper used by AbslInternalSpinLockDelay. -// Returns a suggested delay in nanoseconds for iteration number "loop". -int SpinLockSuggestedDelayNS(int loop); - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -// In some build configurations we pass --detect-odr-violations to the -// gold linker. This causes it to flag weak symbol overrides as ODR -// violations. Because ODR only applies to C++ and not C, -// --detect-odr-violations ignores symbols not mangled with C++ names. -// By changing our extension points to be extern "C", we dodge this -// check. -extern "C" { -void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, bool all); -void AbslInternalSpinLockDelay( - std::atomic<uint32_t> *w, uint32_t value, int loop, - absl::base_internal::SchedulingMode scheduling_mode); -} - -inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w, - bool all) { - AbslInternalSpinLockWake(w, all); -} - -inline void absl::base_internal::SpinLockDelay( - std::atomic<uint32_t> *w, uint32_t value, int loop, - absl::base_internal::SchedulingMode scheduling_mode) { - AbslInternalSpinLockDelay(w, value, loop, scheduling_mode); -} - -#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 deleted file mode 100644 index 78654b5b5966..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/spinlock_win32.inc +++ /dev/null @@ -1,37 +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 is a Win32-specific part of spinlock_wait.cc - -#include <windows.h> -#include <atomic> -#include "absl/base/internal/scheduling_mode.h" - -extern "C" { - -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); - } else { - Sleep(absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000); - } -} - -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 d66ba1201135..000000000000 --- 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) { - absl::base_internal::ErrnoSaver errno_saver; - 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) { - 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 350097366eed..000000000000 --- 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 c9ab14a89dbb..000000000000 --- 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 a53da97f92c9..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/strerror_test.cc +++ /dev/null @@ -1,86 +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); - // 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(absl::base_internal::StrError(i), Eq(expected_strings[i])); - } - EXPECT_THAT(errno, Eq(ERANGE)); - } - }; - - 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 deleted file mode 100644 index 4a3b205034a7..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/sysinfo.cc +++ /dev/null @@ -1,439 +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/base/internal/sysinfo.h" - -#include "absl/base/attributes.h" - -#ifdef _WIN32 -#include <windows.h> -#else -#include <fcntl.h> -#include <pthread.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> -#endif - -#ifdef __linux__ -#include <sys/syscall.h> -#endif - -#if defined(__APPLE__) || defined(__FreeBSD__) -#include <sys/sysctl.h> -#endif - -#if defined(__myriad2__) -#include <rtems.h> -#endif - -#include <string.h> - -#include <cassert> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <ctime> -#include <limits> -#include <thread> // NOLINT(build/c++11) -#include <utility> -#include <vector> - -#include "absl/base/call_once.h" -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" -#include "absl/base/internal/unscaledcycleclock.h" -#include "absl/base/thread_annotations.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -static int GetNumCPUs() { -#if defined(__myriad2__) - return 1; -#else - // Other possibilities: - // - Read /sys/devices/system/cpu/online and use cpumask_parse() - // - sysconf(_SC_NPROCESSORS_ONLN) - return std::thread::hardware_concurrency(); -#endif -} - -#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 - // pulls in gdi32.dll which makes process destruction much more costly. - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, - KEY_READ, &key) == ERROR_SUCCESS) { - DWORD type = 0; - DWORD data = 0; - DWORD data_size = sizeof(data); - auto result = RegQueryValueExA(key, "~MHz", 0, &type, - reinterpret_cast<LPBYTE>(&data), &data_size); - RegCloseKey(key); - if (result == ERROR_SUCCESS && type == REG_DWORD && - data_size == sizeof(data)) { - return data * 1e6; // Value is MHz. - } - } - return 1.0; -#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP -} - -#elif defined(CTL_HW) && defined(HW_CPU_FREQ) - -static double GetNominalCPUFrequency() { - unsigned freq; - size_t size = sizeof(freq); - int mib[2] = {CTL_HW, HW_CPU_FREQ}; - if (sysctl(mib, 2, &freq, &size, nullptr, 0) == 0) { - return static_cast<double>(freq); - } - return 1.0; -} - -#else - -// Helper function for reading a long from a file. Returns true if successful -// and the memory location pointed to by value is set to the value read. -static bool ReadLongFromFile(const char *file, long *value) { - bool ret = false; - int fd = open(file, O_RDONLY); - if (fd != -1) { - char line[1024]; - char *err; - memset(line, '\0', sizeof(line)); - int len = read(fd, line, sizeof(line) - 1); - if (len <= 0) { - ret = false; - } else { - const long temp_value = strtol(line, &err, 10); - if (line[0] != '\0' && (*err == '\n' || *err == '\0')) { - *value = temp_value; - ret = true; - } - } - close(fd); - } - return ret; -} - -#if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY) - -// Reads a monotonic time source and returns a value in -// nanoseconds. The returned value uses an arbitrary epoch, not the -// Unix epoch. -static int64_t ReadMonotonicClockNanos() { - struct timespec t; -#ifdef CLOCK_MONOTONIC_RAW - int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &t); -#else - int rc = clock_gettime(CLOCK_MONOTONIC, &t); -#endif - if (rc != 0) { - perror("clock_gettime() failed"); - abort(); - } - return int64_t{t.tv_sec} * 1000000000 + t.tv_nsec; -} - -class UnscaledCycleClockWrapperForInitializeFrequency { - public: - static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); } -}; - -struct TimeTscPair { - int64_t time; // From ReadMonotonicClockNanos(). - int64_t tsc; // From UnscaledCycleClock::Now(). -}; - -// Returns a pair of values (monotonic kernel time, TSC ticks) that -// approximately correspond to each other. This is accomplished by -// doing several reads and picking the reading with the lowest -// latency. This approach is used to minimize the probability that -// our thread was preempted between clock reads. -static TimeTscPair GetTimeTscPair() { - int64_t best_latency = std::numeric_limits<int64_t>::max(); - TimeTscPair best; - for (int i = 0; i < 10; ++i) { - int64_t t0 = ReadMonotonicClockNanos(); - int64_t tsc = UnscaledCycleClockWrapperForInitializeFrequency::Now(); - int64_t t1 = ReadMonotonicClockNanos(); - int64_t latency = t1 - t0; - if (latency < best_latency) { - best_latency = latency; - best.time = t0; - best.tsc = tsc; - } - } - return best; -} - -// Measures and returns the TSC frequency by taking a pair of -// measurements approximately `sleep_nanoseconds` apart. -static double MeasureTscFrequencyWithSleep(int sleep_nanoseconds) { - auto t0 = GetTimeTscPair(); - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = sleep_nanoseconds; - while (nanosleep(&ts, &ts) != 0 && errno == EINTR) {} - auto t1 = GetTimeTscPair(); - double elapsed_ticks = t1.tsc - t0.tsc; - double elapsed_time = (t1.time - t0.time) * 1e-9; - return elapsed_ticks / elapsed_time; -} - -// Measures and returns the TSC frequency by calling -// MeasureTscFrequencyWithSleep(), doubling the sleep interval until the -// frequency measurement stabilizes. -static double MeasureTscFrequency() { - double last_measurement = -1.0; - int sleep_nanoseconds = 1000000; // 1 millisecond. - for (int i = 0; i < 8; ++i) { - double measurement = MeasureTscFrequencyWithSleep(sleep_nanoseconds); - if (measurement * 0.99 < last_measurement && - last_measurement < measurement * 1.01) { - // Use the current measurement if it is within 1% of the - // previous measurement. - return measurement; - } - last_measurement = measurement; - sleep_nanoseconds *= 2; - } - return last_measurement; -} - -#endif // ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY - -static double GetNominalCPUFrequency() { - long freq = 0; - - // Google's production kernel has a patch to export the TSC - // frequency through sysfs. If the kernel is exporting the TSC - // frequency use that. There are issues where cpuinfo_max_freq - // cannot be relied on because the BIOS may be exporting an invalid - // p-state (on x86) or p-states may be used to put the processor in - // a new mode (turbo mode). Essentially, those frequencies cannot - // always be relied upon. The same reasons apply to /proc/cpuinfo as - // well. - if (ReadLongFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) { - return freq * 1e3; // Value is kHz. - } - -#if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY) - // On these platforms, the TSC frequency is the nominal CPU - // frequency. But without having the kernel export it directly - // though /sys/devices/system/cpu/cpu0/tsc_freq_khz, there is no - // other way to reliably get the TSC frequency, so we have to - // measure it ourselves. Some CPUs abuse cpuinfo_max_freq by - // exporting "fake" frequencies for implementing new features. For - // example, Intel's turbo mode is enabled by exposing a p-state - // value with a higher frequency than that of the real TSC - // rate. Because of this, we prefer to measure the TSC rate - // ourselves on i386 and x86-64. - return MeasureTscFrequency(); -#else - - // If CPU scaling is in effect, we want to use the *maximum* - // frequency, not whatever CPU speed some random processor happens - // to be using now. - if (ReadLongFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", - &freq)) { - return freq * 1e3; // Value is kHz. - } - - return 1.0; -#endif // !ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY -} - -#endif - -ABSL_CONST_INIT static once_flag init_num_cpus_once; -ABSL_CONST_INIT static int num_cpus = 0; - -// NumCPUs() may be called before main() and before malloc is properly -// initialized, therefore this must not allocate memory. -int NumCPUs() { - base_internal::LowLevelCallOnce( - &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); }); - return num_cpus; -} - -// A default frequency of 0.0 might be dangerous if it is used in division. -ABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once; -ABSL_CONST_INIT static double nominal_cpu_frequency = 1.0; - -// NominalCPUFrequency() may be called before main() and before malloc is -// properly initialized, therefore this must not allocate memory. -double NominalCPUFrequency() { - base_internal::LowLevelCallOnce( - &init_nominal_cpu_frequency_once, - []() { nominal_cpu_frequency = GetNominalCPUFrequency(); }); - return nominal_cpu_frequency; -} - -#if defined(_WIN32) - -pid_t GetTID() { - return pid_t{GetCurrentThreadId()}; -} - -#elif defined(__linux__) - -#ifndef SYS_gettid -#define SYS_gettid __NR_gettid -#endif - -pid_t GetTID() { - return syscall(SYS_gettid); -} - -#elif defined(__akaros__) - -pid_t GetTID() { - // Akaros has a concept of "vcore context", which is the state the program - // is forced into when we need to make a user-level scheduling decision, or - // run a signal handler. This is analogous to the interrupt context that a - // CPU might enter if it encounters some kind of exception. - // - // There is no current thread context in vcore context, but we need to give - // a reasonable answer if asked for a thread ID (e.g., in a signal handler). - // Thread 0 always exists, so if we are in vcore context, we return that. - // - // Otherwise, we know (since we are using pthreads) that the uthread struct - // current_uthread is pointing to is the first element of a - // struct pthread_tcb, so we extract and return the thread ID from that. - // - // TODO(dcross): Akaros anticipates moving the thread ID to the uthread - // structure at some point. We should modify this code to remove the cast - // when that happens. - if (in_vcore_context()) - return 0; - return reinterpret_cast<struct pthread_tcb *>(current_uthread)->id; -} - -#elif defined(__myriad2__) - -pid_t GetTID() { - uint32_t tid; - rtems_task_ident(RTEMS_SELF, 0, &tid); - return tid; -} - -#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); - -// 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 constexpr int kBitsPerWord = 32; // tid_array is uint32_t. - -// Returns the TID to tid_array. -static void FreeTID(void *v) { - intptr_t tid = reinterpret_cast<intptr_t>(v); - int word = tid / kBitsPerWord; - uint32_t mask = ~(1u << (tid % kBitsPerWord)); - absl::base_internal::SpinLockHolder lock(&tid_lock); - assert(0 <= word && static_cast<size_t>(word) < tid_array->size()); - (*tid_array)[word] &= mask; -} - -static void InitGetTID() { - if (pthread_key_create(&tid_key, FreeTID) != 0) { - // The logging system calls GetTID() so it can't be used here. - perror("pthread_key_create failed"); - abort(); - } - - // Initialize tid_array. - absl::base_internal::SpinLockHolder lock(&tid_lock); - tid_array = new std::vector<uint32_t>(1); - (*tid_array)[0] = 1; // ID 0 is never-allocated. -} - -// Return a per-thread small integer ID from pthread's thread-specific data. -pid_t GetTID() { - absl::call_once(tid_once, InitGetTID); - - intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key)); - if (tid != 0) { - return tid; - } - - int bit; // tid_array[word] = 1u << bit; - size_t word; - { - // Search for the first unused ID. - absl::base_internal::SpinLockHolder lock(&tid_lock); - // First search for a word in the array that is not all ones. - word = 0; - while (word < tid_array->size() && ~(*tid_array)[word] == 0) { - ++word; - } - if (word == tid_array->size()) { - tid_array->push_back(0); // No space left, add kBitsPerWord more IDs. - } - // Search for a zero bit in the word. - bit = 0; - while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) { - ++bit; - } - tid = (word * kBitsPerWord) + bit; - (*tid_array)[word] |= 1u << bit; // Mark the TID as allocated. - } - - if (pthread_setspecific(tid_key, reinterpret_cast<void *>(tid)) != 0) { - perror("pthread_setspecific failed"); - abort(); - } - - return static_cast<pid_t>(tid); -} - -#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 deleted file mode 100644 index 119cf1f0e85b..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/sysinfo.h +++ /dev/null @@ -1,74 +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 includes routines to find out characteristics -// of the machine a program is running on. It is undoubtedly -// system-dependent. - -// Functions listed here that accept a pid_t as an argument act on the -// current process if the pid_t argument is 0 -// All functions here are thread-hostile due to file caching unless -// commented otherwise. - -#ifndef ABSL_BASE_INTERNAL_SYSINFO_H_ -#define ABSL_BASE_INTERNAL_SYSINFO_H_ - -#ifndef _WIN32 -#include <sys/types.h> -#endif - -#include <cstdint> - -#include "absl/base/config.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Nominal core processor cycles per second of each processor. This is _not_ -// necessarily the frequency of the CycleClock counter (see cycleclock.h) -// Thread-safe. -double NominalCPUFrequency(); - -// Number of logical processors (hyperthreads) in system. Thread-safe. -int NumCPUs(); - -// Return the thread id of the current thread, as told by the system. -// No two currently-live threads implemented by the OS shall have the same ID. -// Thread ids of exited threads may be reused. Multiple user-level threads -// may have the same thread ID if multiplexed on the same OS thread. -// -// On Linux, you may send a signal to the resulting ID with kill(). However, -// it is recommended for portability that you use pthread_kill() instead. -#ifdef _WIN32 -// On Windows, process id and thread id are of the same type according to the -// return types of GetProcessId() and GetThreadId() are both DWORD, an unsigned -// 32-bit type. -using pid_t = uint32_t; -#endif -pid_t GetTID(); - -// Like GetTID(), but caches the result in thread-local storage in order -// to avoid unnecessary system calls. Note that there are some cases where -// one must call through to GetTID directly, which is why this exists as a -// separate function. For example, GetCachedTID() is not safe to call in -// an asynchronous signal-handling context nor right after a call to fork(). -pid_t GetCachedTID(); - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_SYSINFO_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/sysinfo_test.cc b/third_party/abseil_cpp/absl/base/internal/sysinfo_test.cc deleted file mode 100644 index fa8b88b1dc07..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/sysinfo_test.cc +++ /dev/null @@ -1,100 +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/base/internal/sysinfo.h" - -#ifndef _WIN32 -#include <sys/types.h> -#include <unistd.h> -#endif - -#include <thread> // NOLINT(build/c++11) -#include <unordered_set> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/synchronization/barrier.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -TEST(SysinfoTest, NumCPUs) { - EXPECT_NE(NumCPUs(), 0) - << "NumCPUs() should not have the default value of 0"; -} - -TEST(SysinfoTest, NominalCPUFrequency) { -#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 -} - -TEST(SysinfoTest, GetTID) { - EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test. -#ifdef __native_client__ - // Native Client has a race condition bug that leads to memory - // exaustion when repeatedly creating and joining threads. - // https://bugs.chromium.org/p/nativeclient/issues/detail?id=1027 - return; -#endif - // Test that TIDs are unique to each thread. - // Uses a few loops to exercise implementations that reallocate IDs. - for (int i = 0; i < 10; ++i) { - constexpr int kNumThreads = 10; - Barrier all_threads_done(kNumThreads); - std::vector<std::thread> threads; - - Mutex mutex; - std::unordered_set<pid_t> tids; - - for (int j = 0; j < kNumThreads; ++j) { - threads.push_back(std::thread([&]() { - pid_t id = GetTID(); - { - MutexLock lock(&mutex); - ASSERT_TRUE(tids.find(id) == tids.end()); - tids.insert(id); - } - // We can't simply join the threads here. The threads need to - // be alive otherwise the TID might have been reallocated to - // another live thread. - all_threads_done.Block(); - })); - } - for (auto& thread : threads) { - thread.join(); - } - } -} - -#ifdef __linux__ -TEST(SysinfoTest, LinuxGetTID) { - // On Linux, for the main thread, GetTID()==getpid() is guaranteed by the API. - EXPECT_EQ(GetTID(), getpid()); -} -#endif - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/thread_annotations.h b/third_party/abseil_cpp/absl/base/internal/thread_annotations.h deleted file mode 100644 index 4dab6a9c150a..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/thread_annotations.h +++ /dev/null @@ -1,271 +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. -// -// ----------------------------------------------------------------------------- -// File: thread_annotations.h -// ----------------------------------------------------------------------------- -// -// WARNING: This is a backwards compatible header and it will be removed after -// the migration to prefixed thread annotations is finished; please include -// "absl/base/thread_annotations.h". -// -// This header file contains macro definitions for thread safety annotations -// that allow developers to document the locking policies of multi-threaded -// code. The annotations can also help program analysis tools to identify -// potential thread safety issues. -// -// These annotations are implemented using compiler attributes. Using the macros -// defined here instead of raw attributes allow for portability and future -// compatibility. -// -// When referring to mutexes in the arguments of the attributes, you should -// use variable names or more complex expressions (e.g. my_object->mutex_) -// that evaluate to a concrete mutex object whenever possible. If the mutex -// you want to refer to is not in scope, you may use a member pointer -// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object. - -#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ -#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ - -#if defined(__clang__) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -// GUARDED_BY() -// -// Documents if a shared field or global variable needs to be protected by a -// mutex. GUARDED_BY() allows the user to specify a particular mutex that -// should be held when accessing the annotated variable. -// -// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to -// local variables, a local variable and its associated mutex can often be -// combined into a small class or struct, thereby allowing the annotation. -// -// Example: -// -// class Foo { -// Mutex mu_; -// int p1_ GUARDED_BY(mu_); -// ... -// }; -#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -// PT_GUARDED_BY() -// -// Documents if the memory location pointed to by a pointer should be guarded -// by a mutex when dereferencing the pointer. -// -// Example: -// class Foo { -// Mutex mu_; -// int *p1_ PT_GUARDED_BY(mu_); -// ... -// }; -// -// Note that a pointer variable to a shared memory location could itself be a -// shared variable. -// -// Example: -// -// // `q_`, guarded by `mu1_`, points to a shared memory location that is -// // guarded by `mu2_`: -// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_); -#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -// ACQUIRED_AFTER() / ACQUIRED_BEFORE() -// -// Documents the acquisition order between locks that can be held -// simultaneously by a thread. For any two locks that need to be annotated -// to establish an acquisition order, only one of them needs the annotation. -// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER -// and ACQUIRED_BEFORE.) -// -// As with GUARDED_BY, this is only applicable to mutexes that are shared -// fields or global variables. -// -// Example: -// -// Mutex m1_; -// Mutex m2_ ACQUIRED_AFTER(m1_); -#define ACQUIRED_AFTER(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define ACQUIRED_BEFORE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED() -// -// Documents a function that expects a mutex to be held prior to entry. -// The mutex is expected to be held both on entry to, and exit from, the -// function. -// -// An exclusive lock allows read-write access to the guarded data member(s), and -// only one thread can acquire a lock exclusively at any one time. A shared lock -// allows read-only access, and any number of threads can acquire a shared lock -// concurrently. -// -// Generally, non-const methods should be annotated with -// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with -// SHARED_LOCKS_REQUIRED. -// -// Example: -// -// Mutex mu1, mu2; -// int a GUARDED_BY(mu1); -// int b GUARDED_BY(mu2); -// -// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... } -// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... } -#define EXCLUSIVE_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) - -#define SHARED_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) - -// LOCKS_EXCLUDED() -// -// Documents the locks acquired in the body of the function. These locks -// cannot be held when calling this function (as Abseil's `Mutex` locks are -// non-reentrant). -#define LOCKS_EXCLUDED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -// LOCK_RETURNED() -// -// Documents a function that returns a mutex without acquiring it. For example, -// a public getter method that returns a pointer to a private mutex should -// be annotated with LOCK_RETURNED. -#define LOCK_RETURNED(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -// LOCKABLE -// -// Documents if a class/type is a lockable type (such as the `Mutex` class). -#define LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(lockable) - -// SCOPED_LOCKABLE -// -// Documents if a class does RAII locking (such as the `MutexLock` class). -// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is -// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no -// arguments; the analysis will assume that the destructor unlocks whatever the -// constructor locked. -#define SCOPED_LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -// EXCLUSIVE_LOCK_FUNCTION() -// -// Documents functions that acquire a lock in the body of a function, and do -// not release it. -#define EXCLUSIVE_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) - -// SHARED_LOCK_FUNCTION() -// -// Documents functions that acquire a shared (reader) lock in the body of a -// function, and do not release it. -#define SHARED_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) - -// UNLOCK_FUNCTION() -// -// Documents functions that expect a lock to be held on entry to the function, -// and release it in the body of the function. -#define UNLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) - -// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION() -// -// Documents functions that try to acquire a lock, and return success or failure -// (or a non-boolean value that can be interpreted as a boolean). -// The first argument should be `true` for functions that return `true` on -// success, or `false` for functions that return `false` on success. The second -// argument specifies the mutex that is locked on success. If unspecified, this -// mutex is assumed to be `this`. -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) - -#define SHARED_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) - -// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK() -// -// Documents functions that dynamically check to see if a lock is held, and fail -// if it is not held. -#define ASSERT_EXCLUSIVE_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) - -#define ASSERT_SHARED_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) - -// NO_THREAD_SAFETY_ANALYSIS -// -// Turns off thread safety checking within the body of a particular function. -// This annotation is used to mark functions that are known to be correct, but -// the locking behavior is more complicated than the analyzer can handle. -#define NO_THREAD_SAFETY_ANALYSIS \ - THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - -//------------------------------------------------------------------------------ -// Tool-Supplied Annotations -//------------------------------------------------------------------------------ - -// TS_UNCHECKED should be placed around lock expressions that are not valid -// C++ syntax, but which are present for documentation purposes. These -// annotations will be ignored by the analysis. -#define TS_UNCHECKED(x) "" - -// TS_FIXME is used to mark lock expressions that are not valid C++ syntax. -// It is used by automated tools to mark and disable invalid expressions. -// The annotation should either be fixed, or changed to TS_UNCHECKED. -#define TS_FIXME(x) "" - -// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of -// a particular function. However, this attribute is used to mark functions -// that are incorrect and need to be fixed. It is used by automated tools to -// avoid breaking the build when the analysis is updated. -// Code owners are expected to eventually fix the routine. -#define NO_THREAD_SAFETY_ANALYSIS_FIXME NO_THREAD_SAFETY_ANALYSIS - -// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY -// annotation that needs to be fixed, because it is producing thread safety -// warning. It disables the GUARDED_BY. -#define GUARDED_BY_FIXME(x) - -// Disables warnings for a single read operation. This can be used to avoid -// warnings when it is known that the read is not actually involved in a race, -// but the compiler cannot confirm that. -#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x) - - -namespace thread_safety_analysis { - -// Takes a reference to a guarded data member, and returns an unguarded -// reference. -template <typename T> -inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS { - return v; -} - -template <typename T> -inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS { - return v; -} - -} // namespace thread_safety_analysis - -#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/thread_identity.cc b/third_party/abseil_cpp/absl/base/internal/thread_identity.cc deleted file mode 100644 index 6ea010ed0d31..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/thread_identity.cc +++ /dev/null @@ -1,155 +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/base/internal/thread_identity.h" - -#ifndef _WIN32 -#include <pthread.h> -#include <signal.h> -#endif - -#include <atomic> -#include <cassert> -#include <memory> - -#include "absl/base/attributes.h" -#include "absl/base/call_once.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -#if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11 -namespace { -// Used to co-ordinate one-time creation of our pthread_key -absl::once_flag init_thread_identity_key_once; -pthread_key_t thread_identity_pthread_key; -std::atomic<bool> pthread_key_initialized(false); - -void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) { - pthread_key_create(&thread_identity_pthread_key, reclaimer); - pthread_key_initialized.store(true, std::memory_order_release); -} -} // namespace -#endif - -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \ - ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 -// The actual TLS storage for a thread's currently associated ThreadIdentity. -// This is referenced by inline accessors in the header. -// "protected" visibility ensures that if multiple instances of Abseil code -// 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__) -__attribute__((visibility("protected"))) -#endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__) -#if ABSL_PER_THREAD_TLS -// Prefer __thread to thread_local as benchmarks indicate it is a bit faster. -ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr; -#elif defined(ABSL_HAVE_THREAD_LOCAL) -thread_local ThreadIdentity* thread_identity_ptr = nullptr; -#endif // ABSL_PER_THREAD_TLS -#endif // TLS or CPP11 - -void SetCurrentThreadIdentity( - ThreadIdentity* identity, ThreadIdentityReclaimerFunction reclaimer) { - assert(CurrentThreadIdentityIfPresent() == nullptr); - // Associate our destructor. - // NOTE: This call to pthread_setspecific is currently the only immovable - // barrier to CurrentThreadIdentity() always being async signal safe. -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC - // NOTE: Not async-safe. But can be open-coded. - absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey, - reclaimer); - -#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) - // Emscripten and MinGW pthread implementations does not support signals. - // See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html - // for more information. - pthread_setspecific(thread_identity_pthread_key, - reinterpret_cast<void*>(identity)); -#else - // We must mask signals around the call to setspecific as with current glibc, - // a concurrent getspecific (needed for GetCurrentThreadIdentityIfPresent()) - // may zero our value. - // - // While not officially async-signal safe, getspecific within a signal handler - // is otherwise OK. - sigset_t all_signals; - sigset_t curr_signals; - sigfillset(&all_signals); - pthread_sigmask(SIG_SETMASK, &all_signals, &curr_signals); - pthread_setspecific(thread_identity_pthread_key, - reinterpret_cast<void*>(identity)); - pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr); -#endif // !__EMSCRIPTEN__ && !__MINGW32__ - -#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS - // NOTE: Not async-safe. But can be open-coded. - absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey, - reclaimer); - pthread_setspecific(thread_identity_pthread_key, - reinterpret_cast<void*>(identity)); - thread_identity_ptr = identity; -#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 - thread_local std::unique_ptr<ThreadIdentity, ThreadIdentityReclaimerFunction> - holder(identity, reclaimer); - thread_identity_ptr = identity; -#else -#error Unimplemented ABSL_THREAD_IDENTITY_MODE -#endif -} - -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \ - ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 - -// Please see the comment on `CurrentThreadIdentityIfPresent` in -// thread_identity.h. Because DLLs cannot expose thread_local variables in -// headers, we opt for the correct-but-slower option of placing the definition -// of this function only in a translation unit inside DLL. -#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL) -ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; } -#endif -#endif - -void ClearCurrentThreadIdentity() { -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \ - ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 - thread_identity_ptr = nullptr; -#elif ABSL_THREAD_IDENTITY_MODE == \ - ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC - // pthread_setspecific expected to clear value on destruction - assert(CurrentThreadIdentityIfPresent() == nullptr); -#endif -} - -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC -ThreadIdentity* CurrentThreadIdentityIfPresent() { - bool initialized = pthread_key_initialized.load(std::memory_order_acquire); - if (!initialized) { - return nullptr; - } - return reinterpret_cast<ThreadIdentity*>( - pthread_getspecific(thread_identity_pthread_key)); -} -#endif - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/thread_identity.h b/third_party/abseil_cpp/absl/base/internal/thread_identity.h deleted file mode 100644 index d2a65fd81126..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/thread_identity.h +++ /dev/null @@ -1,260 +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. -// -// Each active thread has an ThreadIdentity that may represent the thread in -// various level interfaces. ThreadIdentity objects are never deallocated. -// When a thread terminates, its ThreadIdentity object may be reused for a -// thread created later. - -#ifndef ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ -#define ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ - -#ifndef _WIN32 -#include <pthread.h> -// Defines __GOOGLE_GRTE_VERSION__ (via glibc-specific features.h) when -// supported. -#include <unistd.h> -#endif - -#include <atomic> -#include <cstdint> - -#include "absl/base/config.h" -#include "absl/base/internal/per_thread_tls.h" -#include "absl/base/optimization.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -struct SynchLocksHeld; -struct SynchWaitParams; - -namespace base_internal { - -class SpinLock; -struct ThreadIdentity; - -// Used by the implementation of absl::Mutex and absl::CondVar. -struct PerThreadSynch { - // The internal representation of absl::Mutex and absl::CondVar rely - // on the alignment of PerThreadSynch. Both store the address of the - // PerThreadSynch in the high-order bits of their internal state, - // which means the low kLowZeroBits of the address of PerThreadSynch - // must be zero. - static constexpr int kLowZeroBits = 8; - static constexpr int kAlignment = 1 << kLowZeroBits; - - // Returns the associated ThreadIdentity. - // This can be implemented as a cast because we guarantee - // PerThreadSynch is the first element of ThreadIdentity. - ThreadIdentity* thread_identity() { - return reinterpret_cast<ThreadIdentity*>(this); - } - - PerThreadSynch *next; // Circular waiter queue; initialized to 0. - PerThreadSynch *skip; // If non-zero, all entries in Mutex queue - // up to and including "skip" have same - // condition as this, and will be woken later - bool may_skip; // if false while on mutex queue, a mutex unlocker - // 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). - - // State values: - // kAvailable: This PerThreadSynch is available. - // kQueued: This PerThreadSynch is unavailable, it's currently queued on a - // Mutex or CondVar waistlist. - // - // Transitions from kQueued to kAvailable require a release - // barrier. This is needed as a waiter may use "state" to - // independently observe that it's no longer queued. - // - // Transitions from kAvailable to kQueued require no barrier, they - // are externally ordered by the Mutex. - enum State { - kAvailable, - kQueued - }; - 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; - - intptr_t readers; // Number of readers in mutex. - - // When priority will next be read (cycles). - int64_t next_priority_read_cycles; - - // Locks held; used during deadlock detection. - // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity(). - SynchLocksHeld *all_locks; -}; - -// The instances of this class are allocated in NewThreadIdentity() with an -// alignment of PerThreadSynch::kAlignment. -struct ThreadIdentity { - // Must be the first member. The Mutex implementation requires that - // the PerThreadSynch object associated with each thread is - // PerThreadSynch::kAlignment aligned. We provide this alignment on - // ThreadIdentity itself. - PerThreadSynch per_thread_synch; - - // Private: Reserved for absl::synchronization_internal::Waiter. - struct WaiterState { - char data[128]; - } waiter_state; - - // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter(). - std::atomic<int>* blocked_count_ptr; - - // The following variables are mostly read/written just by the - // thread itself. The only exception is that these are read by - // a ticker thread as a hint. - std::atomic<int> ticker; // Tick counter, incremented once per second. - std::atomic<int> wait_start; // Ticker value when thread started waiting. - std::atomic<bool> is_idle; // Has thread become idle yet? - - ThreadIdentity* next; -}; - -// Returns the ThreadIdentity object representing the calling thread; guaranteed -// to be unique for its lifetime. The returned object will remain valid for the -// program's lifetime; although it may be re-assigned to a subsequent thread. -// If one does not exist, return nullptr instead. -// -// Does not malloc(*), and is async-signal safe. -// [*] Technically pthread_setspecific() does malloc on first use; however this -// is handled internally within tcmalloc's initialization already. -// -// New ThreadIdentity objects can be constructed and associated with a thread -// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h. -ThreadIdentity* CurrentThreadIdentityIfPresent(); - -using ThreadIdentityReclaimerFunction = void (*)(void*); - -// Sets the current thread identity to the given value. 'reclaimer' is a -// pointer to the global function for cleaning up instances on thread -// destruction. -void SetCurrentThreadIdentity(ThreadIdentity* identity, - ThreadIdentityReclaimerFunction reclaimer); - -// Removes the currently associated ThreadIdentity from the running thread. -// This must be called from inside the ThreadIdentityReclaimerFunction, and only -// from that function. -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 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 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 direcly set -#else -#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2 -#endif - -#ifdef ABSL_THREAD_IDENTITY_MODE -#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__) && \ - (__GOOGLE_GRTE_VERSION__ >= 20140228L) -// Support for async-safe TLS was specifically added in GRTEv4. It's not -// present in the upstream eglibc. -// Note: Current default for production systems. -#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS -#else -#define ABSL_THREAD_IDENTITY_MODE \ - ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC -#endif - -#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \ - ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11 - -#if ABSL_PER_THREAD_TLS -ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* - thread_identity_ptr; -#elif defined(ABSL_HAVE_THREAD_LOCAL) -ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr; -#else -#error Thread-local storage not detected on this platform -#endif - -// thread_local variables cannot be in headers exposed by DLLs. However, it is -// important for performance reasons in general that -// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a -// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note -// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude -// this entire inline definition when compiling as a DLL. -#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL) -inline ThreadIdentity* CurrentThreadIdentityIfPresent() { - return thread_identity_ptr; -} -#endif - -#elif ABSL_THREAD_IDENTITY_MODE != \ - ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC -#error Unknown ABSL_THREAD_IDENTITY_MODE -#endif - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/thread_identity_benchmark.cc b/third_party/abseil_cpp/absl/base/internal/thread_identity_benchmark.cc deleted file mode 100644 index 0ae10f2b1e8a..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/thread_identity_benchmark.cc +++ /dev/null @@ -1,38 +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 "benchmark/benchmark.h" -#include "absl/base/internal/thread_identity.h" -#include "absl/synchronization/internal/create_thread_identity.h" -#include "absl/synchronization/internal/per_thread_sem.h" - -namespace { - -void BM_SafeCurrentThreadIdentity(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()); - } -} -BENCHMARK(BM_SafeCurrentThreadIdentity); - -void BM_UnsafeCurrentThreadIdentity(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::base_internal::CurrentThreadIdentityIfPresent()); - } -} -BENCHMARK(BM_UnsafeCurrentThreadIdentity); - -} // namespace 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 deleted file mode 100644 index 46a6f7434629..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/thread_identity_test.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT 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/thread_identity.h" - -#include <thread> // NOLINT(build/c++11) -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/internal/spinlock.h" -#include "absl/base/macros.h" -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/internal/per_thread_sem.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -ABSL_CONST_INIT static absl::base_internal::SpinLock map_lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); -ABSL_CONST_INIT static int num_identities_reused ABSL_GUARDED_BY(map_lock); - -static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1); - -static void TestThreadIdentityCurrent(const void* assert_no_identity) { - ThreadIdentity* identity; - - // We have to test this conditionally, because if the test framework relies - // on Abseil, then some previous action may have already allocated an - // identity. - if (assert_no_identity == kCheckNoIdentity) { - identity = CurrentThreadIdentityIfPresent(); - EXPECT_TRUE(identity == nullptr); - } - - identity = synchronization_internal::GetOrCreateCurrentThreadIdentity(); - EXPECT_TRUE(identity != nullptr); - ThreadIdentity* identity_no_init; - identity_no_init = CurrentThreadIdentityIfPresent(); - EXPECT_TRUE(identity == identity_no_init); - - // Check that per_thread_synch is correctly aligned. - EXPECT_EQ(0, reinterpret_cast<intptr_t>(&identity->per_thread_synch) % - PerThreadSynch::kAlignment); - EXPECT_EQ(identity, identity->per_thread_synch.thread_identity()); - - absl::base_internal::SpinLockHolder l(&map_lock); - num_identities_reused++; -} - -TEST(ThreadIdentityTest, BasicIdentityWorks) { - // This tests for the main() thread. - TestThreadIdentityCurrent(nullptr); -} - -TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) { - // Now try the same basic test with multiple threads being created and - // destroyed. This makes sure that: - // - New threads are created without a ThreadIdentity. - // - We re-allocate ThreadIdentity objects from the free-list. - // - If a thread implementation chooses to recycle threads, that - // correct re-initialization occurs. - static const int kNumLoops = 3; - static const int kNumThreads = 32; - for (int iter = 0; iter < kNumLoops; iter++) { - std::vector<std::thread> threads; - for (int i = 0; i < kNumThreads; ++i) { - threads.push_back( - std::thread(TestThreadIdentityCurrent, kCheckNoIdentity)); - } - for (auto& thread : threads) { - thread.join(); - } - } - - // 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); -} - -TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) { - // This test repeatly creates and joins a series of threads, each of - // which acquires and releases shared Mutex locks. This verifies - // Mutex operations work correctly under a reused - // ThreadIdentity. Note that the most likely failure mode of this - // test is a crash or deadlock. - static const int kNumLoops = 10; - static const int kNumThreads = 12; - static const int kNumMutexes = 3; - static const int kNumLockLoops = 5; - - Mutex mutexes[kNumMutexes]; - for (int iter = 0; iter < kNumLoops; ++iter) { - std::vector<std::thread> threads; - for (int thread = 0; thread < kNumThreads; ++thread) { - threads.push_back(std::thread([&]() { - for (int l = 0; l < kNumLockLoops; ++l) { - for (int m = 0; m < kNumMutexes; ++m) { - MutexLock lock(&mutexes[m]); - } - } - })); - } - for (auto& thread : threads) { - thread.join(); - } - } -} - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/throw_delegate.cc b/third_party/abseil_cpp/absl/base/internal/throw_delegate.cc deleted file mode 100644 index c260ff1eed63..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/throw_delegate.cc +++ /dev/null @@ -1,212 +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/base/internal/throw_delegate.h" - -#include <cstdlib> -#include <functional> -#include <new> -#include <stdexcept> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// NOTE: The various STL exception throwing functions are placed within the -// #ifdef blocks so the symbols aren't exposed on platforms that don't support -// them, such as the Android NDK. For example, ANGLE fails to link when building -// within AOSP without them, since the STL functions don't exist. -namespace { -#ifdef ABSL_HAVE_EXCEPTIONS -template <typename T> -[[noreturn]] void Throw(const T& error) { - throw error; -} -#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 ThrowStdBadAlloc() { -#ifdef ABSL_HAVE_EXCEPTIONS - Throw(std::bad_alloc()); -#else - std::abort(); -#endif -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/internal/throw_delegate.h b/third_party/abseil_cpp/absl/base/internal/throw_delegate.h deleted file mode 100644 index 075f5272543a..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/throw_delegate.h +++ /dev/null @@ -1,75 +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. -// - -#ifndef ABSL_BASE_INTERNAL_THROW_DELEGATE_H_ -#define ABSL_BASE_INTERNAL_THROW_DELEGATE_H_ - -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Helper functions that allow throwing exceptions consistently from anywhere. -// The main use case is for header-based libraries (eg templates), as they will -// be built by many different targets with their own compiler options. -// In particular, this will allow a safe way to throw exceptions even if the -// caller is compiled with -fno-exceptions. This is intended for implementing -// things like map<>::at(), which the standard documents as throwing an -// exception on error. -// -// Using other techniques like #if tricks could lead to ODR violations. -// -// You shouldn't use it unless you're writing code that you know will be built -// both with and without exceptions and you need to conform to an interface -// that uses exceptions. - -[[noreturn]] void ThrowStdLogicError(const std::string& what_arg); -[[noreturn]] void ThrowStdLogicError(const char* what_arg); -[[noreturn]] void ThrowStdInvalidArgument(const std::string& what_arg); -[[noreturn]] void ThrowStdInvalidArgument(const char* what_arg); -[[noreturn]] void ThrowStdDomainError(const std::string& what_arg); -[[noreturn]] void ThrowStdDomainError(const char* what_arg); -[[noreturn]] void ThrowStdLengthError(const std::string& what_arg); -[[noreturn]] void ThrowStdLengthError(const char* what_arg); -[[noreturn]] void ThrowStdOutOfRange(const std::string& what_arg); -[[noreturn]] void ThrowStdOutOfRange(const char* what_arg); -[[noreturn]] void ThrowStdRuntimeError(const std::string& what_arg); -[[noreturn]] void ThrowStdRuntimeError(const char* what_arg); -[[noreturn]] void ThrowStdRangeError(const std::string& what_arg); -[[noreturn]] void ThrowStdRangeError(const char* what_arg); -[[noreturn]] void ThrowStdOverflowError(const std::string& what_arg); -[[noreturn]] void ThrowStdOverflowError(const char* what_arg); -[[noreturn]] void ThrowStdUnderflowError(const std::string& what_arg); -[[noreturn]] void ThrowStdUnderflowError(const char* what_arg); - -[[noreturn]] void ThrowStdBadFunctionCall(); -[[noreturn]] void ThrowStdBadAlloc(); - -// ThrowStdBadArrayNewLength() cannot be consistently supported because -// std::bad_array_new_length is missing in libstdc++ until 4.9.0. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.3/libstdc++/api/a01379_source.html -// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/libstdc++/api/a01327_source.html -// libcxx (as of 3.2) and msvc (as of 2015) both have it. -// [[noreturn]] void ThrowStdBadArrayNewLength(); - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_ 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 deleted file mode 100644 index 39207d8a5c42..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/tsan_mutex_interface.h +++ /dev/null @@ -1,68 +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 is intended solely for spinlock.h. -// It provides ThreadSanitizer annotations for custom mutexes. -// See <sanitizer/tsan_interface.h> for meaning of these annotations. - -#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. -// -// Checks whether LLVM Thread Sanitizer interfaces are available. -// First made available in LLVM 5.0 (Sep 2017). -#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE -#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set." -#endif - -#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include) -#if __has_include(<sanitizer/tsan_interface.h>) -#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1 -#endif -#endif - -#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE -#include <sanitizer/tsan_interface.h> - -#define ABSL_TSAN_MUTEX_CREATE __tsan_mutex_create -#define ABSL_TSAN_MUTEX_DESTROY __tsan_mutex_destroy -#define ABSL_TSAN_MUTEX_PRE_LOCK __tsan_mutex_pre_lock -#define ABSL_TSAN_MUTEX_POST_LOCK __tsan_mutex_post_lock -#define ABSL_TSAN_MUTEX_PRE_UNLOCK __tsan_mutex_pre_unlock -#define ABSL_TSAN_MUTEX_POST_UNLOCK __tsan_mutex_post_unlock -#define ABSL_TSAN_MUTEX_PRE_SIGNAL __tsan_mutex_pre_signal -#define ABSL_TSAN_MUTEX_POST_SIGNAL __tsan_mutex_post_signal -#define ABSL_TSAN_MUTEX_PRE_DIVERT __tsan_mutex_pre_divert -#define ABSL_TSAN_MUTEX_POST_DIVERT __tsan_mutex_post_divert - -#else - -#define ABSL_TSAN_MUTEX_CREATE(...) -#define ABSL_TSAN_MUTEX_DESTROY(...) -#define ABSL_TSAN_MUTEX_PRE_LOCK(...) -#define ABSL_TSAN_MUTEX_POST_LOCK(...) -#define ABSL_TSAN_MUTEX_PRE_UNLOCK(...) -#define ABSL_TSAN_MUTEX_POST_UNLOCK(...) -#define ABSL_TSAN_MUTEX_PRE_SIGNAL(...) -#define ABSL_TSAN_MUTEX_POST_SIGNAL(...) -#define ABSL_TSAN_MUTEX_PRE_DIVERT(...) -#define ABSL_TSAN_MUTEX_POST_DIVERT(...) - -#endif - -#endif // ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_ diff --git a/third_party/abseil_cpp/absl/base/internal/unaligned_access.h b/third_party/abseil_cpp/absl/base/internal/unaligned_access.h deleted file mode 100644 index 093dd9b499f0..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/unaligned_access.h +++ /dev/null @@ -1,82 +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. -// - -#ifndef ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_ -#define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_ - -#include <string.h> - -#include <cstdint> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" - -// unaligned APIs - -// Portable handling of unaligned loads, stores, and copies. - -// The unaligned API is C++ only. The declarations use C++ features -// (namespaces, inline) which are absent or incompatible in C. -#if defined(__cplusplus) -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -inline uint16_t UnalignedLoad16(const void *p) { - uint16_t t; - memcpy(&t, p, sizeof t); - return t; -} - -inline uint32_t UnalignedLoad32(const void *p) { - uint32_t t; - memcpy(&t, p, sizeof t); - return t; -} - -inline uint64_t UnalignedLoad64(const void *p) { - uint64_t t; - memcpy(&t, p, sizeof t); - return t; -} - -inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); } - -inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } - -inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } - -} // namespace base_internal -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)) - -#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 ff8c2b3fb427..000000000000 --- 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 deleted file mode 100644 index 1545288cf2de..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/unscaledcycleclock.cc +++ /dev/null @@ -1,138 +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/base/internal/unscaledcycleclock.h" - -#if ABSL_USE_UNSCALED_CYCLECLOCK - -#if defined(_WIN32) -#include <intrin.h> -#endif - -#if defined(__powerpc__) || defined(__ppc__) -#ifdef __GLIBC__ -#include <sys/platform/ppc.h> -#elif defined(__FreeBSD__) -#include <sys/sysctl.h> -#include <sys/types.h> -#endif -#endif - -#include "absl/base/internal/sysinfo.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -#if defined(__i386__) - -int64_t UnscaledCycleClock::Now() { - int64_t ret; - __asm__ volatile("rdtsc" : "=A"(ret)); - return ret; -} - -double UnscaledCycleClock::Frequency() { - return base_internal::NominalCPUFrequency(); -} - -#elif defined(__x86_64__) - -int64_t UnscaledCycleClock::Now() { - uint64_t low, high; - __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); - return (high << 32) | low; -} - -double UnscaledCycleClock::Frequency() { - return base_internal::NominalCPUFrequency(); -} - -#elif defined(__powerpc__) || defined(__ppc__) - -int64_t UnscaledCycleClock::Now() { -#ifdef __GLIBC__ - return __ppc_get_timebase(); -#else -#ifdef __powerpc64__ - int64_t tbr; - asm volatile("mfspr %0, 268" : "=r"(tbr)); - return tbr; -#else - int32_t tbu, tbl, tmp; - asm volatile( - "0:\n" - "mftbu %[hi32]\n" - "mftb %[lo32]\n" - "mftbu %[tmp]\n" - "cmpw %[tmp],%[hi32]\n" - "bne 0b\n" - : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp)); - return (static_cast<int64_t>(tbu) << 32) | tbl; -#endif -#endif -} - -double UnscaledCycleClock::Frequency() { -#ifdef __GLIBC__ - return __ppc_get_timebase_freq(); -#elif defined(__FreeBSD__) - static once_flag init_timebase_frequency_once; - static double timebase_frequency = 0.0; - base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() { - size_t length = sizeof(timebase_frequency); - sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency, - &length, nullptr, 0); - }); - return timebase_frequency; -#else -#error Must implement UnscaledCycleClock::Frequency() -#endif -} - -#elif defined(__aarch64__) - -// System timer of ARMv8 runs at a different frequency than the CPU's. -// The frequency is fixed, typically in the range 1-50MHz. It can be -// read at CNTFRQ special register. We assume the OS has set up -// the virtual timer properly. -int64_t UnscaledCycleClock::Now() { - int64_t virtual_timer_value; - asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); - return virtual_timer_value; -} - -double UnscaledCycleClock::Frequency() { - uint64_t aarch64_timer_frequency; - asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency)); - return aarch64_timer_frequency; -} - -#elif defined(_M_IX86) || defined(_M_X64) - -#pragma intrinsic(__rdtsc) - -int64_t UnscaledCycleClock::Now() { return __rdtsc(); } - -double UnscaledCycleClock::Frequency() { - return base_internal::NominalCPUFrequency(); -} - -#endif - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USE_UNSCALED_CYCLECLOCK diff --git a/third_party/abseil_cpp/absl/base/internal/unscaledcycleclock.h b/third_party/abseil_cpp/absl/base/internal/unscaledcycleclock.h deleted file mode 100644 index 82f2c87a95a9..000000000000 --- a/third_party/abseil_cpp/absl/base/internal/unscaledcycleclock.h +++ /dev/null @@ -1,124 +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. -// -// 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. -// -// Notes: -// The cycle counter frequency is not necessarily the core clock frequency. -// That is, CycleCounter cycles are not necessarily "CPU cycles". -// -// An arbitrary offset may have been added to the counter at power on. -// -// On some platforms, the rate and offset of the counter may differ -// slightly when read from different CPUs of a multiprocessor. Usually, -// we try to ensure that the operating system adjusts values periodically -// so that values agree approximately. If you need stronger guarantees, -// consider using alternate interfaces. -// -// The CPU is not required to maintain the ordering of a cycle counter read -// with respect to surrounding instructions. - -#ifndef ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_ -#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_ - -#include <cstdint> - -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -#include "absl/base/port.h" - -// The following platforms have an implementation of a hardware counter. -#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \ - defined(__powerpc__) || defined(__ppc__) || \ - defined(_M_IX86) || defined(_M_X64) -#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1 -#else -#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0 -#endif - -// The following platforms often disable access to the hardware -// counter (through a sandbox) even if the underlying hardware has a -// usable counter. The CycleTimer interface also requires a *scaled* -// CycleClock that runs at atleast 1 MHz. We've found some Android -// ARM64 devices where this is not the case, so we disable it by -// default on Android ARM64. -#if defined(__native_client__) || \ - (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ - (defined(__ANDROID__) && defined(__aarch64__)) -#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0 -#else -#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1 -#endif - -// UnscaledCycleClock is an optional internal feature. -// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence. -// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1 -#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK) -#define ABSL_USE_UNSCALED_CYCLECLOCK \ - (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \ - ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT) -#endif - -#if ABSL_USE_UNSCALED_CYCLECLOCK - -// This macro can be used to test if UnscaledCycleClock::Frequency() -// is NominalCPUFrequency() on a particular platform. -#if (defined(__i386__) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(_M_X64)) -#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -class UnscaledCycleClockWrapperForGetCurrentTime; -} // namespace time_internal - -namespace base_internal { -class CycleClock; -class UnscaledCycleClockWrapperForInitializeFrequency; - -class UnscaledCycleClock { - private: - UnscaledCycleClock() = delete; - - // Return the value of a cycle counter that counts at a rate that is - // approximately constant. - static int64_t Now(); - - // Return the how much UnscaledCycleClock::Now() increases per second. - // This is not necessarily the core CPU clock frequency. - // It may be the nominal value report by the kernel, rather than a measured - // value. - static double Frequency(); - - // Allowed users - friend class base_internal::CycleClock; - friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime; - friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency; -}; - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USE_UNSCALED_CYCLECLOCK - -#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_ diff --git a/third_party/abseil_cpp/absl/base/invoke_test.cc b/third_party/abseil_cpp/absl/base/invoke_test.cc deleted file mode 100644 index bcdef36c3bfa..000000000000 --- a/third_party/abseil_cpp/absl/base/invoke_test.cc +++ /dev/null @@ -1,229 +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/base/internal/invoke.h" - -#include <functional> -#include <memory> -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -namespace { - -int Function(int a, int b) { return a - b; } - -int Sink(std::unique_ptr<int> p) { - return *p; -} - -std::unique_ptr<int> Factory(int n) { - return make_unique<int>(n); -} - -void NoOp() {} - -struct ConstFunctor { - int operator()(int a, int b) const { return a - b; } -}; - -struct MutableFunctor { - int operator()(int a, int b) { return a - b; } -}; - -struct EphemeralFunctor { - int operator()(int a, int b) && { return a - b; } -}; - -struct OverloadedFunctor { - template <typename... Args> - std::string operator()(const Args&... args) & { - return StrCat("&", args...); - } - template <typename... Args> - std::string operator()(const Args&... args) const& { - return StrCat("const&", args...); - } - template <typename... Args> - std::string operator()(const Args&... args) && { - return StrCat("&&", args...); - } -}; - -struct Class { - int Method(int a, int b) { return a - b; } - int ConstMethod(int a, int b) const { return a - b; } - int RefMethod(int a, int b) & { return a - b; } - int RefRefMethod(int a, int b) && { return a - b; } - int NoExceptMethod(int a, int b) noexcept { return a - b; } - int VolatileMethod(int a, int b) volatile { return a - b; } - - int member; -}; - -struct FlipFlop { - int ConstMethod() const { return member; } - FlipFlop operator*() const { return {-member}; } - - int member; -}; - -// 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); -} - -template <typename F> -decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg( - const F& f) { - return base_internal::invoke(f, 42); -} - -TEST(InvokeTest, Function) { - EXPECT_EQ(1, base_internal::invoke(Function, 3, 2)); - EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2)); -} - -TEST(InvokeTest, NonCopyableArgument) { - EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42))); -} - -TEST(InvokeTest, NonCopyableResult) { - EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42)); -} - -TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); } - -TEST(InvokeTest, ConstFunctor) { - EXPECT_EQ(1, base_internal::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)); -} - -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)); -} - -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("&&", base_internal::invoke(std::move(f))); - - OverloadedFunctor f2; - EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 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)); -} - -TEST(InvokeTest, MemberFunction) { - std::unique_ptr<Class> p(new Class); - 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)); -} - -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())); - - base_internal::invoke(&Class::member, p) = 42; - base_internal::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())); -} - -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)); -} - -TEST(InvokeTest, SfinaeFriendly) { - CallMaybeWithArg(NoOp); - EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42)); -} - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/log_severity.cc b/third_party/abseil_cpp/absl/base/log_severity.cc deleted file mode 100644 index 72312afd367e..000000000000 --- a/third_party/abseil_cpp/absl/base/log_severity.cc +++ /dev/null @@ -1,27 +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/base/log_severity.h" - -#include <ostream> - -namespace absl { -ABSL_NAMESPACE_BEGIN - -std::ostream& operator<<(std::ostream& os, absl::LogSeverity s) { - if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s); - return os << "absl::LogSeverity(" << static_cast<int>(s) << ")"; -} -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/log_severity.h b/third_party/abseil_cpp/absl/base/log_severity.h deleted file mode 100644 index 045f17f81db9..000000000000 --- a/third_party/abseil_cpp/absl/base/log_severity.h +++ /dev/null @@ -1,121 +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. - -#ifndef ABSL_BASE_LOG_SEVERITY_H_ -#define ABSL_BASE_LOG_SEVERITY_H_ - -#include <array> -#include <ostream> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::LogSeverity -// -// Four severity levels are defined. Logging APIs should terminate the program -// when a message is logged at severity `kFatal`; the other levels have no -// special semantics. -// -// Values other than the four defined levels (e.g. produced by `static_cast`) -// are valid, but their semantics when passed to a function, macro, or flag -// depend on the function, macro, or flag. The usual behavior is to normalize -// such values to a defined severity level, however in some cases values other -// than the defined levels are useful for comparison. -// -// Exmaple: -// -// // Effectively disables all logging: -// SetMinLogLevel(static_cast<absl::LogSeverity>(100)); -// -// Abseil flags may be defined with type `LogSeverity`. Dependency layering -// constraints require that the `AbslParseFlag()` overload be declared and -// defined in the flags library itself rather than here. The `AbslUnparseFlag()` -// overload is defined there as well for consistency. -// -// absl::LogSeverity Flag String Representation -// -// An `absl::LogSeverity` has a string representation used for parsing -// command-line flags based on the enumerator name (e.g. `kFatal`) or -// its unprefixed name (without the `k`) in any case-insensitive form. (E.g. -// "FATAL", "fatal" or "Fatal" are all valid.) Unparsing such flags produces an -// unprefixed string representation in all caps (e.g. "FATAL") or an integer. -// -// Additionally, the parser accepts arbitrary integers (as if the type were -// `int`). -// -// Examples: -// -// --my_log_level=kInfo -// --my_log_level=INFO -// --my_log_level=info -// --my_log_level=0 -// -// Unparsing a flag produces the same result as `absl::LogSeverityName()` for -// the standard levels and a base-ten integer otherwise. -enum class LogSeverity : int { - kInfo = 0, - kWarning = 1, - kError = 2, - kFatal = 3, -}; - -// LogSeverities() -// -// Returns an iterable of all standard `absl::LogSeverity` values, ordered from -// least to most severe. -constexpr std::array<absl::LogSeverity, 4> LogSeverities() { - return {{absl::LogSeverity::kInfo, absl::LogSeverity::kWarning, - absl::LogSeverity::kError, absl::LogSeverity::kFatal}}; -} - -// LogSeverityName() -// -// Returns the all-caps string representation (e.g. "INFO") of the specified -// severity level if it is one of the standard levels and "UNKNOWN" otherwise. -constexpr const char* LogSeverityName(absl::LogSeverity s) { - return s == absl::LogSeverity::kInfo - ? "INFO" - : s == absl::LogSeverity::kWarning - ? "WARNING" - : s == absl::LogSeverity::kError - ? "ERROR" - : s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN"; -} - -// NormalizeLogSeverity() -// -// Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal` -// normalize to `kError` (**NOT** `kFatal`). -constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) { - return s < absl::LogSeverity::kInfo - ? absl::LogSeverity::kInfo - : s > absl::LogSeverity::kFatal ? absl::LogSeverity::kError : s; -} -constexpr absl::LogSeverity NormalizeLogSeverity(int s) { - return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s)); -} - -// operator<< -// -// The exact representation of a streamed `absl::LogSeverity` is deliberately -// unspecified; do not rely on it. -std::ostream& operator<<(std::ostream& os, absl::LogSeverity s); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_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 deleted file mode 100644 index 2c6872b00a64..000000000000 --- a/third_party/abseil_cpp/absl/base/log_severity_test.cc +++ /dev/null @@ -1,204 +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/base/log_severity.h" - -#include <cstdint> -#include <ios> -#include <limits> -#include <ostream> -#include <sstream> -#include <string> -#include <tuple> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/flags/internal/flag.h" -#include "absl/flags/marshalling.h" -#include "absl/strings/str_cat.h" - -namespace { -using ::testing::Eq; -using ::testing::IsFalse; -using ::testing::IsTrue; -using ::testing::TestWithParam; -using ::testing::Values; - -std::string StreamHelper(absl::LogSeverity value) { - std::ostringstream stream; - stream << value; - return stream.str(); -} - -TEST(StreamTest, Works) { - EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(-100)), - Eq("absl::LogSeverity(-100)")); - EXPECT_THAT(StreamHelper(absl::LogSeverity::kInfo), Eq("INFO")); - EXPECT_THAT(StreamHelper(absl::LogSeverity::kWarning), Eq("WARNING")); - EXPECT_THAT(StreamHelper(absl::LogSeverity::kError), Eq("ERROR")); - EXPECT_THAT(StreamHelper(absl::LogSeverity::kFatal), Eq("FATAL")); - EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(4)), - Eq("absl::LogSeverity(4)")); -} - -static_assert( - absl::flags_internal::FlagUseOneWordStorage<absl::LogSeverity>::value, - "Flags of type absl::LogSeverity ought to be lock-free."); - -using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>; -INSTANTIATE_TEST_SUITE_P( - Instantiation, ParseFlagFromOutOfRangeIntegerTest, - Values(static_cast<int64_t>(std::numeric_limits<int>::min()) - 1, - static_cast<int64_t>(std::numeric_limits<int>::max()) + 1)); -TEST_P(ParseFlagFromOutOfRangeIntegerTest, ReturnsError) { - const std::string to_parse = absl::StrCat(GetParam()); - absl::LogSeverity value; - std::string error; - EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value; -} - -using ParseFlagFromAlmostOutOfRangeIntegerTest = TestWithParam<int>; -INSTANTIATE_TEST_SUITE_P(Instantiation, - ParseFlagFromAlmostOutOfRangeIntegerTest, - Values(std::numeric_limits<int>::min(), - std::numeric_limits<int>::max())); -TEST_P(ParseFlagFromAlmostOutOfRangeIntegerTest, YieldsExpectedValue) { - const auto expected = static_cast<absl::LogSeverity>(GetParam()); - const std::string to_parse = absl::StrCat(GetParam()); - absl::LogSeverity value; - std::string error; - ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; - EXPECT_THAT(value, Eq(expected)); -} - -using ParseFlagFromIntegerMatchingEnumeratorTest = - TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>; -INSTANTIATE_TEST_SUITE_P( - Instantiation, ParseFlagFromIntegerMatchingEnumeratorTest, - Values(std::make_tuple("0", absl::LogSeverity::kInfo), - std::make_tuple(" 0", absl::LogSeverity::kInfo), - std::make_tuple("-0", absl::LogSeverity::kInfo), - std::make_tuple("+0", absl::LogSeverity::kInfo), - std::make_tuple("00", absl::LogSeverity::kInfo), - std::make_tuple("0 ", absl::LogSeverity::kInfo), - std::make_tuple("0x0", absl::LogSeverity::kInfo), - std::make_tuple("1", absl::LogSeverity::kWarning), - std::make_tuple("+1", absl::LogSeverity::kWarning), - std::make_tuple("2", absl::LogSeverity::kError), - std::make_tuple("3", absl::LogSeverity::kFatal))); -TEST_P(ParseFlagFromIntegerMatchingEnumeratorTest, YieldsExpectedValue) { - const absl::string_view to_parse = std::get<0>(GetParam()); - const absl::LogSeverity expected = std::get<1>(GetParam()); - absl::LogSeverity value; - std::string error; - ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; - EXPECT_THAT(value, Eq(expected)); -} - -using ParseFlagFromOtherIntegerTest = - TestWithParam<std::tuple<absl::string_view, int>>; -INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromOtherIntegerTest, - Values(std::make_tuple("-1", -1), - std::make_tuple("4", 4), - std::make_tuple("010", 10), - std::make_tuple("0x10", 16))); -TEST_P(ParseFlagFromOtherIntegerTest, YieldsExpectedValue) { - const absl::string_view to_parse = std::get<0>(GetParam()); - const auto expected = static_cast<absl::LogSeverity>(std::get<1>(GetParam())); - absl::LogSeverity value; - std::string error; - ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; - EXPECT_THAT(value, Eq(expected)); -} - -using ParseFlagFromEnumeratorTest = - TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>; -INSTANTIATE_TEST_SUITE_P( - Instantiation, ParseFlagFromEnumeratorTest, - Values(std::make_tuple("INFO", absl::LogSeverity::kInfo), - std::make_tuple("info", absl::LogSeverity::kInfo), - std::make_tuple("kInfo", absl::LogSeverity::kInfo), - std::make_tuple("iNfO", absl::LogSeverity::kInfo), - std::make_tuple("kInFo", absl::LogSeverity::kInfo), - std::make_tuple("WARNING", absl::LogSeverity::kWarning), - std::make_tuple("warning", absl::LogSeverity::kWarning), - std::make_tuple("kWarning", absl::LogSeverity::kWarning), - std::make_tuple("WaRnInG", absl::LogSeverity::kWarning), - std::make_tuple("KwArNiNg", absl::LogSeverity::kWarning), - std::make_tuple("ERROR", absl::LogSeverity::kError), - std::make_tuple("error", absl::LogSeverity::kError), - std::make_tuple("kError", absl::LogSeverity::kError), - std::make_tuple("eRrOr", absl::LogSeverity::kError), - std::make_tuple("kErRoR", absl::LogSeverity::kError), - std::make_tuple("FATAL", absl::LogSeverity::kFatal), - std::make_tuple("fatal", absl::LogSeverity::kFatal), - std::make_tuple("kFatal", absl::LogSeverity::kFatal), - std::make_tuple("FaTaL", absl::LogSeverity::kFatal), - std::make_tuple("KfAtAl", absl::LogSeverity::kFatal))); -TEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) { - const absl::string_view to_parse = std::get<0>(GetParam()); - const absl::LogSeverity expected = std::get<1>(GetParam()); - absl::LogSeverity value; - std::string error; - ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; - EXPECT_THAT(value, Eq(expected)); -} - -using ParseFlagFromGarbageTest = TestWithParam<absl::string_view>; -INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromGarbageTest, - Values("", "\0", " ", "garbage", "kkinfo", "I")); -TEST_P(ParseFlagFromGarbageTest, ReturnsError) { - const absl::string_view to_parse = GetParam(); - absl::LogSeverity value; - std::string error; - EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value; -} - -using UnparseFlagToEnumeratorTest = - TestWithParam<std::tuple<absl::LogSeverity, absl::string_view>>; -INSTANTIATE_TEST_SUITE_P( - Instantiation, UnparseFlagToEnumeratorTest, - Values(std::make_tuple(absl::LogSeverity::kInfo, "INFO"), - std::make_tuple(absl::LogSeverity::kWarning, "WARNING"), - std::make_tuple(absl::LogSeverity::kError, "ERROR"), - std::make_tuple(absl::LogSeverity::kFatal, "FATAL"))); -TEST_P(UnparseFlagToEnumeratorTest, ReturnsExpectedValueAndRoundTrips) { - const absl::LogSeverity to_unparse = std::get<0>(GetParam()); - const absl::string_view expected = std::get<1>(GetParam()); - const std::string stringified_value = absl::UnparseFlag(to_unparse); - EXPECT_THAT(stringified_value, Eq(expected)); - absl::LogSeverity reparsed_value; - std::string error; - EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error), - IsTrue()); - EXPECT_THAT(reparsed_value, Eq(to_unparse)); -} - -using UnparseFlagToOtherIntegerTest = TestWithParam<int>; -INSTANTIATE_TEST_SUITE_P(Instantiation, UnparseFlagToOtherIntegerTest, - Values(std::numeric_limits<int>::min(), -1, 4, - std::numeric_limits<int>::max())); -TEST_P(UnparseFlagToOtherIntegerTest, ReturnsExpectedValueAndRoundTrips) { - const absl::LogSeverity to_unparse = - static_cast<absl::LogSeverity>(GetParam()); - const std::string expected = absl::StrCat(GetParam()); - const std::string stringified_value = absl::UnparseFlag(to_unparse); - EXPECT_THAT(stringified_value, Eq(expected)); - absl::LogSeverity reparsed_value; - std::string error; - EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error), - IsTrue()); - EXPECT_THAT(reparsed_value, Eq(to_unparse)); -} -} // namespace diff --git a/third_party/abseil_cpp/absl/base/macros.h b/third_party/abseil_cpp/absl/base/macros.h deleted file mode 100644 index 3e085a916bbe..000000000000 --- a/third_party/abseil_cpp/absl/base/macros.h +++ /dev/null @@ -1,158 +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. -// -// ----------------------------------------------------------------------------- -// File: macros.h -// ----------------------------------------------------------------------------- -// -// This header file defines the set of language macros used within Abseil code. -// For the set of macros used to determine supported compilers and platforms, -// see absl/base/config.h instead. -// -// This code is compiled directly on many platforms, including client -// platforms like Windows, Mac, and embedded systems. Before making -// any changes here, make sure that you're not breaking any platforms. - -#ifndef ABSL_BASE_MACROS_H_ -#define ABSL_BASE_MACROS_H_ - -#include <cassert> -#include <cstddef> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" - -// ABSL_ARRAYSIZE() -// -// Returns the number of elements in an array as a compile-time constant, which -// can be used in defining new arrays. If you use this macro on a pointer by -// mistake, you will get a compile-time error. -#define ABSL_ARRAYSIZE(array) \ - (sizeof(::absl::macros_internal::ArraySizeHelper(array))) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace macros_internal { -// Note: this internal template function declaration is used by ABSL_ARRAYSIZE. -// The function doesn't need a definition, as we only use its type. -template <typename T, size_t N> -auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; -} // namespace macros_internal -ABSL_NAMESPACE_END -} // namespace absl - -// ABSL_BAD_CALL_IF() -// -// Used on a function overload to trap bad calls: any call that matches the -// overload will cause a compile-time error. This macro uses a clang-specific -// "enable_if" attribute, as described at -// https://clang.llvm.org/docs/AttributeReference.html#enable-if -// -// Overloads which use this macro should be bracketed by -// `#ifdef ABSL_BAD_CALL_IF`. -// -// Example: -// -// int isdigit(int c); -// #ifdef ABSL_BAD_CALL_IF -// int isdigit(int c) -// ABSL_BAD_CALL_IF(c <= -1 || c > 255, -// "'c' must have the value of an unsigned char or EOF"); -// #endif // ABSL_BAD_CALL_IF -#if ABSL_HAVE_ATTRIBUTE(enable_if) -#define ABSL_BAD_CALL_IF(expr, msg) \ - __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) -#endif - -// ABSL_ASSERT() -// -// In C++11, `assert` can't be used portably within constexpr functions. -// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr -// functions. Example: -// -// constexpr double Divide(double a, double b) { -// return ABSL_ASSERT(b != 0), a / b; -// } -// -// This macro is inspired by -// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ -#if defined(NDEBUG) -#define ABSL_ASSERT(expr) \ - (false ? static_cast<void>(expr) : static_cast<void>(0)) -#else -#define ABSL_ASSERT(expr) \ - (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \ - : [] { assert(false && #expr); }()) // NOLINT -#endif - -// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()` -// aborts the program in release mode (when NDEBUG is defined). The -// implementation should abort the program as quickly as possible and ideally it -// should not be possible to ignore the abort request. -#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \ - ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_INTERNAL_HARDENING_ABORT() \ - do { \ - __builtin_trap(); \ - __builtin_unreachable(); \ - } while (false) -#else -#define ABSL_INTERNAL_HARDENING_ABORT() abort() -#endif - -// ABSL_HARDENING_ASSERT() -// -// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement -// runtime assertions that should be enabled in hardened builds even when -// `NDEBUG` is defined. -// -// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to -// `ABSL_ASSERT()`. -// -// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on -// hardened mode. -#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) -#define ABSL_HARDENING_ASSERT(expr) \ - (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \ - : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) -#else -#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr) -#endif - -#ifdef ABSL_HAVE_EXCEPTIONS -#define ABSL_INTERNAL_TRY try -#define ABSL_INTERNAL_CATCH_ANY catch (...) -#define ABSL_INTERNAL_RETHROW do { throw; } while (false) -#else // ABSL_HAVE_EXCEPTIONS -#define ABSL_INTERNAL_TRY if (true) -#define ABSL_INTERNAL_CATCH_ANY else if (false) -#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 deleted file mode 100644 index 393fc3a423ec..000000000000 --- a/third_party/abseil_cpp/absl/base/optimization.h +++ /dev/null @@ -1,241 +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. -// -// ----------------------------------------------------------------------------- -// File: optimization.h -// ----------------------------------------------------------------------------- -// -// This header file defines portable macros for performance optimization. - -#ifndef ABSL_BASE_OPTIMIZATION_H_ -#define ABSL_BASE_OPTIMIZATION_H_ - -#include "absl/base/config.h" - -// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION -// -// Instructs the compiler to avoid optimizing tail-call recursion. Use of this -// macro is useful when you wish to preserve the existing function order within -// a stack trace for logging, debugging, or profiling purposes. -// -// Example: -// -// int f() { -// int result = g(); -// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -// return result; -// } -#if defined(__pnacl__) -#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } -#elif defined(__clang__) -// Clang will not tail call given inline volatile assembly. -#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") -#elif defined(__GNUC__) -// GCC will not tail call given inline volatile assembly. -#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") -#elif defined(_MSC_VER) -#include <intrin.h> -// The __nop() intrinsic blocks the optimisation. -#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() -#else -#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } -#endif - -// ABSL_CACHELINE_SIZE -// -// Explicitly defines the size of the L1 cache for purposes of alignment. -// Setting the cacheline size allows you to specify that certain objects be -// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations. -// (See below.) -// -// NOTE: this macro should be replaced with the following C++17 features, when -// those are generally available: -// -// * `std::hardware_constructive_interference_size` -// * `std::hardware_destructive_interference_size` -// -// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html -// for more information. -#if defined(__GNUC__) -// Cache line alignment -#if defined(__i386__) || defined(__x86_64__) -#define ABSL_CACHELINE_SIZE 64 -#elif defined(__powerpc64__) -#define ABSL_CACHELINE_SIZE 128 -#elif defined(__aarch64__) -// We would need to read special register ctr_el0 to find out L1 dcache size. -// This value is a good estimate based on a real aarch64 machine. -#define ABSL_CACHELINE_SIZE 64 -#elif defined(__arm__) -// Cache line sizes for ARM: These values are not strictly correct since -// cache line sizes depend on implementations, not architectures. There -// are even implementations with cache line sizes configurable at boot -// time. -#if defined(__ARM_ARCH_5T__) -#define ABSL_CACHELINE_SIZE 32 -#elif defined(__ARM_ARCH_7A__) -#define ABSL_CACHELINE_SIZE 64 -#endif -#endif - -#ifndef ABSL_CACHELINE_SIZE -// A reasonable default guess. Note that overestimates tend to waste more -// space, while underestimates tend to waste more time. -#define ABSL_CACHELINE_SIZE 64 -#endif - -// ABSL_CACHELINE_ALIGNED -// -// Indicates that the declared object be cache aligned using -// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to -// load a set of related objects in the L1 cache for performance improvements. -// Cacheline aligning objects properly allows constructive memory sharing and -// prevents destructive (or "false") memory sharing. -// -// NOTE: this macro should be replaced with usage of `alignas()` using -// `std::hardware_constructive_interference_size` and/or -// `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. -// -// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__` -// or `__declspec` attribute. For compilers where this is not known to work, -// the macro expands to nothing. -// -// No further guarantees are made here. The result of applying the macro -// to variables and types is always implementation-defined. -// -// WARNING: It is easy to use this attribute incorrectly, even to the point -// of causing bugs that are difficult to diagnose, crash, etc. It does not -// of itself guarantee that objects are aligned to a cache line. -// -// NOTE: Some compilers are picky about the locations of annotations such as -// this attribute, so prefer to put it at the beginning of your declaration. -// For example, -// -// ABSL_CACHELINE_ALIGNED static Foo* foo = ... -// -// class ABSL_CACHELINE_ALIGNED Bar { ... -// -// Recommendations: -// -// 1) Consult compiler documentation; this comment is not kept in sync as -// toolchains evolve. -// 2) Verify your use has the intended effect. This often requires inspecting -// the generated machine code. -// 3) Prefer applying this attribute to individual variables. Avoid -// applying it to types. This tends to localize the effect. -#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE))) -#elif defined(_MSC_VER) -#define ABSL_CACHELINE_SIZE 64 -#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE)) -#else -#define ABSL_CACHELINE_SIZE 64 -#define ABSL_CACHELINE_ALIGNED -#endif - -// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE -// -// Enables the compiler to prioritize compilation using static analysis for -// likely paths within a boolean branch. -// -// Example: -// -// if (ABSL_PREDICT_TRUE(expression)) { -// return result; // Faster if more likely -// } else { -// return 0; -// } -// -// Compilers can use the information that a certain branch is not likely to be -// taken (for instance, a CHECK failure) to optimize for the common case in -// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). -// -// Recommendation: Modern CPUs dynamically predict branch execution paths, -// typically with accuracy greater than 97%. As a result, annotating every -// branch in a codebase is likely counterproductive; however, annotating -// specific branches that are both hot and consistently mispredicted is likely -// to yield performance improvements. -#if ABSL_HAVE_BUILTIN(__builtin_expect) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) -#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) -#else -#define ABSL_PREDICT_FALSE(x) (x) -#define ABSL_PREDICT_TRUE(x) (x) -#endif - -// ABSL_INTERNAL_ASSUME(cond) -// Informs the compiler that a condition is always true and that it can assume -// it to be true for optimization purposes. The call has undefined behavior if -// the condition is false. -// In !NDEBUG mode, the condition is checked with an assert(). -// NOTE: The expression must not have side effects, as it will only be evaluated -// in some compilation modes and not others. -// -// Example: -// -// int x = ...; -// ABSL_INTERNAL_ASSUME(x >= 0); -// // The compiler can optimize the division to a simple right shift using the -// // assumption specified above. -// int y = x / 16; -// -#if !defined(NDEBUG) -#define ABSL_INTERNAL_ASSUME(cond) assert(cond) -#elif ABSL_HAVE_BUILTIN(__builtin_assume) -#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond) -#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) -#define ABSL_INTERNAL_ASSUME(cond) \ - do { \ - if (!(cond)) __builtin_unreachable(); \ - } while (0) -#elif defined(_MSC_VER) -#define ABSL_INTERNAL_ASSUME(cond) __assume(cond) -#else -#define ABSL_INTERNAL_ASSUME(cond) \ - do { \ - static_cast<void>(false && (cond)); \ - } while (0) -#endif - -// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) -// This macro forces small unique name on a static file level symbols like -// static local variables or static functions. This is intended to be used in -// macro definitions to optimize the cost of generated code. Do NOT use it on -// symbols exported from translation unit since it may casue 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 e83369f32261..000000000000 --- 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 deleted file mode 100644 index 230bf1eecc4a..000000000000 --- a/third_party/abseil_cpp/absl/base/options.h +++ /dev/null @@ -1,238 +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. -// -// ----------------------------------------------------------------------------- -// File: options.h -// ----------------------------------------------------------------------------- -// -// This file contains Abseil configuration options for setting specific -// implementations instead of letting Abseil determine which implementation to -// use at compile-time. Setting these options may be useful for package or build -// managers who wish to guarantee ABI stability within binary builds (which are -// otherwise difficult to enforce). -// -// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that -// maintainers of package managers who wish to package Abseil read and -// understand this file! *** -// -// Abseil contains a number of possible configuration endpoints, based on -// parameters such as the detected platform, language version, or command-line -// flags used to invoke the underlying binary. As is the case with all -// libraries, binaries which contain Abseil code must ensure that separate -// packages use the same compiled copy of Abseil to avoid a diamond dependency -// problem, which can occur if two packages built with different Abseil -// configuration settings are linked together. Diamond dependency problems in -// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in -// linker errors), or undefined behavior (resulting in crashes). -// -// Diamond dependency problems can be avoided if all packages utilize the same -// exact version of Abseil. Building from source code with the same compilation -// parameters is the easiest way to avoid such dependency problems. However, for -// package managers who cannot control such compilation parameters, we are -// providing the file to allow you to inject ABI (Application Binary Interface) -// stability across builds. Settings options in this file will neither change -// API nor ABI, providing a stable copy of Abseil between packages. -// -// Care must be taken to keep options within these configurations isolated -// from any other dynamic settings, such as command-line flags which could alter -// these options. This file is provided specifically to help build and package -// managers provide a stable copy of Abseil within their libraries and binaries; -// other developers should not have need to alter the contents of this file. -// -// ----------------------------------------------------------------------------- -// Usage -// ----------------------------------------------------------------------------- -// -// For any particular package release, set the appropriate definitions within -// this file to whatever value makes the most sense for your package(s). Note -// that, by default, most of these options, at the moment, affect the -// implementation of types; future options may affect other implementation -// details. -// -// NOTE: the defaults within this file all assume that Abseil can select the -// proper Abseil implementation at compile-time, which will not be sufficient -// to guarantee ABI stability to package managers. - -#ifndef ABSL_BASE_OPTIONS_H_ -#define ABSL_BASE_OPTIONS_H_ - -// Include a standard library header to allow configuration based on the -// standard library in use. -#ifdef __cplusplus -#include <ciso646> -#endif - -// ----------------------------------------------------------------------------- -// Type Compatibility Options -// ----------------------------------------------------------------------------- -// -// ABSL_OPTION_USE_STD_ANY -// -// This option controls whether absl::any is implemented as an alias to -// std::any, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::any. This requires that all code -// using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::any is available. This option is -// useful when you are building your entire program, including all of its -// dependencies, from source. It should not be used otherwise -- for example, -// if you are distributing Abseil in a binary package manager -- since in -// mode 2, absl::any will name a different type, with a different mangled name -// and binary layout, depending on the compiler flags passed by the end user. -// For more info, see https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. - -#define ABSL_OPTION_USE_STD_ANY 2 - - -// ABSL_OPTION_USE_STD_OPTIONAL -// -// This option controls whether absl::optional is implemented as an alias to -// std::optional, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::optional. This requires that all -// code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::optional is available. This option -// is useful when you are building your program from source. It should not be -// used otherwise -- for example, if you are distributing Abseil in a binary -// package manager -- since in mode 2, absl::optional will name a different -// type, with a different mangled name and binary layout, depending on the -// compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. - -// User code should not inspect this macro. To check in the preprocessor if -// absl::optional is a typedef of std::optional, use the feature macro -// ABSL_USES_STD_OPTIONAL. - -#define ABSL_OPTION_USE_STD_OPTIONAL 2 - - -// ABSL_OPTION_USE_STD_STRING_VIEW -// -// This option controls whether absl::string_view is implemented as an alias to -// std::string_view, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::string_view. This requires that -// all code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::string_view is available. This -// option is useful when you are building your program from source. It should -// not be used otherwise -- for example, if you are distributing Abseil in a -// binary package manager -- since in mode 2, absl::string_view will name a -// different type, with a different mangled name and binary layout, depending on -// the compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::string_view is a typedef of std::string_view, use the feature macro -// ABSL_USES_STD_STRING_VIEW. - -#define ABSL_OPTION_USE_STD_STRING_VIEW 2 - -// ABSL_OPTION_USE_STD_VARIANT -// -// This option controls whether absl::variant is implemented as an alias to -// std::variant, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::variant. This requires that all -// code using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::variant is available. This option -// is useful when you are building your program from source. It should not be -// used otherwise -- for example, if you are distributing Abseil in a binary -// package manager -- since in mode 2, absl::variant will name a different -// type, with a different mangled name and binary layout, depending on the -// compiler flags passed by the end user. For more info, see -// https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::variant is a typedef of std::variant, use the feature macro -// ABSL_USES_STD_VARIANT. - -#define ABSL_OPTION_USE_STD_VARIANT 2 - - -// ABSL_OPTION_USE_INLINE_NAMESPACE -// ABSL_OPTION_INLINE_NAMESPACE_NAME -// -// These options controls whether all entities in the absl namespace are -// contained within an inner inline namespace. This does not affect the -// user-visible API of Abseil, but it changes the mangled names of all symbols. -// -// This can be useful as a version tag if you are distributing Abseil in -// precompiled form. This will prevent a binary library build of Abseil with -// one inline namespace being used with headers configured with a different -// inline namespace name. Binary packagers are reminded that Abseil does not -// guarantee any ABI stability in Abseil, so any update of Abseil or -// configuration change in such a binary package should be combined with a -// new, unique value for the inline namespace name. -// -// A value of 0 means not to use inline namespaces. -// -// A value of 1 means to use an inline namespace with the given name inside -// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also -// be changed to a new, unique identifier name. In particular "head" is not -// allowed. - -#define ABSL_OPTION_USE_INLINE_NAMESPACE 0 -#define ABSL_OPTION_INLINE_NAMESPACE_NAME head - -// ABSL_OPTION_HARDENED -// -// This option enables a "hardened" build in release mode (in this context, -// release mode is defined as a build where the `NDEBUG` macro is defined). -// -// A value of 0 means that "hardened" mode is not enabled. -// -// A value of 1 means that "hardened" mode is enabled. -// -// Hardened builds have additional security checks enabled when `NDEBUG` is -// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a -// no-op, as well as disabling other bespoke program consistency checks. By -// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in -// release mode. These checks guard against programming errors that may lead to -// security vulnerabilities. In release mode, when one of these programming -// errors is encountered, the program will immediately abort, possibly without -// any attempt at logging. -// -// The checks enabled by this option are not free; they do incur runtime cost. -// -// The checks enabled by this option are always active when `NDEBUG` is not -// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The -// checks enabled by this option may abort the program in a different way and -// log additional information when `NDEBUG` is not defined. - -#define ABSL_OPTION_HARDENED 0 - -#endif // ABSL_BASE_OPTIONS_H_ diff --git a/third_party/abseil_cpp/absl/base/policy_checks.h b/third_party/abseil_cpp/absl/base/policy_checks.h deleted file mode 100644 index 06b324391685..000000000000 --- a/third_party/abseil_cpp/absl/base/policy_checks.h +++ /dev/null @@ -1,111 +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. -// -// ----------------------------------------------------------------------------- -// File: policy_checks.h -// ----------------------------------------------------------------------------- -// -// This header enforces a minimum set of policies at build time, such as the -// supported compiler and library versions. Unsupported configurations are -// reported with `#error`. This enforcement is best effort, so successfully -// compiling this header does not guarantee a supported configuration. - -#ifndef ABSL_BASE_POLICY_CHECKS_H_ -#define ABSL_BASE_POLICY_CHECKS_H_ - -// Included for the __GLIBC_PREREQ macro used below. -#include <limits.h> - -// Included for the _STLPORT_VERSION macro used below. -#if defined(__cplusplus) -#include <cstddef> -#endif - -// ----------------------------------------------------------------------------- -// Operating System Check -// ----------------------------------------------------------------------------- - -#if defined(__CYGWIN__) -#error "Cygwin is not supported." -#endif - -// ----------------------------------------------------------------------------- -// Toolchain Check -// ----------------------------------------------------------------------------- - -// We support MSVC++ 14.0 update 2 and later. -// This minimum will go up. -#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__) -#error "This package requires Visual Studio 2015 Update 2 or higher." -#endif - -// We support gcc 4.7 and later. -// This minimum will go up. -#if defined(__GNUC__) && !defined(__clang__) -#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) -#error "This package requires gcc 4.7 or higher." -#endif -#endif - -// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later. -// This corresponds to Apple Xcode version 4.5. -// This minimum will go up. -#if defined(__apple_build_version__) && __apple_build_version__ < 4211165 -#error "This package requires __apple_build_version__ of 4211165 or higher." -#endif - -// ----------------------------------------------------------------------------- -// C++ Version Check -// ----------------------------------------------------------------------------- - -// Enforce C++11 as the minimum. Note that Visual Studio has not -// advanced __cplusplus despite being good enough for our purposes, so -// so we exempt it from the check. -#if defined(__cplusplus) && !defined(_MSC_VER) -#if __cplusplus < 201103L -#error "C++ versions less than C++11 are not supported." -#endif -#endif - -// ----------------------------------------------------------------------------- -// Standard Library Check -// ----------------------------------------------------------------------------- - -#if defined(_STLPORT_VERSION) -#error "STLPort is not supported." -#endif - -// ----------------------------------------------------------------------------- -// `char` Size Check -// ----------------------------------------------------------------------------- - -// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a -// platform where this is not the case, please provide us with the details about -// your platform so we can consider relaxing this requirement. -#if CHAR_BIT != 8 -#error "Abseil assumes CHAR_BIT == 8." -#endif - -// ----------------------------------------------------------------------------- -// `int` Size Check -// ----------------------------------------------------------------------------- - -// Abseil currently assumes that an int is 4 bytes. If you would like to use -// Abseil on a platform where this is not the case, please provide us with the -// details about your platform so we can consider relaxing this requirement. -#if INT_MAX < 2147483647 -#error "Abseil assumes that int is at least 4 bytes. " -#endif - -#endif // ABSL_BASE_POLICY_CHECKS_H_ diff --git a/third_party/abseil_cpp/absl/base/port.h b/third_party/abseil_cpp/absl/base/port.h deleted file mode 100644 index 6c28068d4f40..000000000000 --- a/third_party/abseil_cpp/absl/base/port.h +++ /dev/null @@ -1,26 +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 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_ - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/optimization.h" - -#endif // ABSL_BASE_PORT_H_ diff --git a/third_party/abseil_cpp/absl/base/raw_logging_test.cc b/third_party/abseil_cpp/absl/base/raw_logging_test.cc deleted file mode 100644 index 3d30bd386115..000000000000 --- a/third_party/abseil_cpp/absl/base/raw_logging_test.cc +++ /dev/null @@ -1,79 +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 test serves primarily as a compilation test for base/raw_logging.h. -// Raw logging testing is covered by logging_unittest.cc, which is not as -// portable as this test. - -#include "absl/base/internal/raw_logging.h" - -#include <tuple> - -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" - -namespace { - -TEST(RawLoggingCompilationTest, Log) { - ABSL_RAW_LOG(INFO, "RAW INFO: %d", 1); - ABSL_RAW_LOG(INFO, "RAW INFO: %d %d", 1, 2); - ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d", 1, 2, 3); - ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d", 1, 2, 3, 4); - ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d %d", 1, 2, 3, 4, 5); - ABSL_RAW_LOG(WARNING, "RAW WARNING: %d", 1); - ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1); -} - -TEST(RawLoggingCompilationTest, PassingCheck) { - ABSL_RAW_CHECK(true, "RAW CHECK"); -} - -// Not all platforms support output from raw log, so we don't verify any -// particular output for RAW check failures (expecting the empty string -// accomplishes this). This test is primarily a compilation test, but we -// are verifying process death when EXPECT_DEATH works for a platform. -const char kExpectedDeathOutput[] = ""; - -TEST(RawLoggingDeathTest, FailingCheck) { - EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_CHECK(1 == 0, "explanation"), - kExpectedDeathOutput); -} - -TEST(RawLoggingDeathTest, LogFatal) { - EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_LOG(FATAL, "my dog has fleas"), - kExpectedDeathOutput); -} - -TEST(InternalLog, CompilationTest) { - ABSL_INTERNAL_LOG(INFO, "Internal Log"); - std::string log_msg = "Internal Log"; - ABSL_INTERNAL_LOG(INFO, log_msg); - - ABSL_INTERNAL_LOG(INFO, log_msg + " 2"); - - float d = 1.1f; - ABSL_INTERNAL_LOG(INFO, absl::StrCat("Internal log ", 3, " + ", d)); -} - -TEST(InternalLogDeathTest, FailingCheck) { - EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_CHECK(1 == 0, "explanation"), - kExpectedDeathOutput); -} - -TEST(InternalLogDeathTest, LogFatal) { - EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_LOG(FATAL, "my dog has fleas"), - kExpectedDeathOutput); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/base/spinlock_test_common.cc b/third_party/abseil_cpp/absl/base/spinlock_test_common.cc deleted file mode 100644 index dee266e4f4c0..000000000000 --- a/third_party/abseil_cpp/absl/base/spinlock_test_common.cc +++ /dev/null @@ -1,271 +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. - -// A bunch of threads repeatedly hash an array of ints protected by a -// spinlock. If the spinlock is working properly, all elements of the -// array should be equal at the end of the test. - -#include <cstdint> -#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" -#include "absl/base/internal/sysinfo.h" -#include "absl/base/macros.h" -#include "absl/synchronization/blocking_counter.h" -#include "absl/synchronization/notification.h" - -constexpr int32_t kNumThreads = 10; -constexpr int32_t kIters = 1000; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// This is defined outside of anonymous namespace so that it can be -// a friend of SpinLock to access protected methods for testing. -struct SpinLockTest { - static uint32_t EncodeWaitCycles(int64_t wait_start_time, - int64_t wait_end_time) { - return SpinLock::EncodeWaitCycles(wait_start_time, wait_end_time); - } - static uint64_t DecodeWaitCycles(uint32_t lock_value) { - return SpinLock::DecodeWaitCycles(lock_value); - } -}; - -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); - -// Simple integer hash function based on the public domain lookup2 hash. -// http://burtleburtle.net/bob/c/lookup2.c -static uint32_t Hash32(uint32_t a, uint32_t c) { - uint32_t b = 0x9e3779b9UL; // The golden ratio; an arbitrary value. - a -= b; a -= c; a ^= (c >> 13); - b -= c; b -= a; b ^= (a << 8); - c -= a; c -= b; c ^= (b >> 13); - a -= b; a -= c; a ^= (c >> 12); - b -= c; b -= a; b ^= (a << 16); - c -= a; c -= b; c ^= (b >> 5); - a -= b; a -= c; a ^= (c >> 3); - b -= c; b -= a; b ^= (a << 10); - c -= a; c -= b; c ^= (b >> 15); - return c; -} - -static void TestFunction(int thread_salt, SpinLock* spinlock) { - for (int i = 0; i < kIters; i++) { - SpinLockHolder h(spinlock); - for (int j = 0; j < kArrayLength; j++) { - const int index = (j + thread_salt) % kArrayLength; - values[index] = Hash32(values[index], thread_salt); - std::this_thread::yield(); - } - } -} - -static void ThreadedTest(SpinLock* spinlock) { - std::vector<std::thread> threads; - for (int i = 0; i < kNumThreads; ++i) { - threads.push_back(std::thread(TestFunction, i, spinlock)); - } - for (auto& thread : threads) { - thread.join(); - } - - SpinLockHolder h(spinlock); - for (int i = 1; i < kArrayLength; i++) { - EXPECT_EQ(values[0], values[i]); - } -} - -#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(); - EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed()); - spinlock.Unlock(); -} - -TEST(SpinLock, StaticNonCooperativeDisablesScheduling) { - static_noncooperative_spinlock.Lock(); - EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed()); - static_noncooperative_spinlock.Unlock(); -} - -TEST(SpinLock, WaitCyclesEncoding) { - // These are implementation details not exported by SpinLock. - const int kProfileTimestampShift = 7; - const int kLockwordReservedShift = 3; - const uint32_t kSpinLockSleeper = 8; - - // We should be able to encode up to (1^kMaxCycleBits - 1) without clamping - // but the lower kProfileTimestampShift will be dropped. - const int kMaxCyclesShift = - 32 - kLockwordReservedShift + kProfileTimestampShift; - const uint64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1; - - // These bits should be zero after encoding. - const uint32_t kLockwordReservedMask = (1 << kLockwordReservedShift) - 1; - - // These bits are dropped when wait cycles are encoded. - const uint64_t kProfileTimestampMask = (1 << kProfileTimestampShift) - 1; - - // Test a bunch of random values - std::default_random_engine generator; - // Shift to avoid overflow below. - std::uniform_int_distribution<uint64_t> time_distribution( - 0, std::numeric_limits<uint64_t>::max() >> 4); - std::uniform_int_distribution<uint64_t> cycle_distribution(0, kMaxCycles); - - for (int i = 0; i < 100; i++) { - int64_t start_time = time_distribution(generator); - int64_t cycles = cycle_distribution(generator); - int64_t end_time = start_time + cycles; - uint32_t lock_value = SpinLockTest::EncodeWaitCycles(start_time, end_time); - EXPECT_EQ(0, lock_value & kLockwordReservedMask); - uint64_t decoded = SpinLockTest::DecodeWaitCycles(lock_value); - EXPECT_EQ(0, decoded & kProfileTimestampMask); - EXPECT_EQ(cycles & ~kProfileTimestampMask, decoded); - } - - // Test corner cases - int64_t start_time = time_distribution(generator); - EXPECT_EQ(kSpinLockSleeper, - SpinLockTest::EncodeWaitCycles(start_time, start_time)); - EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0)); - EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask)); - EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask, - SpinLockTest::DecodeWaitCycles(~kLockwordReservedMask)); - - // Check that we cannot produce kSpinLockSleeper during encoding. - int64_t sleeper_cycles = - kSpinLockSleeper << (kProfileTimestampShift - kLockwordReservedShift); - uint32_t sleeper_value = - SpinLockTest::EncodeWaitCycles(start_time, start_time + sleeper_cycles); - EXPECT_NE(sleeper_value, kSpinLockSleeper); - - // Test clamping - uint32_t max_value = - SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles); - uint64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value); - uint64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask; - EXPECT_EQ(expected_max_value_decoded, max_value_decoded); - - const int64_t step = (1 << kProfileTimestampShift); - uint32_t after_max_value = - SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles + step); - uint64_t after_max_value_decoded = - SpinLockTest::DecodeWaitCycles(after_max_value); - EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded); - - uint32_t before_max_value = SpinLockTest::EncodeWaitCycles( - start_time, start_time + kMaxCycles - step); - uint64_t before_max_value_decoded = - SpinLockTest::DecodeWaitCycles(before_max_value); - EXPECT_GT(expected_max_value_decoded, before_max_value_decoded); -} - -TEST(SpinLockWithThreads, StackSpinLock) { - SpinLock spinlock; - ThreadedTest(&spinlock); -} - -TEST(SpinLockWithThreads, StackCooperativeSpinLock) { - SpinLock spinlock(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); - ThreadedTest(&spinlock); -} - -TEST(SpinLockWithThreads, StackNonCooperativeSpinLock) { - SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY); - ThreadedTest(&spinlock); -} - -TEST(SpinLockWithThreads, StaticCooperativeSpinLock) { - ThreadedTest(&static_cooperative_spinlock); -} - -TEST(SpinLockWithThreads, StaticNonCooperativeSpinLock) { - ThreadedTest(&static_noncooperative_spinlock); -} - -TEST(SpinLockWithThreads, DoesNotDeadlock) { - struct Helper { - static void NotifyThenLock(Notification* locked, SpinLock* spinlock, - BlockingCounter* b) { - locked->WaitForNotification(); // Wait for LockThenWait() to hold "s". - b->DecrementCount(); - SpinLockHolder l(spinlock); - } - - static void LockThenWait(Notification* locked, SpinLock* spinlock, - BlockingCounter* b) { - SpinLockHolder l(spinlock); - locked->Notify(); - b->Wait(); - } - - static void DeadlockTest(SpinLock* spinlock, int num_spinners) { - Notification locked; - BlockingCounter counter(num_spinners); - std::vector<std::thread> threads; - - threads.push_back( - std::thread(Helper::LockThenWait, &locked, spinlock, &counter)); - for (int i = 0; i < num_spinners; ++i) { - threads.push_back( - std::thread(Helper::NotifyThenLock, &locked, spinlock, &counter)); - } - - for (auto& thread : threads) { - thread.join(); - } - } - }; - - SpinLock stack_cooperative_spinlock( - base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL); - SpinLock stack_noncooperative_spinlock(base_internal::SCHEDULE_KERNEL_ONLY); - Helper::DeadlockTest(&stack_cooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&stack_noncooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&static_cooperative_spinlock, - base_internal::NumCPUs() * 2); - Helper::DeadlockTest(&static_noncooperative_spinlock, - base_internal::NumCPUs() * 2); -} - -} // namespace -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/base/thread_annotations.h b/third_party/abseil_cpp/absl/base/thread_annotations.h deleted file mode 100644 index e23fff1d2013..000000000000 --- a/third_party/abseil_cpp/absl/base/thread_annotations.h +++ /dev/null @@ -1,335 +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. -// -// ----------------------------------------------------------------------------- -// File: thread_annotations.h -// ----------------------------------------------------------------------------- -// -// This header file contains macro definitions for thread safety annotations -// that allow developers to document the locking policies of multi-threaded -// code. The annotations can also help program analysis tools to identify -// potential thread safety issues. -// -// These annotations are implemented using compiler attributes. Using the macros -// defined here instead of raw attributes allow for portability and future -// compatibility. -// -// When referring to mutexes in the arguments of the attributes, you should -// use variable names or more complex expressions (e.g. my_object->mutex_) -// that evaluate to a concrete mutex object whenever possible. If the mutex -// you want to refer to is not in scope, you may use a member pointer -// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object. - -#ifndef ABSL_BASE_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 - -// ABSL_GUARDED_BY() -// -// Documents if a shared field or global variable needs to be protected by a -// mutex. ABSL_GUARDED_BY() allows the user to specify a particular mutex that -// should be held when accessing the annotated variable. -// -// Although this annotation (and ABSL_PT_GUARDED_BY, below) cannot be applied to -// local variables, a local variable and its associated mutex can often be -// combined into a small class or struct, thereby allowing the annotation. -// -// Example: -// -// class Foo { -// Mutex mu_; -// 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 - -// ABSL_PT_GUARDED_BY() -// -// Documents if the memory location pointed to by a pointer should be guarded -// by a mutex when dereferencing the pointer. -// -// Example: -// class Foo { -// Mutex mu_; -// int *p1_ ABSL_PT_GUARDED_BY(mu_); -// ... -// }; -// -// Note that a pointer variable to a shared memory location could itself be a -// shared variable. -// -// Example: -// -// // `q_`, guarded by `mu1_`, points to a shared memory location that is -// // guarded by `mu2_`: -// int *q_ 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 - -// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE() -// -// Documents the acquisition order between locks that can be held -// simultaneously by a thread. For any two locks that need to be annotated -// to establish an acquisition order, only one of them needs the annotation. -// (i.e. You don't have to annotate both locks with both ABSL_ACQUIRED_AFTER -// and ABSL_ACQUIRED_BEFORE.) -// -// As with ABSL_GUARDED_BY, this is only applicable to mutexes that are shared -// fields or global variables. -// -// Example: -// -// 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 - -#if ABSL_HAVE_ATTRIBUTE(acquired_before) -#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) -#else -#define ABSL_ACQUIRED_BEFORE(...) -#endif - -// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED() -// -// Documents a function that expects a mutex to be held prior to entry. -// The mutex is expected to be held both on entry to, and exit from, the -// function. -// -// An exclusive lock allows read-write access to the guarded data member(s), and -// only one thread can acquire a lock exclusively at any one time. A shared lock -// allows read-only access, and any number of threads can acquire a shared lock -// concurrently. -// -// Generally, non-const methods should be annotated with -// ABSL_EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with -// ABSL_SHARED_LOCKS_REQUIRED. -// -// Example: -// -// Mutex mu1, mu2; -// int a ABSL_GUARDED_BY(mu1); -// int b ABSL_GUARDED_BY(mu2); -// -// void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... } -// void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... } -#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required) -#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \ - __attribute__((exclusive_locks_required(__VA_ARGS__))) -#else -#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) -#endif - -#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_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 - -// 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 - -// 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 - -// ABSL_SCOPED_LOCKABLE -// -// Documents if a class does RAII locking (such as the `MutexLock` class). -// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is -// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no -// arguments; the analysis will assume that the destructor unlocks whatever the -// constructor locked. -#if ABSL_HAVE_ATTRIBUTE(scoped_lockable) -#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable)) -#else -#define ABSL_SCOPED_LOCKABLE -#endif - -// 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 - -// 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_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 - -// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION() -// -// Documents functions that try to acquire a lock, and return success or failure -// (or a non-boolean value that can be interpreted as a boolean). -// The first argument should be `true` for functions that return `true` on -// success, or `false` for functions that return `false` on success. The second -// argument specifies the mutex that is locked on success. If unspecified, this -// mutex is assumed to be `this`. -#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 - -#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 - -// 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 - -#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_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 - -//------------------------------------------------------------------------------ -// Tool-Supplied Annotations -//------------------------------------------------------------------------------ - -// ABSL_TS_UNCHECKED should be placed around lock expressions that are not valid -// C++ syntax, but which are present for documentation purposes. These -// annotations will be ignored by the analysis. -#define ABSL_TS_UNCHECKED(x) "" - -// ABSL_TS_FIXME is used to mark lock expressions that are not valid C++ syntax. -// It is used by automated tools to mark and disable invalid expressions. -// The annotation should either be fixed, or changed to ABSL_TS_UNCHECKED. -#define ABSL_TS_FIXME(x) "" - -// Like ABSL_NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body -// of a particular function. However, this attribute is used to mark functions -// that are incorrect and need to be fixed. It is used by automated tools to -// avoid breaking the build when the analysis is updated. -// Code owners are expected to eventually fix the routine. -#define ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME ABSL_NO_THREAD_SAFETY_ANALYSIS - -// Similar to ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a -// ABSL_GUARDED_BY annotation that needs to be fixed, because it is producing -// thread safety warning. It disables the ABSL_GUARDED_BY. -#define ABSL_GUARDED_BY_FIXME(x) - -// Disables warnings for a single read operation. This can be used to avoid -// warnings when it is known that the read is not actually involved in a race, -// but the compiler cannot confirm that. -#define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { - -// Takes a reference to a guarded data member, and returns an unguarded -// reference. -// 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; -} - -template <typename T> -inline T& ts_unchecked_read(T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS { - return v; -} - -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_BASE_THREAD_ANNOTATIONS_H_ diff --git a/third_party/abseil_cpp/absl/base/throw_delegate_test.cc b/third_party/abseil_cpp/absl/base/throw_delegate_test.cc deleted file mode 100644 index 5ba4ce55e6d5..000000000000 --- a/third_party/abseil_cpp/absl/base/throw_delegate_test.cc +++ /dev/null @@ -1,107 +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/base/internal/throw_delegate.h" - -#include <functional> -#include <new> -#include <stdexcept> - -#include "absl/base/config.h" -#include "gtest/gtest.h" - -namespace { - -using absl::base_internal::ThrowStdLogicError; -using absl::base_internal::ThrowStdInvalidArgument; -using absl::base_internal::ThrowStdDomainError; -using absl::base_internal::ThrowStdLengthError; -using absl::base_internal::ThrowStdOutOfRange; -using absl::base_internal::ThrowStdRuntimeError; -using absl::base_internal::ThrowStdRangeError; -using absl::base_internal::ThrowStdOverflowError; -using absl::base_internal::ThrowStdUnderflowError; -using absl::base_internal::ThrowStdBadFunctionCall; -using absl::base_internal::ThrowStdBadAlloc; - -constexpr const char* what_arg = "The quick brown fox jumps over the lazy dog"; - -template <typename E> -void ExpectThrowChar(void (*f)(const char*)) { -#ifdef ABSL_HAVE_EXCEPTIONS - try { - f(what_arg); - FAIL() << "Didn't throw"; - } catch (const E& e) { - EXPECT_STREQ(e.what(), what_arg); - } -#else - EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg); -#endif -} - -template <typename E> -void ExpectThrowString(void (*f)(const std::string&)) { -#ifdef ABSL_HAVE_EXCEPTIONS - try { - f(what_arg); - FAIL() << "Didn't throw"; - } catch (const E& e) { - EXPECT_STREQ(e.what(), what_arg); - } -#else - EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg); -#endif -} - -template <typename E> -void ExpectThrowNoWhat(void (*f)()) { -#ifdef ABSL_HAVE_EXCEPTIONS - try { - f(); - FAIL() << "Didn't throw"; - } catch (const E& e) { - } -#else - EXPECT_DEATH_IF_SUPPORTED(f(), ""); -#endif -} - -TEST(ThrowHelper, Test) { - // Not using EXPECT_THROW because we want to check the .what() message too. - ExpectThrowChar<std::logic_error>(ThrowStdLogicError); - ExpectThrowChar<std::invalid_argument>(ThrowStdInvalidArgument); - ExpectThrowChar<std::domain_error>(ThrowStdDomainError); - ExpectThrowChar<std::length_error>(ThrowStdLengthError); - ExpectThrowChar<std::out_of_range>(ThrowStdOutOfRange); - ExpectThrowChar<std::runtime_error>(ThrowStdRuntimeError); - ExpectThrowChar<std::range_error>(ThrowStdRangeError); - ExpectThrowChar<std::overflow_error>(ThrowStdOverflowError); - ExpectThrowChar<std::underflow_error>(ThrowStdUnderflowError); - - ExpectThrowString<std::logic_error>(ThrowStdLogicError); - ExpectThrowString<std::invalid_argument>(ThrowStdInvalidArgument); - ExpectThrowString<std::domain_error>(ThrowStdDomainError); - ExpectThrowString<std::length_error>(ThrowStdLengthError); - ExpectThrowString<std::out_of_range>(ThrowStdOutOfRange); - ExpectThrowString<std::runtime_error>(ThrowStdRuntimeError); - ExpectThrowString<std::range_error>(ThrowStdRangeError); - ExpectThrowString<std::overflow_error>(ThrowStdOverflowError); - ExpectThrowString<std::underflow_error>(ThrowStdUnderflowError); - - ExpectThrowNoWhat<std::bad_function_call>(ThrowStdBadFunctionCall); - ExpectThrowNoWhat<std::bad_alloc>(ThrowStdBadAlloc); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/container/BUILD.bazel b/third_party/abseil_cpp/absl/container/BUILD.bazel deleted file mode 100644 index 8e72ad03547c..000000000000 --- a/third_party/abseil_cpp/absl/container/BUILD.bazel +++ /dev/null @@ -1,921 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "compressed_tuple", - hdrs = ["internal/compressed_tuple.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/utility", - ], -) - -cc_test( - name = "compressed_tuple_test", - srcs = ["internal/compressed_tuple_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":compressed_tuple", - ":test_instance_tracker", - "//absl/memory", - "//absl/types:any", - "//absl/types:optional", - "//absl/utility", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "fixed_array", - hdrs = ["fixed_array.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":compressed_tuple", - "//absl/algorithm", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "//absl/base:throw_delegate", - "//absl/memory", - ], -) - -cc_test( - name = "fixed_array_test", - srcs = ["fixed_array_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":counting_allocator", - ":fixed_array", - "//absl/base:config", - "//absl/base:exception_testing", - "//absl/hash:hash_testing", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "fixed_array_exception_safety_test", - srcs = ["fixed_array_exception_safety_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fixed_array", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "fixed_array_benchmark", - srcs = ["fixed_array_benchmark.cc"], - copts = ABSL_TEST_COPTS + ["$(STACK_FRAME_UNLIMITED)"], - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":fixed_array", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "inlined_vector_internal", - hdrs = ["internal/inlined_vector.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":compressed_tuple", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/types:span", - ], -) - -cc_library( - name = "inlined_vector", - hdrs = ["inlined_vector.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":inlined_vector_internal", - "//absl/algorithm", - "//absl/base:core_headers", - "//absl/base:throw_delegate", - "//absl/memory", - ], -) - -cc_library( - name = "counting_allocator", - testonly = 1, - hdrs = ["internal/counting_allocator.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = ["//absl/base:config"], -) - -cc_test( - name = "inlined_vector_test", - srcs = ["inlined_vector_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":counting_allocator", - ":inlined_vector", - ":test_instance_tracker", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:exception_testing", - "//absl/base:raw_logging_internal", - "//absl/hash:hash_testing", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "inlined_vector_benchmark", - srcs = ["inlined_vector_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":inlined_vector", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/strings", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "inlined_vector_exception_safety_test", - srcs = ["inlined_vector_exception_safety_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":inlined_vector", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "test_instance_tracker", - testonly = 1, - srcs = ["internal/test_instance_tracker.cc"], - hdrs = ["internal/test_instance_tracker.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = ["//absl/types:compare"], -) - -cc_test( - name = "test_instance_tracker_test", - srcs = ["internal/test_instance_tracker_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":test_instance_tracker", - "@com_google_googletest//:gtest_main", - ], -) - -NOTEST_TAGS_NONMOBILE = [ - "no_test_darwin_x86_64", - "no_test_loonix", -] - -NOTEST_TAGS_MOBILE = [ - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - "no_test_ios_x86_64", -] - -NOTEST_TAGS = NOTEST_TAGS_MOBILE + NOTEST_TAGS_NONMOBILE - -cc_library( - name = "flat_hash_map", - hdrs = ["flat_hash_map.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":container_memory", - ":hash_function_defaults", - ":raw_hash_map", - "//absl/algorithm:container", - "//absl/memory", - ], -) - -cc_test( - name = "flat_hash_map_test", - srcs = ["flat_hash_map_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":flat_hash_map", - ":hash_generator_testing", - ":unordered_map_constructor_test", - ":unordered_map_lookup_test", - ":unordered_map_members_test", - ":unordered_map_modifiers_test", - "//absl/base:raw_logging_internal", - "//absl/types:any", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "flat_hash_set", - hdrs = ["flat_hash_set.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":container_memory", - ":hash_function_defaults", - ":raw_hash_set", - "//absl/algorithm:container", - "//absl/base:core_headers", - "//absl/memory", - ], -) - -cc_test( - name = "flat_hash_set_test", - srcs = ["flat_hash_set_test.cc"], - copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"], - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":flat_hash_set", - ":hash_generator_testing", - ":unordered_set_constructor_test", - ":unordered_set_lookup_test", - ":unordered_set_members_test", - ":unordered_set_modifiers_test", - "//absl/base:raw_logging_internal", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "node_hash_map", - hdrs = ["node_hash_map.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":container_memory", - ":hash_function_defaults", - ":node_hash_policy", - ":raw_hash_map", - "//absl/algorithm:container", - "//absl/memory", - ], -) - -cc_test( - name = "node_hash_map_test", - srcs = ["node_hash_map_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":hash_generator_testing", - ":node_hash_map", - ":tracked", - ":unordered_map_constructor_test", - ":unordered_map_lookup_test", - ":unordered_map_members_test", - ":unordered_map_modifiers_test", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "node_hash_set", - hdrs = ["node_hash_set.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_function_defaults", - ":node_hash_policy", - ":raw_hash_set", - "//absl/algorithm:container", - "//absl/memory", - ], -) - -cc_test( - name = "node_hash_set_test", - srcs = ["node_hash_set_test.cc"], - copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"], - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":node_hash_set", - ":unordered_set_constructor_test", - ":unordered_set_lookup_test", - ":unordered_set_members_test", - ":unordered_set_modifiers_test", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "container_memory", - hdrs = ["internal/container_memory.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_test( - name = "container_memory_test", - srcs = ["internal/container_memory_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":container_memory", - ":test_instance_tracker", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "hash_function_defaults", - hdrs = ["internal/hash_function_defaults.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/hash", - "//absl/strings", - "//absl/strings:cord", - ], -) - -cc_test( - name = "hash_function_defaults_test", - srcs = ["internal/hash_function_defaults_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS, - deps = [ - ":hash_function_defaults", - "//absl/hash", - "//absl/random", - "//absl/strings", - "//absl/strings:cord", - "//absl/strings:cord_test_helpers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "hash_generator_testing", - testonly = 1, - srcs = ["internal/hash_generator_testing.cc"], - hdrs = ["internal/hash_generator_testing.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_policy_testing", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - ], -) - -cc_library( - name = "hash_policy_testing", - testonly = 1, - hdrs = ["internal/hash_policy_testing.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/hash", - "//absl/strings", - ], -) - -cc_test( - name = "hash_policy_testing_test", - srcs = ["internal/hash_policy_testing_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_policy_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "hash_policy_traits", - hdrs = ["internal/hash_policy_traits.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/meta:type_traits"], -) - -cc_test( - name = "hash_policy_traits_test", - srcs = ["internal/hash_policy_traits_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_policy_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "hashtable_debug", - hdrs = ["internal/hashtable_debug.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hashtable_debug_hooks", - ], -) - -cc_library( - name = "hashtable_debug_hooks", - hdrs = ["internal/hashtable_debug_hooks.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - ], -) - -cc_library( - name = "hashtablez_sampler", - srcs = [ - "internal/hashtablez_sampler.cc", - "internal/hashtablez_sampler_force_weak_definition.cc", - ], - hdrs = ["internal/hashtablez_sampler.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":have_sse", - "//absl/base", - "//absl/base:core_headers", - "//absl/base:exponential_biased", - "//absl/debugging:stacktrace", - "//absl/memory", - "//absl/synchronization", - "//absl/utility", - ], -) - -cc_test( - name = "hashtablez_sampler_test", - srcs = ["internal/hashtablez_sampler_test.cc"], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hashtablez_sampler", - ":have_sse", - "//absl/base:core_headers", - "//absl/synchronization", - "//absl/synchronization:thread_pool", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "node_hash_policy", - hdrs = ["internal/node_hash_policy.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], -) - -cc_test( - name = "node_hash_policy_test", - srcs = ["internal/node_hash_policy_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_policy_traits", - ":node_hash_policy", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "raw_hash_map", - hdrs = ["internal/raw_hash_map.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":container_memory", - ":raw_hash_set", - "//absl/base:throw_delegate", - ], -) - -cc_library( - name = "have_sse", - hdrs = ["internal/have_sse.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], -) - -cc_library( - name = "common", - hdrs = ["internal/common.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/meta:type_traits", - "//absl/types:optional", - ], -) - -cc_library( - name = "raw_hash_set", - srcs = ["internal/raw_hash_set.cc"], - hdrs = ["internal/raw_hash_set.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":common", - ":compressed_tuple", - ":container_memory", - ":hash_policy_traits", - ":hashtable_debug_hooks", - ":hashtablez_sampler", - ":have_sse", - ":layout", - "//absl/base:bits", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_test( - name = "raw_hash_set_test", - srcs = ["internal/raw_hash_set_test.cc"], - copts = ABSL_TEST_COPTS, - linkstatic = 1, - tags = NOTEST_TAGS, - deps = [ - ":container_memory", - ":hash_function_defaults", - ":hash_policy_testing", - ":hashtable_debug", - ":raw_hash_set", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "raw_hash_set_allocator_test", - size = "small", - srcs = ["internal/raw_hash_set_allocator_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":raw_hash_set", - ":tracked", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "layout", - hdrs = ["internal/layout.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/types:span", - "//absl/utility", - ], -) - -cc_test( - name = "layout_test", - size = "small", - srcs = ["internal/layout_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS, - visibility = ["//visibility:private"], - deps = [ - ":layout", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/types:span", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "tracked", - testonly = 1, - hdrs = ["internal/tracked.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - ], -) - -cc_library( - name = "unordered_map_constructor_test", - testonly = 1, - hdrs = ["internal/unordered_map_constructor_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_map_lookup_test", - testonly = 1, - hdrs = ["internal/unordered_map_lookup_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_map_modifiers_test", - testonly = 1, - hdrs = ["internal/unordered_map_modifiers_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_set_constructor_test", - testonly = 1, - hdrs = ["internal/unordered_set_constructor_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_set_members_test", - testonly = 1, - hdrs = ["internal/unordered_set_members_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/meta:type_traits", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_map_members_test", - testonly = 1, - hdrs = ["internal/unordered_map_members_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/meta:type_traits", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_set_lookup_test", - testonly = 1, - hdrs = ["internal/unordered_set_lookup_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "unordered_set_modifiers_test", - testonly = 1, - hdrs = ["internal/unordered_set_modifiers_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash_generator_testing", - ":hash_policy_testing", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "unordered_set_test", - srcs = ["internal/unordered_set_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":unordered_set_constructor_test", - ":unordered_set_lookup_test", - ":unordered_set_members_test", - ":unordered_set_modifiers_test", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "unordered_map_test", - srcs = ["internal/unordered_map_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = NOTEST_TAGS_NONMOBILE, - deps = [ - ":unordered_map_constructor_test", - ":unordered_map_lookup_test", - ":unordered_map_members_test", - ":unordered_map_modifiers_test", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "btree", - srcs = [ - "internal/btree.h", - "internal/btree_container.h", - ], - hdrs = [ - "btree_map.h", - "btree_set.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:public"], - deps = [ - ":common", - ":compressed_tuple", - ":container_memory", - ":layout", - "//absl/base:core_headers", - "//absl/base:throw_delegate", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/strings:cord", - "//absl/types:compare", - "//absl/utility", - ], -) - -cc_library( - name = "btree_test_common", - testonly = 1, - hdrs = ["btree_test.h"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - ":btree", - ":flat_hash_set", - "//absl/strings", - "//absl/strings:cord", - "//absl/time", - ], -) - -cc_test( - name = "btree_test", - size = "large", - srcs = [ - "btree_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - shard_count = 10, - visibility = ["//visibility:private"], - deps = [ - ":btree", - ":btree_test_common", - ":counting_allocator", - ":test_instance_tracker", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/flags:flag", - "//absl/hash:hash_testing", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/types:compare", - "@com_google_googletest//:gtest_main", - ], -) - -cc_binary( - name = "btree_benchmark", - testonly = 1, - srcs = [ - "btree_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":btree", - ":btree_test_common", - ":flat_hash_map", - ":flat_hash_set", - ":hashtable_debug", - "//absl/base:raw_logging_internal", - "//absl/flags:flag", - "//absl/hash", - "//absl/memory", - "//absl/strings:cord", - "//absl/strings:str_format", - "//absl/time", - "@com_github_google_benchmark//:benchmark_main", - ], -) diff --git a/third_party/abseil_cpp/absl/container/CMakeLists.txt b/third_party/abseil_cpp/absl/container/CMakeLists.txt deleted file mode 100644 index eb202c459b27..000000000000 --- a/third_party/abseil_cpp/absl/container/CMakeLists.txt +++ /dev/null @@ -1,905 +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 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 - HDRS - "btree_map.h" - "btree_set.h" - "internal/btree.h" - "internal/btree_container.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::container_common - absl::compare - absl::compressed_tuple - absl::container_memory - absl::cord - absl::core_headers - absl::layout - absl::memory - absl::strings - absl::throw_delegate - absl::type_traits - absl::utility -) - -absl_cc_library( - NAME - btree_test_common - hdrs - "btree_test.h" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::btree - absl::cord - absl::flat_hash_set - absl::strings - absl::time - TESTONLY -) - -absl_cc_test( - NAME - btree_test - SRCS - "btree_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::btree - absl::btree_test_common - absl::compare - absl::core_headers - absl::counting_allocator - absl::flags - absl::hash_testing - absl::raw_logging_internal - absl::strings - absl::test_instance_tracker - absl::type_traits - gmock_main -) - -absl_cc_library( - NAME - compressed_tuple - HDRS - "internal/compressed_tuple.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::utility - PUBLIC -) - -absl_cc_test( - NAME - compressed_tuple_test - SRCS - "internal/compressed_tuple_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::compressed_tuple - absl::memory - absl::optional - absl::test_instance_tracker - absl::utility - gmock_main -) - -absl_cc_library( - NAME - fixed_array - HDRS - "fixed_array.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::compressed_tuple - absl::algorithm - absl::config - absl::core_headers - absl::dynamic_annotations - absl::throw_delegate - absl::memory - PUBLIC -) - -absl_cc_test( - NAME - fixed_array_test - SRCS - "fixed_array_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::fixed_array - absl::counting_allocator - absl::config - absl::exception_testing - absl::hash_testing - absl::memory - gmock_main -) - -absl_cc_test( - NAME - fixed_array_exception_safety_test - SRCS - "fixed_array_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::fixed_array - absl::config - absl::exception_safety_testing - gmock_main -) - -absl_cc_library( - NAME - inlined_vector_internal - HDRS - "internal/inlined_vector.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::compressed_tuple - absl::core_headers - absl::memory - absl::span - absl::type_traits - PUBLIC -) - -absl_cc_library( - NAME - inlined_vector - HDRS - "inlined_vector.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::core_headers - absl::inlined_vector_internal - absl::throw_delegate - absl::memory - PUBLIC -) - -absl_cc_library( - NAME - counting_allocator - HDRS - "internal/counting_allocator.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config -) - -absl_cc_test( - NAME - inlined_vector_test - SRCS - "inlined_vector_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - 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 - gmock_main -) - -absl_cc_test( - NAME - inlined_vector_exception_safety_test - SRCS - "inlined_vector_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::inlined_vector - absl::config - absl::exception_safety_testing - gmock_main -) - -absl_cc_library( - NAME - test_instance_tracker - HDRS - "internal/test_instance_tracker.h" - SRCS - "internal/test_instance_tracker.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::compare - TESTONLY -) - -absl_cc_test( - NAME - test_instance_tracker_test - SRCS - "internal/test_instance_tracker_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::test_instance_tracker - gmock_main -) - -absl_cc_library( - NAME - flat_hash_map - HDRS - "flat_hash_map.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::container_memory - absl::hash_function_defaults - absl::raw_hash_map - absl::algorithm_container - absl::memory - PUBLIC -) - -absl_cc_test( - NAME - flat_hash_map_test - SRCS - "flat_hash_map_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flat_hash_map - absl::hash_generator_testing - absl::unordered_map_constructor_test - absl::unordered_map_lookup_test - absl::unordered_map_members_test - absl::unordered_map_modifiers_test - absl::any - absl::raw_logging_internal - gmock_main -) - -absl_cc_library( - NAME - flat_hash_set - HDRS - "flat_hash_set.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::container_memory - absl::hash_function_defaults - absl::raw_hash_set - absl::algorithm_container - absl::core_headers - absl::memory - PUBLIC -) - -absl_cc_test( - NAME - flat_hash_set_test - SRCS - "flat_hash_set_test.cc" - COPTS - ${ABSL_TEST_COPTS} - "-DUNORDERED_SET_CXX17" - DEPS - absl::flat_hash_set - absl::hash_generator_testing - absl::unordered_set_constructor_test - absl::unordered_set_lookup_test - absl::unordered_set_members_test - absl::unordered_set_modifiers_test - absl::memory - absl::raw_logging_internal - absl::strings - gmock_main -) - -absl_cc_library( - NAME - node_hash_map - HDRS - "node_hash_map.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::container_memory - absl::hash_function_defaults - absl::node_hash_policy - absl::raw_hash_map - absl::algorithm_container - absl::memory - PUBLIC -) - -absl_cc_test( - NAME - node_hash_map_test - SRCS - "node_hash_map_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::node_hash_map - absl::tracked - absl::unordered_map_constructor_test - absl::unordered_map_lookup_test - absl::unordered_map_members_test - absl::unordered_map_modifiers_test - gmock_main -) - -absl_cc_library( - NAME - node_hash_set - HDRS - "node_hash_set.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::hash_function_defaults - absl::node_hash_policy - absl::raw_hash_set - absl::algorithm_container - absl::memory - PUBLIC -) - -absl_cc_test( - NAME - node_hash_set_test - SRCS - "node_hash_set_test.cc" - COPTS - ${ABSL_TEST_COPTS} - "-DUNORDERED_SET_CXX17" - DEPS - absl::hash_generator_testing - absl::node_hash_set - absl::unordered_set_constructor_test - absl::unordered_set_lookup_test - absl::unordered_set_members_test - absl::unordered_set_modifiers_test - gmock_main -) - -absl_cc_library( - NAME - container_memory - HDRS - "internal/container_memory.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::memory - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_test( - NAME - container_memory_test - SRCS - "internal/container_memory_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::container_memory - absl::strings - absl::test_instance_tracker - gmock_main -) - -absl_cc_library( - NAME - hash_function_defaults - HDRS - "internal/hash_function_defaults.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::cord - absl::hash - absl::strings - PUBLIC -) - -absl_cc_test( - NAME - hash_function_defaults_test - SRCS - "internal/hash_function_defaults_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::cord - absl::cord_test_helpers - absl::hash_function_defaults - absl::hash - absl::random_random - absl::strings - gmock_main -) - -absl_cc_library( - NAME - hash_generator_testing - HDRS - "internal/hash_generator_testing.h" - SRCS - "internal/hash_generator_testing.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_policy_testing - absl::memory - absl::meta - absl::strings - TESTONLY -) - -absl_cc_library( - NAME - hash_policy_testing - HDRS - "internal/hash_policy_testing.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash - absl::strings - TESTONLY -) - -absl_cc_test( - NAME - hash_policy_testing_test - SRCS - "internal/hash_policy_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_policy_testing - gmock_main -) - -absl_cc_library( - NAME - hash_policy_traits - HDRS - "internal/hash_policy_traits.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::meta - PUBLIC -) - -absl_cc_test( - NAME - hash_policy_traits_test - SRCS - "internal/hash_policy_traits_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_policy_traits - gmock_main -) - -absl_cc_library( - NAME - hashtablez_sampler - HDRS - "internal/hashtablez_sampler.h" - SRCS - "internal/hashtablez_sampler.cc" - "internal/hashtablez_sampler_force_weak_definition.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::exponential_biased - absl::have_sse - absl::synchronization -) - -absl_cc_test( - NAME - hashtablez_sampler_test - SRCS - "internal/hashtablez_sampler_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hashtablez_sampler - absl::have_sse - gmock_main -) - -absl_cc_library( - NAME - hashtable_debug - HDRS - "internal/hashtable_debug.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::hashtable_debug_hooks -) - -absl_cc_library( - NAME - hashtable_debug_hooks - HDRS - "internal/hashtable_debug_hooks.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_library( - NAME - have_sse - HDRS - "internal/have_sse.h" - COPTS - ${ABSL_DEFAULT_COPTS} -) - -absl_cc_library( - NAME - node_hash_policy - HDRS - "internal/node_hash_policy.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_test( - NAME - node_hash_policy_test - SRCS - "internal/node_hash_policy_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_policy_traits - absl::node_hash_policy - gmock_main -) - -absl_cc_library( - NAME - raw_hash_map - HDRS - "internal/raw_hash_map.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::container_memory - absl::raw_hash_set - absl::throw_delegate - PUBLIC -) - -absl_cc_library( - NAME - container_common - HDRS - "internal/common.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::type_traits -) - -absl_cc_library( - NAME - raw_hash_set - HDRS - "internal/raw_hash_set.h" - SRCS - "internal/raw_hash_set.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bits - absl::compressed_tuple - absl::config - absl::container_common - absl::container_memory - absl::core_headers - absl::endian - absl::hash_policy_traits - absl::hashtable_debug_hooks - absl::have_sse - absl::layout - absl::memory - absl::meta - absl::optional - absl::utility - absl::hashtablez_sampler - PUBLIC -) - -absl_cc_test( - NAME - raw_hash_set_test - SRCS - "internal/raw_hash_set_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::container_memory - absl::hash_function_defaults - absl::hash_policy_testing - absl::hashtable_debug - absl::raw_hash_set - absl::base - absl::config - absl::core_headers - absl::raw_logging_internal - absl::strings - gmock_main -) - -absl_cc_test( - NAME - raw_hash_set_allocator_test - SRCS - "internal/raw_hash_set_allocator_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::raw_hash_set - absl::tracked - absl::core_headers - gmock_main -) - -absl_cc_library( - NAME - layout - HDRS - "internal/layout.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - absl::meta - absl::strings - absl::span - absl::utility - PUBLIC -) - -absl_cc_test( - NAME - layout_test - SRCS - "internal/layout_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::layout - absl::config - absl::core_headers - absl::raw_logging_internal - absl::span - gmock_main -) - -absl_cc_library( - NAME - tracked - HDRS - "internal/tracked.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::config - TESTONLY -) - -absl_cc_library( - NAME - unordered_map_constructor_test - HDRS - "internal/unordered_map_constructor_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_map_lookup_test - HDRS - "internal/unordered_map_lookup_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_map_members_test - HDRS - "internal/unordered_map_members_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::type_traits - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_map_modifiers_test - HDRS - "internal/unordered_map_modifiers_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_set_constructor_test - HDRS - "internal/unordered_set_constructor_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_set_lookup_test - HDRS - "internal/unordered_set_lookup_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_set_members_test - HDRS - "internal/unordered_set_members_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::type_traits - gmock - TESTONLY -) - -absl_cc_library( - NAME - unordered_set_modifiers_test - HDRS - "internal/unordered_set_modifiers_test.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::hash_generator_testing - absl::hash_policy_testing - gmock - TESTONLY -) - -absl_cc_test( - NAME - unordered_set_test - SRCS - "internal/unordered_set_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::unordered_set_constructor_test - absl::unordered_set_lookup_test - absl::unordered_set_members_test - absl::unordered_set_modifiers_test - gmock_main -) - -absl_cc_test( - NAME - unordered_map_test - SRCS - "internal/unordered_map_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::unordered_map_constructor_test - absl::unordered_map_lookup_test - absl::unordered_map_members_test - absl::unordered_map_modifiers_test - gmock_main -) diff --git a/third_party/abseil_cpp/absl/container/btree_benchmark.cc b/third_party/abseil_cpp/absl/container/btree_benchmark.cc deleted file mode 100644 index 467986768aa1..000000000000 --- a/third_party/abseil_cpp/absl/container/btree_benchmark.cc +++ /dev/null @@ -1,735 +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 <stdint.h> - -#include <algorithm> -#include <functional> -#include <map> -#include <numeric> -#include <random> -#include <set> -#include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "absl/base/internal/raw_logging.h" -#include "absl/container/btree_map.h" -#include "absl/container/btree_set.h" -#include "absl/container/btree_test.h" -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/container/internal/hashtable_debug.h" -#include "absl/flags/flag.h" -#include "absl/hash/hash.h" -#include "absl/memory/memory.h" -#include "absl/strings/cord.h" -#include "absl/strings/str_format.h" -#include "absl/time/time.h" -#include "benchmark/benchmark.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -constexpr size_t kBenchmarkValues = 1 << 20; - -// How many times we add and remove sub-batches in one batch of *AddRem -// benchmarks. -constexpr size_t kAddRemBatchSize = 1 << 2; - -// Generates n values in the range [0, 4 * n]. -template <typename V> -std::vector<V> GenerateValues(int n) { - constexpr int kSeed = 23; - return GenerateValuesWithSeed<V>(n, 4 * n, kSeed); -} - -// Benchmark insertion of values into a container. -template <typename T> -void BM_InsertImpl(benchmark::State& state, bool sorted) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - if (sorted) { - std::sort(values.begin(), values.end()); - } - T container(values.begin(), values.end()); - - // Remove and re-insert 10% of the keys per batch. - const int batch_size = (kBenchmarkValues + 9) / 10; - while (state.KeepRunningBatch(batch_size)) { - state.PauseTiming(); - const auto i = static_cast<int>(state.iterations()); - - for (int j = i; j < i + batch_size; j++) { - int x = j % kBenchmarkValues; - container.erase(key_of_value(values[x])); - } - - state.ResumeTiming(); - - for (int j = i; j < i + batch_size; j++) { - int x = j % kBenchmarkValues; - container.insert(values[x]); - } - } -} - -template <typename T> -void BM_Insert(benchmark::State& state) { - BM_InsertImpl<T>(state, false); -} - -template <typename T> -void BM_InsertSorted(benchmark::State& state) { - BM_InsertImpl<T>(state, true); -} - -// 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_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; - - 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); - - auto it = container.find(k); - while (state.KeepRunning()) { - // Repeatedly removing then adding v. - container.erase(it); - it = GetIterFromInsert(container.insert(v)); - } -} - -// Benchmark inserting the first few elements in a container. In b-tree, this is -// when the root node grows. -template <typename T> -void BM_InsertSmall(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - - const int kSize = 8; - std::vector<V> values = GenerateValues<V>(kSize); - T container; - - while (state.KeepRunningBatch(kSize)) { - for (int i = 0; i < kSize; ++i) { - benchmark::DoNotOptimize(container.insert(values[i])); - } - state.PauseTiming(); - // Do not measure the time it takes to clear the container. - container.clear(); - state.ResumeTiming(); - } -} - -template <typename T> -void BM_LookupImpl(benchmark::State& state, bool sorted) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - if (sorted) { - std::sort(values.begin(), values.end()); - } - T container(values.begin(), values.end()); - - while (state.KeepRunning()) { - int idx = state.iterations() % kBenchmarkValues; - benchmark::DoNotOptimize(container.find(key_of_value(values[idx]))); - } -} - -// Benchmark lookup of values in a container. -template <typename T> -void BM_Lookup(benchmark::State& state) { - BM_LookupImpl<T>(state, false); -} - -// Benchmark lookup of values in a full container, meaning that values -// are inserted in-order to take advantage of biased insertion, which -// yields a full tree. -template <typename T> -void BM_FullLookup(benchmark::State& state) { - BM_LookupImpl<T>(state, true); -} - -// Benchmark deletion of values from a container. -template <typename T> -void BM_Delete(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - T container(values.begin(), values.end()); - - // Remove and re-insert 10% of the keys per batch. - const int batch_size = (kBenchmarkValues + 9) / 10; - while (state.KeepRunningBatch(batch_size)) { - const int i = state.iterations(); - - for (int j = i; j < i + batch_size; j++) { - int x = j % kBenchmarkValues; - container.erase(key_of_value(values[x])); - } - - state.PauseTiming(); - for (int j = i; j < i + batch_size; j++) { - int x = j % kBenchmarkValues; - container.insert(values[x]); - } - state.ResumeTiming(); - } -} - -// Benchmark deletion of multiple values from a container. -template <typename T> -void BM_DeleteRange(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - T container(values.begin(), values.end()); - - // Remove and re-insert 10% of the keys per batch. - const int batch_size = (kBenchmarkValues + 9) / 10; - while (state.KeepRunningBatch(batch_size)) { - const int i = state.iterations(); - - const int start_index = i % kBenchmarkValues; - - state.PauseTiming(); - { - std::vector<V> removed; - removed.reserve(batch_size); - auto itr = container.find(key_of_value(values[start_index])); - auto start = itr; - for (int j = 0; j < batch_size; j++) { - if (itr == container.end()) { - state.ResumeTiming(); - container.erase(start, itr); - state.PauseTiming(); - itr = container.begin(); - start = itr; - } - removed.push_back(*itr++); - } - - state.ResumeTiming(); - container.erase(start, itr); - state.PauseTiming(); - - container.insert(removed.begin(), removed.end()); - } - state.ResumeTiming(); - } -} - -// Benchmark steady-state insert (into first half of range) and remove (from -// second half of range), treating the container approximately like a queue with -// log-time access for all elements. This benchmark does not test the case where -// insertion and removal happen in the same region of the tree. This benchmark -// counts two value constructors. -template <typename T> -void BM_QueueAddRem(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - - ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance"); - - T container; - - const size_t half = kBenchmarkValues / 2; - std::vector<int> remove_keys(half); - std::vector<int> add_keys(half); - - // We want to do the exact same work repeatedly, and the benchmark can end - // after a different number of iterations depending on the speed of the - // individual run so we use a large batch size here and ensure that we do - // deterministic work every batch. - while (state.KeepRunningBatch(half * kAddRemBatchSize)) { - state.PauseTiming(); - - container.clear(); - - for (size_t i = 0; i < half; ++i) { - remove_keys[i] = i; - add_keys[i] = i; - } - constexpr int kSeed = 5; - std::mt19937_64 rand(kSeed); - std::shuffle(remove_keys.begin(), remove_keys.end(), rand); - std::shuffle(add_keys.begin(), add_keys.end(), rand); - - // Note needs lazy generation of values. - Generator<V> g(kBenchmarkValues * kAddRemBatchSize); - - for (size_t i = 0; i < half; ++i) { - container.insert(g(add_keys[i])); - container.insert(g(half + remove_keys[i])); - } - - // There are three parts each of size "half": - // 1 is being deleted from [offset - half, offset) - // 2 is standing [offset, offset + half) - // 3 is being inserted into [offset + half, offset + 2 * half) - size_t offset = 0; - - for (size_t i = 0; i < kAddRemBatchSize; ++i) { - std::shuffle(remove_keys.begin(), remove_keys.end(), rand); - std::shuffle(add_keys.begin(), add_keys.end(), rand); - offset += half; - - state.ResumeTiming(); - for (size_t idx = 0; idx < half; ++idx) { - container.erase(key_of_value(g(offset - half + remove_keys[idx]))); - container.insert(g(offset + half + add_keys[idx])); - } - state.PauseTiming(); - } - state.ResumeTiming(); - } -} - -// Mixed insertion and deletion in the same range using pre-constructed values. -template <typename T> -void BM_MixedAddRem(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - - ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance"); - - T container; - - // Create two random shuffles - std::vector<int> remove_keys(kBenchmarkValues); - std::vector<int> add_keys(kBenchmarkValues); - - // We want to do the exact same work repeatedly, and the benchmark can end - // after a different number of iterations depending on the speed of the - // individual run so we use a large batch size here and ensure that we do - // deterministic work every batch. - while (state.KeepRunningBatch(kBenchmarkValues * kAddRemBatchSize)) { - state.PauseTiming(); - - container.clear(); - - constexpr int kSeed = 7; - std::mt19937_64 rand(kSeed); - - std::vector<V> values = GenerateValues<V>(kBenchmarkValues * 2); - - // Insert the first half of the values (already in random order) - container.insert(values.begin(), values.begin() + kBenchmarkValues); - - // Insert the first half of the values (already in random order) - for (size_t i = 0; i < kBenchmarkValues; ++i) { - // remove_keys and add_keys will be swapped before each round, - // therefore fill add_keys here w/ the keys being inserted, so - // they'll be the first to be removed. - remove_keys[i] = i + kBenchmarkValues; - add_keys[i] = i; - } - - for (size_t i = 0; i < kAddRemBatchSize; ++i) { - remove_keys.swap(add_keys); - std::shuffle(remove_keys.begin(), remove_keys.end(), rand); - std::shuffle(add_keys.begin(), add_keys.end(), rand); - - state.ResumeTiming(); - for (size_t idx = 0; idx < kBenchmarkValues; ++idx) { - container.erase(key_of_value(values[remove_keys[idx]])); - container.insert(values[add_keys[idx]]); - } - state.PauseTiming(); - } - state.ResumeTiming(); - } -} - -// Insertion at end, removal from the beginning. This benchmark -// counts two value constructors. -// TODO(ezb): we could add a GenerateNext version of generator that could reduce -// noise for string-like types. -template <typename T> -void BM_Fifo(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - - T container; - // Need lazy generation of values as state.max_iterations is large. - Generator<V> g(kBenchmarkValues + state.max_iterations); - - for (int i = 0; i < kBenchmarkValues; i++) { - container.insert(g(i)); - } - - while (state.KeepRunning()) { - container.erase(container.begin()); - container.insert(container.end(), g(state.iterations() + kBenchmarkValues)); - } -} - -// Iteration (forward) through the tree -template <typename T> -void BM_FwdIter(benchmark::State& state) { - using V = typename remove_pair_const<typename T::value_type>::type; - using R = typename T::value_type const*; - - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - T container(values.begin(), values.end()); - - auto iter = container.end(); - - R r = nullptr; - - while (state.KeepRunning()) { - if (iter == container.end()) iter = container.begin(); - r = &(*iter); - ++iter; - } - - benchmark::DoNotOptimize(r); -} - -// Benchmark random range-construction of a container. -template <typename T> -void BM_RangeConstructionImpl(benchmark::State& state, bool sorted) { - using V = typename remove_pair_const<typename T::value_type>::type; - - std::vector<V> values = GenerateValues<V>(kBenchmarkValues); - if (sorted) { - std::sort(values.begin(), values.end()); - } - { - T container(values.begin(), values.end()); - } - - while (state.KeepRunning()) { - T container(values.begin(), values.end()); - benchmark::DoNotOptimize(container); - } -} - -template <typename T> -void BM_InsertRangeRandom(benchmark::State& state) { - BM_RangeConstructionImpl<T>(state, false); -} - -template <typename T> -void BM_InsertRangeSorted(benchmark::State& state) { - BM_RangeConstructionImpl<T>(state, true); -} - -#define STL_ORDERED_TYPES(value) \ - using stl_set_##value = std::set<value>; \ - using stl_map_##value = std::map<value, intptr_t>; \ - using stl_multiset_##value = std::multiset<value>; \ - using stl_multimap_##value = std::multimap<value, intptr_t> - -using StdString = std::string; -STL_ORDERED_TYPES(int32_t); -STL_ORDERED_TYPES(int64_t); -STL_ORDERED_TYPES(StdString); -STL_ORDERED_TYPES(Cord); -STL_ORDERED_TYPES(Time); - -#define STL_UNORDERED_TYPES(value) \ - using stl_unordered_set_##value = std::unordered_set<value>; \ - using stl_unordered_map_##value = std::unordered_map<value, intptr_t>; \ - using flat_hash_set_##value = flat_hash_set<value>; \ - using flat_hash_map_##value = flat_hash_map<value, intptr_t>; \ - using stl_unordered_multiset_##value = std::unordered_multiset<value>; \ - using stl_unordered_multimap_##value = \ - std::unordered_multimap<value, intptr_t> - -#define STL_UNORDERED_TYPES_CUSTOM_HASH(value, hash) \ - using stl_unordered_set_##value = std::unordered_set<value, hash>; \ - using stl_unordered_map_##value = std::unordered_map<value, intptr_t, hash>; \ - using flat_hash_set_##value = flat_hash_set<value, hash>; \ - using flat_hash_map_##value = flat_hash_map<value, intptr_t, hash>; \ - using stl_unordered_multiset_##value = std::unordered_multiset<value, hash>; \ - using stl_unordered_multimap_##value = \ - std::unordered_multimap<value, intptr_t, hash> - -STL_UNORDERED_TYPES_CUSTOM_HASH(Cord, absl::Hash<absl::Cord>); - -STL_UNORDERED_TYPES(int32_t); -STL_UNORDERED_TYPES(int64_t); -STL_UNORDERED_TYPES(StdString); -STL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>); - -#define BTREE_TYPES(value) \ - using btree_256_set_##value = \ - btree_set<value, std::less<value>, std::allocator<value>>; \ - using btree_256_map_##value = \ - btree_map<value, intptr_t, std::less<value>, \ - std::allocator<std::pair<const value, intptr_t>>>; \ - using btree_256_multiset_##value = \ - btree_multiset<value, std::less<value>, std::allocator<value>>; \ - using btree_256_multimap_##value = \ - btree_multimap<value, intptr_t, std::less<value>, \ - std::allocator<std::pair<const value, intptr_t>>> - -BTREE_TYPES(int32_t); -BTREE_TYPES(int64_t); -BTREE_TYPES(StdString); -BTREE_TYPES(Cord); -BTREE_TYPES(Time); - -#define MY_BENCHMARK4(type, func) \ - void BM_##type##_##func(benchmark::State& state) { BM_##func<type>(state); } \ - BENCHMARK(BM_##type##_##func) - -#define MY_BENCHMARK3(type) \ - MY_BENCHMARK4(type, Insert); \ - MY_BENCHMARK4(type, InsertSorted); \ - MY_BENCHMARK4(type, InsertEnd); \ - MY_BENCHMARK4(type, InsertSmall); \ - MY_BENCHMARK4(type, Lookup); \ - MY_BENCHMARK4(type, FullLookup); \ - MY_BENCHMARK4(type, Delete); \ - MY_BENCHMARK4(type, DeleteRange); \ - MY_BENCHMARK4(type, QueueAddRem); \ - MY_BENCHMARK4(type, MixedAddRem); \ - MY_BENCHMARK4(type, Fifo); \ - MY_BENCHMARK4(type, FwdIter); \ - MY_BENCHMARK4(type, InsertRangeRandom); \ - MY_BENCHMARK4(type, InsertRangeSorted) - -#define MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type) \ - MY_BENCHMARK3(stl_##type); \ - MY_BENCHMARK3(stl_unordered_##type); \ - MY_BENCHMARK3(btree_256_##type) - -#define MY_BENCHMARK2(type) \ - MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type); \ - MY_BENCHMARK3(flat_hash_##type) - -// Define MULTI_TESTING to see benchmarks for multi-containers also. -// -// You can use --copt=-DMULTI_TESTING. -#ifdef MULTI_TESTING -#define MY_BENCHMARK(type) \ - MY_BENCHMARK2(set_##type); \ - MY_BENCHMARK2(map_##type); \ - MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multiset_##type); \ - MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multimap_##type) -#else -#define MY_BENCHMARK(type) \ - MY_BENCHMARK2(set_##type); \ - MY_BENCHMARK2(map_##type) -#endif - -MY_BENCHMARK(int32_t); -MY_BENCHMARK(int64_t); -MY_BENCHMARK(StdString); -MY_BENCHMARK(Cord); -MY_BENCHMARK(Time); - -// Define a type whose size and cost of moving are independently customizable. -// When sizeof(value_type) increases, we expect btree to no longer have as much -// cache-locality advantage over STL. When cost of moving increases, we expect -// btree to actually do more work than STL because it has to move values around -// and STL doesn't have to. -template <int Size, int Copies> -struct BigType { - BigType() : BigType(0) {} - explicit BigType(int x) { std::iota(values.begin(), values.end(), x); } - - void Copy(const BigType& other) { - for (int i = 0; i < Size && i < Copies; ++i) values[i] = other.values[i]; - // If Copies > Size, do extra copies. - for (int i = Size, idx = 0; i < Copies; ++i) { - int64_t tmp = other.values[idx]; - benchmark::DoNotOptimize(tmp); - idx = idx + 1 == Size ? 0 : idx + 1; - } - } - - BigType(const BigType& other) { Copy(other); } - BigType& operator=(const BigType& other) { - Copy(other); - return *this; - } - - // Compare only the first Copies elements if Copies is less than Size. - bool operator<(const BigType& other) const { - return std::lexicographical_compare( - values.begin(), values.begin() + std::min(Size, Copies), - other.values.begin(), other.values.begin() + std::min(Size, Copies)); - } - bool operator==(const BigType& other) const { - return std::equal(values.begin(), values.begin() + std::min(Size, Copies), - other.values.begin()); - } - - // Support absl::Hash. - template <typename State> - friend State AbslHashValue(State h, const BigType& b) { - for (int i = 0; i < Size && i < Copies; ++i) - h = State::combine(std::move(h), b.values[i]); - return h; - } - - std::array<int64_t, Size> values; -}; - -#define BIG_TYPE_BENCHMARKS(SIZE, COPIES) \ - using stl_set_size##SIZE##copies##COPIES = std::set<BigType<SIZE, COPIES>>; \ - using stl_map_size##SIZE##copies##COPIES = \ - std::map<BigType<SIZE, COPIES>, intptr_t>; \ - using stl_multiset_size##SIZE##copies##COPIES = \ - std::multiset<BigType<SIZE, COPIES>>; \ - using stl_multimap_size##SIZE##copies##COPIES = \ - std::multimap<BigType<SIZE, COPIES>, intptr_t>; \ - using stl_unordered_set_size##SIZE##copies##COPIES = \ - std::unordered_set<BigType<SIZE, COPIES>, \ - absl::Hash<BigType<SIZE, COPIES>>>; \ - using stl_unordered_map_size##SIZE##copies##COPIES = \ - std::unordered_map<BigType<SIZE, COPIES>, intptr_t, \ - absl::Hash<BigType<SIZE, COPIES>>>; \ - using flat_hash_set_size##SIZE##copies##COPIES = \ - flat_hash_set<BigType<SIZE, COPIES>>; \ - using flat_hash_map_size##SIZE##copies##COPIES = \ - flat_hash_map<BigType<SIZE, COPIES>, intptr_t>; \ - using stl_unordered_multiset_size##SIZE##copies##COPIES = \ - std::unordered_multiset<BigType<SIZE, COPIES>, \ - absl::Hash<BigType<SIZE, COPIES>>>; \ - using stl_unordered_multimap_size##SIZE##copies##COPIES = \ - std::unordered_multimap<BigType<SIZE, COPIES>, intptr_t, \ - absl::Hash<BigType<SIZE, COPIES>>>; \ - using btree_256_set_size##SIZE##copies##COPIES = \ - btree_set<BigType<SIZE, COPIES>>; \ - using btree_256_map_size##SIZE##copies##COPIES = \ - btree_map<BigType<SIZE, COPIES>, intptr_t>; \ - using btree_256_multiset_size##SIZE##copies##COPIES = \ - btree_multiset<BigType<SIZE, COPIES>>; \ - using btree_256_multimap_size##SIZE##copies##COPIES = \ - btree_multimap<BigType<SIZE, COPIES>, intptr_t>; \ - MY_BENCHMARK(size##SIZE##copies##COPIES) - -// Define BIG_TYPE_TESTING to see benchmarks for more big types. -// -// You can use --copt=-DBIG_TYPE_TESTING. -#ifndef NODESIZE_TESTING -#ifdef BIG_TYPE_TESTING -BIG_TYPE_BENCHMARKS(1, 4); -BIG_TYPE_BENCHMARKS(4, 1); -BIG_TYPE_BENCHMARKS(4, 4); -BIG_TYPE_BENCHMARKS(1, 8); -BIG_TYPE_BENCHMARKS(8, 1); -BIG_TYPE_BENCHMARKS(8, 8); -BIG_TYPE_BENCHMARKS(1, 16); -BIG_TYPE_BENCHMARKS(16, 1); -BIG_TYPE_BENCHMARKS(16, 16); -BIG_TYPE_BENCHMARKS(1, 32); -BIG_TYPE_BENCHMARKS(32, 1); -BIG_TYPE_BENCHMARKS(32, 32); -#else -BIG_TYPE_BENCHMARKS(32, 32); -#endif -#endif - -// Benchmark using unique_ptrs to large value types. In order to be able to use -// the same benchmark code as the other types, use a type that holds a -// unique_ptr and has a copy constructor. -template <int Size> -struct BigTypePtr { - BigTypePtr() : BigTypePtr(0) {} - explicit BigTypePtr(int x) { - ptr = absl::make_unique<BigType<Size, Size>>(x); - } - BigTypePtr(const BigTypePtr& other) { - ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr); - } - BigTypePtr(BigTypePtr&& other) noexcept = default; - BigTypePtr& operator=(const BigTypePtr& other) { - ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr); - } - BigTypePtr& operator=(BigTypePtr&& other) noexcept = default; - - bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; } - bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; } - - std::unique_ptr<BigType<Size, Size>> ptr; -}; - -template <int Size> -double ContainerInfo(const btree_set<BigTypePtr<Size>>& b) { - const double bytes_used = - b.bytes_used() + b.size() * sizeof(BigType<Size, Size>); - const double bytes_per_value = bytes_used / b.size(); - BtreeContainerInfoLog(b, bytes_used, bytes_per_value); - return bytes_per_value; -} -template <int Size> -double ContainerInfo(const btree_map<int, BigTypePtr<Size>>& b) { - const double bytes_used = - b.bytes_used() + b.size() * sizeof(BigType<Size, Size>); - const double bytes_per_value = bytes_used / b.size(); - BtreeContainerInfoLog(b, bytes_used, bytes_per_value); - return bytes_per_value; -} - -#define BIG_TYPE_PTR_BENCHMARKS(SIZE) \ - using stl_set_size##SIZE##copies##SIZE##ptr = std::set<BigType<SIZE, SIZE>>; \ - using stl_map_size##SIZE##copies##SIZE##ptr = \ - std::map<int, BigType<SIZE, SIZE>>; \ - using stl_unordered_set_size##SIZE##copies##SIZE##ptr = \ - std::unordered_set<BigType<SIZE, SIZE>, \ - absl::Hash<BigType<SIZE, SIZE>>>; \ - using stl_unordered_map_size##SIZE##copies##SIZE##ptr = \ - std::unordered_map<int, BigType<SIZE, SIZE>>; \ - using flat_hash_set_size##SIZE##copies##SIZE##ptr = \ - flat_hash_set<BigType<SIZE, SIZE>>; \ - using flat_hash_map_size##SIZE##copies##SIZE##ptr = \ - flat_hash_map<int, BigTypePtr<SIZE>>; \ - using btree_256_set_size##SIZE##copies##SIZE##ptr = \ - btree_set<BigTypePtr<SIZE>>; \ - using btree_256_map_size##SIZE##copies##SIZE##ptr = \ - btree_map<int, BigTypePtr<SIZE>>; \ - MY_BENCHMARK3(stl_set_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(stl_unordered_set_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(flat_hash_set_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(btree_256_set_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(stl_map_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(stl_unordered_map_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(flat_hash_map_size##SIZE##copies##SIZE##ptr); \ - MY_BENCHMARK3(btree_256_map_size##SIZE##copies##SIZE##ptr) - -BIG_TYPE_PTR_BENCHMARKS(32); - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/btree_map.h b/third_party/abseil_cpp/absl/container/btree_map.h deleted file mode 100644 index abc09b0ac068..000000000000 --- a/third_party/abseil_cpp/absl/container/btree_map.h +++ /dev/null @@ -1,769 +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: btree_map.h -// ----------------------------------------------------------------------------- -// -// This header file defines B-tree maps: sorted associative containers mapping -// keys to values. -// -// * `absl::btree_map<>` -// * `absl::btree_multimap<>` -// -// These B-tree types are similar to the corresponding types in the STL -// (`std::map` and `std::multimap`) and generally conform to the STL interfaces -// of those types. However, because they are implemented using B-trees, they -// are more efficient in most situations. -// -// Unlike `std::map` and `std::multimap`, which are commonly implemented using -// red-black tree nodes, B-tree maps use more generic B-tree nodes able to hold -// multiple values per node. Holding multiple values per node often makes -// B-tree maps perform better than their `std::map` counterparts, because -// multiple entries can be checked within the same cache hit. -// -// However, these types should not be considered drop-in replacements for -// `std::map` and `std::multimap` as there are some API differences, which are -// noted in this header file. -// -// Importantly, insertions and deletions may invalidate outstanding iterators, -// pointers, and references to elements. Such invalidations are typically only -// an issue if insertion and deletion operations are interleaved with the use of -// more than one iterator, pointer, or reference simultaneously. For this -// reason, `insert()` and `erase()` return a valid iterator at the current -// position. - -#ifndef ABSL_CONTAINER_BTREE_MAP_H_ -#define ABSL_CONTAINER_BTREE_MAP_H_ - -#include "absl/container/internal/btree.h" // IWYU pragma: export -#include "absl/container/internal/btree_container.h" // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::btree_map<> -// -// An `absl::btree_map<K, V>` is an ordered associative container of -// unique keys and associated values designed to be a more efficient replacement -// for `std::map` (in most cases). -// -// Keys are sorted using an (optional) comparison function, which defaults to -// `std::less<K>`. -// -// An `absl::btree_map<K, V>` uses a default allocator of -// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate) -// nodes, and construct and destruct values within those nodes. You may -// instead specify a custom allocator `A` (which in turn requires specifying a -// custom comparator `C`) as in `absl::btree_map<K, V, C, A>`. -// -template <typename Key, typename Value, typename Compare = std::less<Key>, - typename Alloc = std::allocator<std::pair<const Key, Value>>> -class btree_map - : public container_internal::btree_map_container< - container_internal::btree<container_internal::map_params< - Key, Value, Compare, Alloc, /*TargetNodeSize=*/256, - /*Multi=*/false>>> { - using Base = typename btree_map::btree_map_container; - - public: - // Constructors and Assignment Operators - // - // A `btree_map` supports the same overload set as `std::map` - // for construction and assignment: - // - // * Default constructor - // - // absl::btree_map<int, std::string> map1; - // - // * Initializer List constructor - // - // absl::btree_map<int, std::string> map2 = - // {{1, "huey"}, {2, "dewey"}, {3, "louie"},}; - // - // * Copy constructor - // - // absl::btree_map<int, std::string> map3(map2); - // - // * Copy assignment operator - // - // absl::btree_map<int, std::string> map4; - // map4 = map3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::btree_map<int, std::string> map5(std::move(map4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::btree_map<int, std::string> map6; - // map6 = std::move(map5); - // - // * Range constructor - // - // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; - // absl::btree_map<int, std::string> map7(v.begin(), v.end()); - btree_map() {} - using Base::Base; - - // btree_map::begin() - // - // Returns an iterator to the beginning of the `btree_map`. - using Base::begin; - - // btree_map::cbegin() - // - // Returns a const iterator to the beginning of the `btree_map`. - using Base::cbegin; - - // btree_map::end() - // - // Returns an iterator to the end of the `btree_map`. - using Base::end; - - // btree_map::cend() - // - // Returns a const iterator to the end of the `btree_map`. - using Base::cend; - - // btree_map::empty() - // - // Returns whether or not the `btree_map` is empty. - using Base::empty; - - // btree_map::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `btree_map` under current memory constraints. This value can be thought - // of as the largest value of `std::distance(begin(), end())` for a - // `btree_map<Key, T>`. - using Base::max_size; - - // btree_map::size() - // - // Returns the number of elements currently within the `btree_map`. - using Base::size; - - // btree_map::clear() - // - // Removes all elements from the `btree_map`. Invalidates any references, - // pointers, or iterators referring to contained elements. - using Base::clear; - - // btree_map::erase() - // - // Erases elements within the `btree_map`. If an erase occurs, any references, - // pointers, or iterators are invalidated. - // Overloads are listed below. - // - // iterator erase(iterator position): - // iterator erase(const_iterator position): - // - // Erases the element at `position` of the `btree_map`, returning - // the iterator pointing to the element after the one that was erased - // (or end() if none exists). - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning - // the iterator pointing to the element after the interval that was erased - // (or end() if none exists). - // - // template <typename K> size_type erase(const K& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // btree_map::insert() - // - // Inserts an element of the specified value into the `btree_map`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If an insertion - // occurs, any references, pointers, or iterators are invalidated. - // Overloads are listed below. - // - // std::pair<iterator,bool> insert(const value_type& value): - // - // Inserts a value into the `btree_map`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a bool denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(value_type&& value): - // - // Inserts a moveable value into the `btree_map`. Returns a pair - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a bool denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const value_type& value): - // iterator insert(const_iterator hint, value_type&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - using Base::insert; - - // btree_map::insert_or_assign() - // - // Inserts an element of the specified value into the `btree_map` provided - // that a value with the given key does not already exist, or replaces the - // corresponding mapped type with the forwarded `obj` argument if a key for - // that value already exists, returning an iterator pointing to the newly - // inserted element. Overloads are listed below. - // - // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj): - // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `btree_map`. If the returned bool is true, insertion took place, and if - // it's false, assignment took place. - // - // iterator insert_or_assign(const_iterator hint, - // const key_type& k, M&& obj): - // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `btree_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - using Base::insert_or_assign; - - // btree_map::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_map`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. - using Base::emplace; - - // btree_map::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_map`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. - using Base::emplace_hint; - - // btree_map::try_emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_map`, provided that no element with the given key - // already exists. Unlike `emplace()`, if an element with the given key - // already exists, we guarantee that no element is constructed. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. - // - // Overloads are listed below. - // - // std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args): - // std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `btree_map`. - // - // iterator try_emplace(const_iterator hint, - // const key_type& k, Args&&... args): - // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `btree_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - using Base::try_emplace; - - // btree_map::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // template <typename K> node_type extract(const K& k): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `btree_map` - // does not contain an element with a matching key, this function returns an - // empty node handle. - // - // NOTE: when compiled in an earlier version of C++ than C++17, - // `node_type::key()` returns a const reference to the key instead of a - // mutable reference. We cannot safely return a mutable reference without - // std::launder (which is not available before C++17). - // - // NOTE: In this context, `node_type` refers to the C++17 concept of a - // move-only type that owns and provides access to the elements in associative - // containers (https://en.cppreference.com/w/cpp/container/node_handle). - // It does NOT refer to the data layout of the underlying btree. - using Base::extract; - - // btree_map::merge() - // - // Extracts elements from a given `source` btree_map into this - // `btree_map`. If the destination `btree_map` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // btree_map::swap(btree_map& other) - // - // Exchanges the contents of this `btree_map` with those of the `other` - // btree_map, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `btree_map` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - using Base::swap; - - // btree_map::at() - // - // Returns a reference to the mapped value of the element with key equivalent - // to the passed key. - using Base::at; - - // btree_map::contains() - // - // template <typename K> bool contains(const K& key) const: - // - // Determines whether an element comparing equal to the given `key` exists - // within the `btree_map`, returning `true` if so or `false` otherwise. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::contains; - - // btree_map::count() - // - // template <typename K> size_type count(const K& key) const: - // - // Returns the number of elements comparing equal to the given `key` within - // the `btree_map`. Note that this function will return either `1` or `0` - // since duplicate elements are not allowed within a `btree_map`. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::count; - - // btree_map::equal_range() - // - // Returns a 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() - // - // template <typename K> iterator find(const K& key): - // template <typename K> const_iterator find(const K& key) const: - // - // Finds an element with the passed `key` within the `btree_map`. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::find; - - // btree_map::operator[]() - // - // Returns a reference to the value mapped to the passed key within the - // `btree_map`, performing an `insert()` if the key does not already - // exist. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. Otherwise iterators are not affected and references are not - // invalidated. Overloads are listed below. - // - // T& operator[](key_type&& key): - // T& operator[](const key_type& key): - // - // Inserts a value_type object constructed in-place if the element with the - // given key does not exist. - using Base::operator[]; - - // btree_map::get_allocator() - // - // Returns the allocator function associated with this `btree_map`. - using Base::get_allocator; - - // btree_map::key_comp(); - // - // Returns the key comparator associated with this `btree_map`. - using Base::key_comp; - - // btree_map::value_comp(); - // - // Returns the value comparator associated with this `btree_map`. - using Base::value_comp; -}; - -// absl::swap(absl::btree_map<>, absl::btree_map<>) -// -// Swaps the contents of two `absl::btree_map` containers. -template <typename K, typename V, typename C, typename A> -void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) { - return x.swap(y); -} - -// absl::erase_if(absl::btree_map<>, Pred) -// -// Erases all elements that satisfy the predicate pred from the container. -template <typename K, typename V, typename C, typename A, typename Pred> -void erase_if(btree_map<K, V, C, A> &map, Pred pred) { - for (auto it = map.begin(); it != map.end();) { - if (pred(*it)) { - it = map.erase(it); - } else { - ++it; - } - } -} - -// absl::btree_multimap -// -// An `absl::btree_multimap<K, V>` is an ordered associative container of -// keys and associated values designed to be a more efficient replacement for -// `std::multimap` (in most cases). Unlike `absl::btree_map`, a B-tree multimap -// allows multiple elements with equivalent keys. -// -// Keys are sorted using an (optional) comparison function, which defaults to -// `std::less<K>`. -// -// An `absl::btree_multimap<K, V>` uses a default allocator of -// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate) -// nodes, and construct and destruct values within those nodes. You may -// instead specify a custom allocator `A` (which in turn requires specifying a -// custom comparator `C`) as in `absl::btree_multimap<K, V, C, A>`. -// -template <typename Key, typename Value, typename Compare = std::less<Key>, - typename Alloc = std::allocator<std::pair<const Key, Value>>> -class btree_multimap - : public container_internal::btree_multimap_container< - container_internal::btree<container_internal::map_params< - Key, Value, Compare, Alloc, /*TargetNodeSize=*/256, - /*Multi=*/true>>> { - using Base = typename btree_multimap::btree_multimap_container; - - public: - // Constructors and Assignment Operators - // - // A `btree_multimap` supports the same overload set as `std::multimap` - // for construction and assignment: - // - // * Default constructor - // - // absl::btree_multimap<int, std::string> map1; - // - // * Initializer List constructor - // - // absl::btree_multimap<int, std::string> map2 = - // {{1, "huey"}, {2, "dewey"}, {3, "louie"},}; - // - // * Copy constructor - // - // absl::btree_multimap<int, std::string> map3(map2); - // - // * Copy assignment operator - // - // absl::btree_multimap<int, std::string> map4; - // map4 = map3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::btree_multimap<int, std::string> map5(std::move(map4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::btree_multimap<int, std::string> map6; - // map6 = std::move(map5); - // - // * Range constructor - // - // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; - // absl::btree_multimap<int, std::string> map7(v.begin(), v.end()); - btree_multimap() {} - using Base::Base; - - // btree_multimap::begin() - // - // Returns an iterator to the beginning of the `btree_multimap`. - using Base::begin; - - // btree_multimap::cbegin() - // - // Returns a const iterator to the beginning of the `btree_multimap`. - using Base::cbegin; - - // btree_multimap::end() - // - // Returns an iterator to the end of the `btree_multimap`. - using Base::end; - - // btree_multimap::cend() - // - // Returns a const iterator to the end of the `btree_multimap`. - using Base::cend; - - // btree_multimap::empty() - // - // Returns whether or not the `btree_multimap` is empty. - using Base::empty; - - // btree_multimap::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `btree_multimap` under current memory constraints. This value can be - // thought of as the largest value of `std::distance(begin(), end())` for a - // `btree_multimap<Key, T>`. - using Base::max_size; - - // btree_multimap::size() - // - // Returns the number of elements currently within the `btree_multimap`. - using Base::size; - - // btree_multimap::clear() - // - // Removes all elements from the `btree_multimap`. Invalidates any references, - // pointers, or iterators referring to contained elements. - using Base::clear; - - // btree_multimap::erase() - // - // Erases elements within the `btree_multimap`. If an erase occurs, any - // references, pointers, or iterators are invalidated. - // Overloads are listed below. - // - // iterator erase(iterator position): - // iterator erase(const_iterator position): - // - // Erases the element at `position` of the `btree_multimap`, returning - // the iterator pointing to the element after the one that was erased - // (or end() if none exists). - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning - // the iterator pointing to the element after the interval that was erased - // (or end() if none exists). - // - // template <typename K> size_type erase(const K& key): - // - // Erases the elements matching the key, if any exist, returning the - // number of elements erased. - using Base::erase; - - // btree_multimap::insert() - // - // Inserts an element of the specified value into the `btree_multimap`, - // returning an iterator pointing to the newly inserted element. - // Any references, pointers, or iterators are invalidated. Overloads are - // listed below. - // - // iterator insert(const value_type& value): - // - // Inserts a value into the `btree_multimap`, returning an iterator to the - // inserted element. - // - // iterator insert(value_type&& value): - // - // Inserts a moveable value into the `btree_multimap`, returning an iterator - // to the inserted element. - // - // iterator insert(const_iterator hint, const value_type& value): - // iterator insert(const_iterator hint, value_type&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - using Base::insert; - - // btree_multimap::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_multimap`. Any references, pointers, or iterators are - // invalidated. - using Base::emplace; - - // btree_multimap::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_multimap`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search. - // - // Any references, pointers, or iterators are invalidated. - using Base::emplace_hint; - - // btree_multimap::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // template <typename K> node_type extract(const K& k): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `btree_multimap` - // does not contain an element with a matching key, this function returns an - // empty node handle. - // - // NOTE: when compiled in an earlier version of C++ than C++17, - // `node_type::key()` returns a const reference to the key instead of a - // mutable reference. We cannot safely return a mutable reference without - // std::launder (which is not available before C++17). - // - // NOTE: In this context, `node_type` refers to the C++17 concept of a - // move-only type that owns and provides access to the elements in associative - // containers (https://en.cppreference.com/w/cpp/container/node_handle). - // It does NOT refer to the data layout of the underlying btree. - using Base::extract; - - // btree_multimap::merge() - // - // Extracts elements from a given `source` btree_multimap into this - // `btree_multimap`. If the destination `btree_multimap` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // btree_multimap::swap(btree_multimap& other) - // - // Exchanges the contents of this `btree_multimap` with those of the `other` - // btree_multimap, avoiding invocation of any move, copy, or swap operations - // on individual elements. - // - // All iterators and references on the `btree_multimap` remain valid, - // excepting for the past-the-end iterator, which is invalidated. - using Base::swap; - - // btree_multimap::contains() - // - // template <typename K> bool contains(const K& key) const: - // - // Determines whether an element comparing equal to the given `key` exists - // within the `btree_multimap`, returning `true` if so or `false` otherwise. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::contains; - - // btree_multimap::count() - // - // template <typename K> size_type count(const K& key) const: - // - // Returns the number of elements comparing equal to the given `key` within - // the `btree_multimap`. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::count; - - // btree_multimap::equal_range() - // - // Returns a 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; - - // btree_multimap::find() - // - // template <typename K> iterator find(const K& key): - // template <typename K> const_iterator find(const K& key) const: - // - // Finds an element with the passed `key` within the `btree_multimap`. - // - // Supports heterogeneous lookup, provided that the map is provided a - // compatible heterogeneous comparator. - using Base::find; - - // btree_multimap::get_allocator() - // - // Returns the allocator function associated with this `btree_multimap`. - using Base::get_allocator; - - // btree_multimap::key_comp(); - // - // Returns the key comparator associated with this `btree_multimap`. - using Base::key_comp; - - // btree_multimap::value_comp(); - // - // Returns the value comparator associated with this `btree_multimap`. - using Base::value_comp; -}; - -// absl::swap(absl::btree_multimap<>, absl::btree_multimap<>) -// -// Swaps the contents of two `absl::btree_multimap` containers. -template <typename K, typename V, typename C, typename A> -void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) { - return x.swap(y); -} - -// absl::erase_if(absl::btree_multimap<>, Pred) -// -// Erases all elements that satisfy the predicate pred from the container. -template <typename K, typename V, typename C, typename A, typename Pred> -void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) { - for (auto it = map.begin(); it != map.end();) { - if (pred(*it)) { - it = map.erase(it); - } else { - ++it; - } - } -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_BTREE_MAP_H_ diff --git a/third_party/abseil_cpp/absl/container/btree_set.h b/third_party/abseil_cpp/absl/container/btree_set.h deleted file mode 100644 index 21ef0a032a85..000000000000 --- a/third_party/abseil_cpp/absl/container/btree_set.h +++ /dev/null @@ -1,683 +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: btree_set.h -// ----------------------------------------------------------------------------- -// -// This header file defines B-tree sets: sorted associative containers of -// values. -// -// * `absl::btree_set<>` -// * `absl::btree_multiset<>` -// -// These B-tree types are similar to the corresponding types in the STL -// (`std::set` and `std::multiset`) and generally conform to the STL interfaces -// of those types. However, because they are implemented using B-trees, they -// are more efficient in most situations. -// -// Unlike `std::set` and `std::multiset`, which are commonly implemented using -// red-black tree nodes, B-tree sets use more generic B-tree nodes able to hold -// multiple values per node. Holding multiple values per node often makes -// B-tree sets perform better than their `std::set` counterparts, because -// multiple entries can be checked within the same cache hit. -// -// However, these types should not be considered drop-in replacements for -// `std::set` and `std::multiset` as there are some API differences, which are -// noted in this header file. -// -// Importantly, insertions and deletions may invalidate outstanding iterators, -// pointers, and references to elements. Such invalidations are typically only -// an issue if insertion and deletion operations are interleaved with the use of -// more than one iterator, pointer, or reference simultaneously. For this -// reason, `insert()` and `erase()` return a valid iterator at the current -// position. - -#ifndef ABSL_CONTAINER_BTREE_SET_H_ -#define ABSL_CONTAINER_BTREE_SET_H_ - -#include "absl/container/internal/btree.h" // IWYU pragma: export -#include "absl/container/internal/btree_container.h" // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::btree_set<> -// -// An `absl::btree_set<K>` is an ordered associative container of unique key -// values designed to be a more efficient replacement for `std::set` (in most -// cases). -// -// Keys are sorted using an (optional) comparison function, which defaults to -// `std::less<K>`. -// -// An `absl::btree_set<K>` uses a default allocator of `std::allocator<K>` to -// allocate (and deallocate) nodes, and construct and destruct values within -// those nodes. You may instead specify a custom allocator `A` (which in turn -// requires specifying a custom comparator `C`) as in -// `absl::btree_set<K, C, A>`. -// -template <typename Key, typename Compare = std::less<Key>, - typename Alloc = std::allocator<Key>> -class btree_set - : public container_internal::btree_set_container< - container_internal::btree<container_internal::set_params< - Key, Compare, Alloc, /*TargetNodeSize=*/256, - /*Multi=*/false>>> { - using Base = typename btree_set::btree_set_container; - - public: - // Constructors and Assignment Operators - // - // A `btree_set` supports the same overload set as `std::set` - // for construction and assignment: - // - // * Default constructor - // - // absl::btree_set<std::string> set1; - // - // * Initializer List constructor - // - // absl::btree_set<std::string> set2 = - // {{"huey"}, {"dewey"}, {"louie"},}; - // - // * Copy constructor - // - // absl::btree_set<std::string> set3(set2); - // - // * Copy assignment operator - // - // absl::btree_set<std::string> set4; - // set4 = set3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::btree_set<std::string> set5(std::move(set4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::btree_set<std::string> set6; - // set6 = std::move(set5); - // - // * Range constructor - // - // std::vector<std::string> v = {"a", "b"}; - // absl::btree_set<std::string> set7(v.begin(), v.end()); - btree_set() {} - using Base::Base; - - // btree_set::begin() - // - // Returns an iterator to the beginning of the `btree_set`. - using Base::begin; - - // btree_set::cbegin() - // - // Returns a const iterator to the beginning of the `btree_set`. - using Base::cbegin; - - // btree_set::end() - // - // Returns an iterator to the end of the `btree_set`. - using Base::end; - - // btree_set::cend() - // - // Returns a const iterator to the end of the `btree_set`. - using Base::cend; - - // btree_set::empty() - // - // Returns whether or not the `btree_set` is empty. - using Base::empty; - - // btree_set::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `btree_set` under current memory constraints. This value can be thought - // of as the largest value of `std::distance(begin(), end())` for a - // `btree_set<Key>`. - using Base::max_size; - - // btree_set::size() - // - // Returns the number of elements currently within the `btree_set`. - using Base::size; - - // btree_set::clear() - // - // Removes all elements from the `btree_set`. Invalidates any references, - // pointers, or iterators referring to contained elements. - using Base::clear; - - // btree_set::erase() - // - // Erases elements within the `btree_set`. Overloads are listed below. - // - // iterator erase(iterator position): - // iterator erase(const_iterator position): - // - // Erases the element at `position` of the `btree_set`, returning - // the iterator pointing to the element after the one that was erased - // (or end() if none exists). - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning - // the iterator pointing to the element after the interval that was erased - // (or end() if none exists). - // - // template <typename K> size_type erase(const K& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // btree_set::insert() - // - // Inserts an element of the specified value into the `btree_set`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If an insertion - // occurs, any references, pointers, or iterators are invalidated. - // Overloads are listed below. - // - // std::pair<iterator,bool> insert(const value_type& value): - // - // Inserts a value into the `btree_set`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a bool denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(value_type&& value): - // - // Inserts a moveable value into the `btree_set`. Returns a pair - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a bool denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const value_type& value): - // iterator insert(const_iterator hint, value_type&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - using Base::insert; - - // btree_set::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_set`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. - using Base::emplace; - - // btree_set::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_set`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If an insertion occurs, any references, pointers, or iterators are - // invalidated. - using Base::emplace_hint; - - // btree_set::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // template <typename K> node_type extract(const K& k): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `btree_set` - // does not contain an element with a matching key, this function returns an - // empty node handle. - // - // NOTE: In this context, `node_type` refers to the C++17 concept of a - // move-only type that owns and provides access to the elements in associative - // containers (https://en.cppreference.com/w/cpp/container/node_handle). - // It does NOT refer to the data layout of the underlying btree. - using Base::extract; - - // btree_set::merge() - // - // Extracts elements from a given `source` btree_set into this - // `btree_set`. If the destination `btree_set` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // btree_set::swap(btree_set& other) - // - // Exchanges the contents of this `btree_set` with those of the `other` - // btree_set, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `btree_set` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - using Base::swap; - - // btree_set::contains() - // - // template <typename K> bool contains(const K& key) const: - // - // Determines whether an element comparing equal to the given `key` exists - // within the `btree_set`, returning `true` if so or `false` otherwise. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::contains; - - // btree_set::count() - // - // template <typename K> size_type count(const K& key) const: - // - // Returns the number of elements comparing equal to the given `key` within - // the `btree_set`. Note that this function will return either `1` or `0` - // since duplicate elements are not allowed within a `btree_set`. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::count; - - // btree_set::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `btree_set`. - using Base::equal_range; - - // btree_set::find() - // - // template <typename K> iterator find(const K& key): - // template <typename K> const_iterator find(const K& key) const: - // - // Finds an element with the passed `key` within the `btree_set`. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::find; - - // btree_set::get_allocator() - // - // Returns the allocator function associated with this `btree_set`. - using Base::get_allocator; - - // btree_set::key_comp(); - // - // Returns the key comparator associated with this `btree_set`. - using Base::key_comp; - - // btree_set::value_comp(); - // - // Returns the value comparator associated with this `btree_set`. The keys to - // sort the elements are the values themselves, therefore `value_comp` and its - // sibling member function `key_comp` are equivalent. - using Base::value_comp; -}; - -// absl::swap(absl::btree_set<>, absl::btree_set<>) -// -// Swaps the contents of two `absl::btree_set` containers. -template <typename K, typename C, typename A> -void swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) { - return x.swap(y); -} - -// absl::erase_if(absl::btree_set<>, Pred) -// -// Erases all elements that satisfy the predicate pred from the container. -template <typename K, typename C, typename A, typename Pred> -void erase_if(btree_set<K, C, A> &set, Pred pred) { - for (auto it = set.begin(); it != set.end();) { - if (pred(*it)) { - it = set.erase(it); - } else { - ++it; - } - } -} - -// absl::btree_multiset<> -// -// An `absl::btree_multiset<K>` is an ordered associative container of -// keys and associated values designed to be a more efficient replacement -// for `std::multiset` (in most cases). Unlike `absl::btree_set`, a B-tree -// multiset allows equivalent elements. -// -// Keys are sorted using an (optional) comparison function, which defaults to -// `std::less<K>`. -// -// An `absl::btree_multiset<K>` uses a default allocator of `std::allocator<K>` -// to allocate (and deallocate) nodes, and construct and destruct values within -// those nodes. You may instead specify a custom allocator `A` (which in turn -// requires specifying a custom comparator `C`) as in -// `absl::btree_multiset<K, C, A>`. -// -template <typename Key, typename Compare = std::less<Key>, - typename Alloc = std::allocator<Key>> -class btree_multiset - : public container_internal::btree_multiset_container< - container_internal::btree<container_internal::set_params< - Key, Compare, Alloc, /*TargetNodeSize=*/256, - /*Multi=*/true>>> { - using Base = typename btree_multiset::btree_multiset_container; - - public: - // Constructors and Assignment Operators - // - // A `btree_multiset` supports the same overload set as `std::set` - // for construction and assignment: - // - // * Default constructor - // - // absl::btree_multiset<std::string> set1; - // - // * Initializer List constructor - // - // absl::btree_multiset<std::string> set2 = - // {{"huey"}, {"dewey"}, {"louie"},}; - // - // * Copy constructor - // - // absl::btree_multiset<std::string> set3(set2); - // - // * Copy assignment operator - // - // absl::btree_multiset<std::string> set4; - // set4 = set3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::btree_multiset<std::string> set5(std::move(set4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::btree_multiset<std::string> set6; - // set6 = std::move(set5); - // - // * Range constructor - // - // std::vector<std::string> v = {"a", "b"}; - // absl::btree_multiset<std::string> set7(v.begin(), v.end()); - btree_multiset() {} - using Base::Base; - - // btree_multiset::begin() - // - // Returns an iterator to the beginning of the `btree_multiset`. - using Base::begin; - - // btree_multiset::cbegin() - // - // Returns a const iterator to the beginning of the `btree_multiset`. - using Base::cbegin; - - // btree_multiset::end() - // - // Returns an iterator to the end of the `btree_multiset`. - using Base::end; - - // btree_multiset::cend() - // - // Returns a const iterator to the end of the `btree_multiset`. - using Base::cend; - - // btree_multiset::empty() - // - // Returns whether or not the `btree_multiset` is empty. - using Base::empty; - - // btree_multiset::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `btree_multiset` under current memory constraints. This value can be - // thought of as the largest value of `std::distance(begin(), end())` for a - // `btree_multiset<Key>`. - using Base::max_size; - - // btree_multiset::size() - // - // Returns the number of elements currently within the `btree_multiset`. - using Base::size; - - // btree_multiset::clear() - // - // Removes all elements from the `btree_multiset`. Invalidates any references, - // pointers, or iterators referring to contained elements. - using Base::clear; - - // btree_multiset::erase() - // - // Erases elements within the `btree_multiset`. Overloads are listed below. - // - // iterator erase(iterator position): - // iterator erase(const_iterator position): - // - // Erases the element at `position` of the `btree_multiset`, returning - // the iterator pointing to the element after the one that was erased - // (or end() if none exists). - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning - // the iterator pointing to the element after the interval that was erased - // (or end() if none exists). - // - // template <typename K> size_type erase(const K& key): - // - // Erases the elements matching the key, if any exist, returning the - // number of elements erased. - using Base::erase; - - // btree_multiset::insert() - // - // Inserts an element of the specified value into the `btree_multiset`, - // returning an iterator pointing to the newly inserted element. - // Any references, pointers, or iterators are invalidated. Overloads are - // listed below. - // - // iterator insert(const value_type& value): - // - // Inserts a value into the `btree_multiset`, returning an iterator to the - // inserted element. - // - // iterator insert(value_type&& value): - // - // Inserts a moveable value into the `btree_multiset`, returning an iterator - // to the inserted element. - // - // iterator insert(const_iterator hint, const value_type& value): - // iterator insert(const_iterator hint, value_type&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - using Base::insert; - - // btree_multiset::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_multiset`. Any references, pointers, or iterators are - // invalidated. - using Base::emplace; - - // btree_multiset::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `btree_multiset`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search. - // - // Any references, pointers, or iterators are invalidated. - using Base::emplace_hint; - - // btree_multiset::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // template <typename K> node_type extract(const K& k): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `btree_multiset` - // does not contain an element with a matching key, this function returns an - // empty node handle. - // - // NOTE: In this context, `node_type` refers to the C++17 concept of a - // move-only type that owns and provides access to the elements in associative - // containers (https://en.cppreference.com/w/cpp/container/node_handle). - // It does NOT refer to the data layout of the underlying btree. - using Base::extract; - - // btree_multiset::merge() - // - // Extracts elements from a given `source` btree_multiset into this - // `btree_multiset`. If the destination `btree_multiset` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // btree_multiset::swap(btree_multiset& other) - // - // Exchanges the contents of this `btree_multiset` with those of the `other` - // btree_multiset, avoiding invocation of any move, copy, or swap operations - // on individual elements. - // - // All iterators and references on the `btree_multiset` remain valid, - // excepting for the past-the-end iterator, which is invalidated. - using Base::swap; - - // btree_multiset::contains() - // - // template <typename K> bool contains(const K& key) const: - // - // Determines whether an element comparing equal to the given `key` exists - // within the `btree_multiset`, returning `true` if so or `false` otherwise. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::contains; - - // btree_multiset::count() - // - // template <typename K> size_type count(const K& key) const: - // - // Returns the number of elements comparing equal to the given `key` within - // the `btree_multiset`. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::count; - - // btree_multiset::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `btree_multiset`. - using Base::equal_range; - - // btree_multiset::find() - // - // template <typename K> iterator find(const K& key): - // template <typename K> const_iterator find(const K& key) const: - // - // Finds an element with the passed `key` within the `btree_multiset`. - // - // Supports heterogeneous lookup, provided that the set is provided a - // compatible heterogeneous comparator. - using Base::find; - - // btree_multiset::get_allocator() - // - // Returns the allocator function associated with this `btree_multiset`. - using Base::get_allocator; - - // btree_multiset::key_comp(); - // - // Returns the key comparator associated with this `btree_multiset`. - using Base::key_comp; - - // btree_multiset::value_comp(); - // - // Returns the value comparator associated with this `btree_multiset`. The - // keys to sort the elements are the values themselves, therefore `value_comp` - // and its sibling member function `key_comp` are equivalent. - using Base::value_comp; -}; - -// absl::swap(absl::btree_multiset<>, absl::btree_multiset<>) -// -// Swaps the contents of two `absl::btree_multiset` containers. -template <typename K, typename C, typename A> -void swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) { - return x.swap(y); -} - -// absl::erase_if(absl::btree_multiset<>, Pred) -// -// Erases all elements that satisfy the predicate pred from the container. -template <typename K, typename C, typename A, typename Pred> -void erase_if(btree_multiset<K, C, A> &set, Pred pred) { - for (auto it = set.begin(); it != set.end();) { - if (pred(*it)) { - it = set.erase(it); - } else { - ++it; - } - } -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_BTREE_SET_H_ diff --git a/third_party/abseil_cpp/absl/container/btree_test.cc b/third_party/abseil_cpp/absl/container/btree_test.cc deleted file mode 100644 index 9b1b6436c7ca..000000000000 --- a/third_party/abseil_cpp/absl/container/btree_test.cc +++ /dev/null @@ -1,2827 +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/btree_test.h" - -#include <cstdint> -#include <limits> -#include <map> -#include <memory> -#include <stdexcept> -#include <string> -#include <type_traits> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/container/btree_map.h" -#include "absl/container/btree_set.h" -#include "absl/container/internal/counting_allocator.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/flags/flag.h" -#include "absl/hash/hash_testing.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" -#include "absl/types/compare.h" - -ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests"); - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::absl::test_internal::CopyableMovableInstance; -using ::absl::test_internal::InstanceTracker; -using ::absl::test_internal::MovableOnlyInstance; -using ::testing::ElementsAre; -using ::testing::ElementsAreArray; -using ::testing::IsEmpty; -using ::testing::IsNull; -using ::testing::Pair; -using ::testing::SizeIs; - -template <typename T, typename U> -void CheckPairEquals(const T &x, const U &y) { - ABSL_INTERNAL_CHECK(x == y, "Values are unequal."); -} - -template <typename T, typename U, typename V, typename W> -void CheckPairEquals(const std::pair<T, U> &x, const std::pair<V, W> &y) { - CheckPairEquals(x.first, y.first); - CheckPairEquals(x.second, y.second); -} -} // namespace - -// The base class for a sorted associative container checker. TreeType is the -// container type to check and CheckerType is the container type to check -// against. TreeType is expected to be btree_{set,map,multiset,multimap} and -// CheckerType is expected to be {set,map,multiset,multimap}. -template <typename TreeType, typename CheckerType> -class base_checker { - public: - using key_type = typename TreeType::key_type; - using value_type = typename TreeType::value_type; - using key_compare = typename TreeType::key_compare; - using pointer = typename TreeType::pointer; - using const_pointer = typename TreeType::const_pointer; - using reference = typename TreeType::reference; - using const_reference = typename TreeType::const_reference; - using size_type = typename TreeType::size_type; - using difference_type = typename TreeType::difference_type; - using iterator = typename TreeType::iterator; - using const_iterator = typename TreeType::const_iterator; - using reverse_iterator = typename TreeType::reverse_iterator; - using const_reverse_iterator = typename TreeType::const_reverse_iterator; - - public: - base_checker() : const_tree_(tree_) {} - base_checker(const base_checker &other) - : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {} - template <typename InputIterator> - base_checker(InputIterator b, InputIterator e) - : tree_(b, e), const_tree_(tree_), checker_(b, e) {} - - iterator begin() { return tree_.begin(); } - const_iterator begin() const { return tree_.begin(); } - iterator end() { return tree_.end(); } - const_iterator end() const { return tree_.end(); } - reverse_iterator rbegin() { return tree_.rbegin(); } - const_reverse_iterator rbegin() const { return tree_.rbegin(); } - reverse_iterator rend() { return tree_.rend(); } - const_reverse_iterator rend() const { return tree_.rend(); } - - template <typename IterType, typename CheckerIterType> - IterType iter_check(IterType tree_iter, CheckerIterType checker_iter) const { - if (tree_iter == tree_.end()) { - ABSL_INTERNAL_CHECK(checker_iter == checker_.end(), - "Checker iterator not at end."); - } else { - CheckPairEquals(*tree_iter, *checker_iter); - } - return tree_iter; - } - template <typename IterType, typename CheckerIterType> - IterType riter_check(IterType tree_iter, CheckerIterType checker_iter) const { - if (tree_iter == tree_.rend()) { - ABSL_INTERNAL_CHECK(checker_iter == checker_.rend(), - "Checker iterator not at rend."); - } else { - CheckPairEquals(*tree_iter, *checker_iter); - } - return tree_iter; - } - void value_check(const value_type &v) { - typename KeyOfValue<typename TreeType::key_type, - typename TreeType::value_type>::type key_of_value; - const key_type &key = key_of_value(v); - CheckPairEquals(*find(key), v); - lower_bound(key); - upper_bound(key); - equal_range(key); - contains(key); - count(key); - } - void erase_check(const key_type &key) { - EXPECT_FALSE(tree_.contains(key)); - EXPECT_EQ(tree_.find(key), const_tree_.end()); - EXPECT_FALSE(const_tree_.contains(key)); - EXPECT_EQ(const_tree_.find(key), tree_.end()); - EXPECT_EQ(tree_.equal_range(key).first, - const_tree_.equal_range(key).second); - } - - iterator lower_bound(const key_type &key) { - return iter_check(tree_.lower_bound(key), checker_.lower_bound(key)); - } - const_iterator lower_bound(const key_type &key) const { - return iter_check(tree_.lower_bound(key), checker_.lower_bound(key)); - } - iterator upper_bound(const key_type &key) { - return iter_check(tree_.upper_bound(key), checker_.upper_bound(key)); - } - const_iterator upper_bound(const key_type &key) const { - return iter_check(tree_.upper_bound(key), checker_.upper_bound(key)); - } - std::pair<iterator, iterator> equal_range(const key_type &key) { - std::pair<typename CheckerType::iterator, typename CheckerType::iterator> - checker_res = checker_.equal_range(key); - std::pair<iterator, iterator> tree_res = tree_.equal_range(key); - iter_check(tree_res.first, checker_res.first); - iter_check(tree_res.second, checker_res.second); - return tree_res; - } - std::pair<const_iterator, const_iterator> equal_range( - const key_type &key) const { - std::pair<typename CheckerType::const_iterator, - typename CheckerType::const_iterator> - checker_res = checker_.equal_range(key); - std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key); - iter_check(tree_res.first, checker_res.first); - iter_check(tree_res.second, checker_res.second); - return tree_res; - } - iterator find(const key_type &key) { - return iter_check(tree_.find(key), checker_.find(key)); - } - const_iterator find(const key_type &key) const { - return iter_check(tree_.find(key), checker_.find(key)); - } - bool contains(const key_type &key) const { return find(key) != end(); } - size_type count(const key_type &key) const { - size_type res = checker_.count(key); - EXPECT_EQ(res, tree_.count(key)); - return res; - } - - base_checker &operator=(const base_checker &other) { - tree_ = other.tree_; - checker_ = other.checker_; - return *this; - } - - int erase(const key_type &key) { - int size = tree_.size(); - int res = checker_.erase(key); - EXPECT_EQ(res, tree_.count(key)); - EXPECT_EQ(res, tree_.erase(key)); - EXPECT_EQ(tree_.count(key), 0); - EXPECT_EQ(tree_.size(), size - res); - erase_check(key); - return res; - } - iterator erase(iterator iter) { - key_type key = iter.key(); - int size = tree_.size(); - int count = tree_.count(key); - auto checker_iter = checker_.lower_bound(key); - for (iterator tmp(tree_.lower_bound(key)); tmp != iter; ++tmp) { - ++checker_iter; - } - auto checker_next = checker_iter; - ++checker_next; - checker_.erase(checker_iter); - iter = tree_.erase(iter); - EXPECT_EQ(tree_.size(), checker_.size()); - EXPECT_EQ(tree_.size(), size - 1); - EXPECT_EQ(tree_.count(key), count - 1); - if (count == 1) { - erase_check(key); - } - return iter_check(iter, checker_next); - } - - void erase(iterator begin, iterator end) { - int size = tree_.size(); - int count = std::distance(begin, end); - auto checker_begin = checker_.lower_bound(begin.key()); - for (iterator tmp(tree_.lower_bound(begin.key())); tmp != begin; ++tmp) { - ++checker_begin; - } - auto checker_end = - end == tree_.end() ? checker_.end() : checker_.lower_bound(end.key()); - if (end != tree_.end()) { - for (iterator tmp(tree_.lower_bound(end.key())); tmp != end; ++tmp) { - ++checker_end; - } - } - const auto checker_ret = checker_.erase(checker_begin, checker_end); - const auto tree_ret = tree_.erase(begin, end); - EXPECT_EQ(std::distance(checker_.begin(), checker_ret), - std::distance(tree_.begin(), tree_ret)); - EXPECT_EQ(tree_.size(), checker_.size()); - EXPECT_EQ(tree_.size(), size - count); - } - - void clear() { - tree_.clear(); - checker_.clear(); - } - void swap(base_checker &other) { - tree_.swap(other.tree_); - checker_.swap(other.checker_); - } - - void verify() const { - tree_.verify(); - EXPECT_EQ(tree_.size(), checker_.size()); - - // Move through the forward iterators using increment. - auto checker_iter = checker_.begin(); - const_iterator tree_iter(tree_.begin()); - for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) { - CheckPairEquals(*tree_iter, *checker_iter); - } - - // Move through the forward iterators using decrement. - for (int n = tree_.size() - 1; n >= 0; --n) { - iter_check(tree_iter, checker_iter); - --tree_iter; - --checker_iter; - } - EXPECT_EQ(tree_iter, tree_.begin()); - EXPECT_EQ(checker_iter, checker_.begin()); - - // Move through the reverse iterators using increment. - auto checker_riter = checker_.rbegin(); - const_reverse_iterator tree_riter(tree_.rbegin()); - for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) { - CheckPairEquals(*tree_riter, *checker_riter); - } - - // Move through the reverse iterators using decrement. - for (int n = tree_.size() - 1; n >= 0; --n) { - riter_check(tree_riter, checker_riter); - --tree_riter; - --checker_riter; - } - EXPECT_EQ(tree_riter, tree_.rbegin()); - EXPECT_EQ(checker_riter, checker_.rbegin()); - } - - const TreeType &tree() const { return tree_; } - - size_type size() const { - EXPECT_EQ(tree_.size(), checker_.size()); - return tree_.size(); - } - size_type max_size() const { return tree_.max_size(); } - bool empty() const { - EXPECT_EQ(tree_.empty(), checker_.empty()); - return tree_.empty(); - } - - protected: - TreeType tree_; - const TreeType &const_tree_; - CheckerType checker_; -}; - -namespace { -// A checker for unique sorted associative containers. TreeType is expected to -// be btree_{set,map} and CheckerType is expected to be {set,map}. -template <typename TreeType, typename CheckerType> -class unique_checker : public base_checker<TreeType, CheckerType> { - using super_type = base_checker<TreeType, CheckerType>; - - public: - using iterator = typename super_type::iterator; - using value_type = typename super_type::value_type; - - public: - unique_checker() : super_type() {} - unique_checker(const unique_checker &other) : super_type(other) {} - template <class InputIterator> - unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {} - unique_checker &operator=(const unique_checker &) = default; - - // Insertion routines. - std::pair<iterator, bool> insert(const value_type &v) { - int size = this->tree_.size(); - std::pair<typename CheckerType::iterator, bool> checker_res = - this->checker_.insert(v); - std::pair<iterator, bool> tree_res = this->tree_.insert(v); - CheckPairEquals(*tree_res.first, *checker_res.first); - EXPECT_EQ(tree_res.second, checker_res.second); - EXPECT_EQ(this->tree_.size(), this->checker_.size()); - EXPECT_EQ(this->tree_.size(), size + tree_res.second); - return tree_res; - } - iterator insert(iterator position, const value_type &v) { - int size = this->tree_.size(); - std::pair<typename CheckerType::iterator, bool> checker_res = - this->checker_.insert(v); - iterator tree_res = this->tree_.insert(position, v); - CheckPairEquals(*tree_res, *checker_res.first); - EXPECT_EQ(this->tree_.size(), this->checker_.size()); - EXPECT_EQ(this->tree_.size(), size + checker_res.second); - return tree_res; - } - template <typename InputIterator> - void insert(InputIterator b, InputIterator e) { - for (; b != e; ++b) { - insert(*b); - } - } -}; - -// A checker for multiple sorted associative containers. TreeType is expected -// to be btree_{multiset,multimap} and CheckerType is expected to be -// {multiset,multimap}. -template <typename TreeType, typename CheckerType> -class multi_checker : public base_checker<TreeType, CheckerType> { - using super_type = base_checker<TreeType, CheckerType>; - - public: - using iterator = typename super_type::iterator; - using value_type = typename super_type::value_type; - - public: - multi_checker() : super_type() {} - multi_checker(const multi_checker &other) : super_type(other) {} - template <class InputIterator> - multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {} - multi_checker &operator=(const multi_checker &) = default; - - // Insertion routines. - iterator insert(const value_type &v) { - int size = this->tree_.size(); - auto checker_res = this->checker_.insert(v); - iterator tree_res = this->tree_.insert(v); - CheckPairEquals(*tree_res, *checker_res); - EXPECT_EQ(this->tree_.size(), this->checker_.size()); - EXPECT_EQ(this->tree_.size(), size + 1); - return tree_res; - } - iterator insert(iterator position, const value_type &v) { - int size = this->tree_.size(); - auto checker_res = this->checker_.insert(v); - iterator tree_res = this->tree_.insert(position, v); - CheckPairEquals(*tree_res, *checker_res); - EXPECT_EQ(this->tree_.size(), this->checker_.size()); - EXPECT_EQ(this->tree_.size(), size + 1); - return tree_res; - } - template <typename InputIterator> - void insert(InputIterator b, InputIterator e) { - for (; b != e; ++b) { - insert(*b); - } - } -}; - -template <typename T, typename V> -void DoTest(const char *name, T *b, const std::vector<V> &values) { - typename KeyOfValue<typename T::key_type, V>::type key_of_value; - - T &mutable_b = *b; - const T &const_b = *b; - - // Test insert. - for (int i = 0; i < values.size(); ++i) { - mutable_b.insert(values[i]); - mutable_b.value_check(values[i]); - } - ASSERT_EQ(mutable_b.size(), values.size()); - - const_b.verify(); - - // Test copy constructor. - T b_copy(const_b); - EXPECT_EQ(b_copy.size(), const_b.size()); - for (int i = 0; i < values.size(); ++i) { - CheckPairEquals(*b_copy.find(key_of_value(values[i])), values[i]); - } - - // Test range constructor. - T b_range(const_b.begin(), const_b.end()); - EXPECT_EQ(b_range.size(), const_b.size()); - for (int i = 0; i < values.size(); ++i) { - CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]); - } - - // Test range insertion for values that already exist. - b_range.insert(b_copy.begin(), b_copy.end()); - b_range.verify(); - - // Test range insertion for new values. - b_range.clear(); - b_range.insert(b_copy.begin(), b_copy.end()); - EXPECT_EQ(b_range.size(), b_copy.size()); - for (int i = 0; i < values.size(); ++i) { - CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]); - } - - // Test assignment to self. Nothing should change. - b_range.operator=(b_range); - EXPECT_EQ(b_range.size(), b_copy.size()); - - // Test assignment of new values. - b_range.clear(); - b_range = b_copy; - EXPECT_EQ(b_range.size(), b_copy.size()); - - // Test swap. - b_range.clear(); - b_range.swap(b_copy); - EXPECT_EQ(b_copy.size(), 0); - EXPECT_EQ(b_range.size(), const_b.size()); - for (int i = 0; i < values.size(); ++i) { - CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]); - } - b_range.swap(b_copy); - - // Test non-member function swap. - swap(b_range, b_copy); - EXPECT_EQ(b_copy.size(), 0); - EXPECT_EQ(b_range.size(), const_b.size()); - for (int i = 0; i < values.size(); ++i) { - CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]); - } - swap(b_range, b_copy); - - // Test erase via values. - for (int i = 0; i < values.size(); ++i) { - mutable_b.erase(key_of_value(values[i])); - // Erasing a non-existent key should have no effect. - ASSERT_EQ(mutable_b.erase(key_of_value(values[i])), 0); - } - - const_b.verify(); - EXPECT_EQ(const_b.size(), 0); - - // Test erase via iterators. - mutable_b = b_copy; - for (int i = 0; i < values.size(); ++i) { - mutable_b.erase(mutable_b.find(key_of_value(values[i]))); - } - - const_b.verify(); - EXPECT_EQ(const_b.size(), 0); - - // Test insert with hint. - for (int i = 0; i < values.size(); i++) { - mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]); - } - - const_b.verify(); - - // Test range erase. - mutable_b.erase(mutable_b.begin(), mutable_b.end()); - EXPECT_EQ(mutable_b.size(), 0); - const_b.verify(); - - // First half. - mutable_b = b_copy; - typename T::iterator mutable_iter_end = mutable_b.begin(); - for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end; - mutable_b.erase(mutable_b.begin(), mutable_iter_end); - EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2); - const_b.verify(); - - // Second half. - mutable_b = b_copy; - typename T::iterator mutable_iter_begin = mutable_b.begin(); - for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin; - mutable_b.erase(mutable_iter_begin, mutable_b.end()); - EXPECT_EQ(mutable_b.size(), values.size() / 2); - const_b.verify(); - - // Second quarter. - mutable_b = b_copy; - mutable_iter_begin = mutable_b.begin(); - for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin; - mutable_iter_end = mutable_iter_begin; - for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end; - mutable_b.erase(mutable_iter_begin, mutable_iter_end); - EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4); - const_b.verify(); - - mutable_b.clear(); -} - -template <typename T> -void ConstTest() { - using value_type = typename T::value_type; - typename KeyOfValue<typename T::key_type, value_type>::type key_of_value; - - T mutable_b; - const T &const_b = mutable_b; - - // Insert a single value into the container and test looking it up. - value_type value = Generator<value_type>(2)(2); - mutable_b.insert(value); - EXPECT_TRUE(mutable_b.contains(key_of_value(value))); - EXPECT_NE(mutable_b.find(key_of_value(value)), const_b.end()); - EXPECT_TRUE(const_b.contains(key_of_value(value))); - EXPECT_NE(const_b.find(key_of_value(value)), mutable_b.end()); - EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value); - EXPECT_EQ(const_b.upper_bound(key_of_value(value)), const_b.end()); - EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value); - - // We can only create a non-const iterator from a non-const container. - typename T::iterator mutable_iter(mutable_b.begin()); - EXPECT_EQ(mutable_iter, const_b.begin()); - EXPECT_NE(mutable_iter, const_b.end()); - EXPECT_EQ(const_b.begin(), mutable_iter); - EXPECT_NE(const_b.end(), mutable_iter); - typename T::reverse_iterator mutable_riter(mutable_b.rbegin()); - EXPECT_EQ(mutable_riter, const_b.rbegin()); - EXPECT_NE(mutable_riter, const_b.rend()); - EXPECT_EQ(const_b.rbegin(), mutable_riter); - EXPECT_NE(const_b.rend(), mutable_riter); - - // We can create a const iterator from a non-const iterator. - typename T::const_iterator const_iter(mutable_iter); - EXPECT_EQ(const_iter, mutable_b.begin()); - EXPECT_NE(const_iter, mutable_b.end()); - EXPECT_EQ(mutable_b.begin(), const_iter); - EXPECT_NE(mutable_b.end(), const_iter); - typename T::const_reverse_iterator const_riter(mutable_riter); - EXPECT_EQ(const_riter, mutable_b.rbegin()); - EXPECT_NE(const_riter, mutable_b.rend()); - EXPECT_EQ(mutable_b.rbegin(), const_riter); - EXPECT_NE(mutable_b.rend(), const_riter); - - // Make sure various methods can be invoked on a const container. - const_b.verify(); - ASSERT_TRUE(!const_b.empty()); - EXPECT_EQ(const_b.size(), 1); - EXPECT_GT(const_b.max_size(), 0); - EXPECT_TRUE(const_b.contains(key_of_value(value))); - EXPECT_EQ(const_b.count(key_of_value(value)), 1); -} - -template <typename T, typename C> -void BtreeTest() { - ConstTest<T>(); - - using V = typename remove_pair_const<typename T::value_type>::type; - const std::vector<V> random_values = GenerateValuesWithSeed<V>( - absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values), - testing::GTEST_FLAG(random_seed)); - - unique_checker<T, C> container; - - // Test key insertion/deletion in sorted order. - std::vector<V> sorted_values(random_values); - std::sort(sorted_values.begin(), sorted_values.end()); - DoTest("sorted: ", &container, sorted_values); - - // Test key insertion/deletion in reverse sorted order. - std::reverse(sorted_values.begin(), sorted_values.end()); - DoTest("rsorted: ", &container, sorted_values); - - // Test key insertion/deletion in random order. - DoTest("random: ", &container, random_values); -} - -template <typename T, typename C> -void BtreeMultiTest() { - ConstTest<T>(); - - using V = typename remove_pair_const<typename T::value_type>::type; - const std::vector<V> random_values = GenerateValuesWithSeed<V>( - absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values), - testing::GTEST_FLAG(random_seed)); - - multi_checker<T, C> container; - - // Test keys in sorted order. - std::vector<V> sorted_values(random_values); - std::sort(sorted_values.begin(), sorted_values.end()); - DoTest("sorted: ", &container, sorted_values); - - // Test keys in reverse sorted order. - std::reverse(sorted_values.begin(), sorted_values.end()); - DoTest("rsorted: ", &container, sorted_values); - - // Test keys in random order. - DoTest("random: ", &container, random_values); - - // Test keys in random order w/ duplicates. - std::vector<V> duplicate_values(random_values); - duplicate_values.insert(duplicate_values.end(), random_values.begin(), - random_values.end()); - DoTest("duplicates:", &container, duplicate_values); - - // Test all identical keys. - std::vector<V> identical_values(100); - std::fill(identical_values.begin(), identical_values.end(), - Generator<V>(2)(2)); - DoTest("identical: ", &container, identical_values); -} - -template <typename T> -struct PropagatingCountingAlloc : public CountingAllocator<T> { - using propagate_on_container_copy_assignment = std::true_type; - using propagate_on_container_move_assignment = std::true_type; - using propagate_on_container_swap = std::true_type; - - using Base = CountingAllocator<T>; - using Base::Base; - - template <typename U> - explicit PropagatingCountingAlloc(const PropagatingCountingAlloc<U> &other) - : Base(other.bytes_used_) {} - - template <typename U> - struct rebind { - using other = PropagatingCountingAlloc<U>; - }; -}; - -template <typename T> -void BtreeAllocatorTest() { - using value_type = typename T::value_type; - - int64_t bytes1 = 0, bytes2 = 0; - PropagatingCountingAlloc<T> allocator1(&bytes1); - PropagatingCountingAlloc<T> allocator2(&bytes2); - Generator<value_type> generator(1000); - - // Test that we allocate properly aligned memory. If we don't, then Layout - // will assert fail. - auto unused1 = allocator1.allocate(1); - auto unused2 = allocator2.allocate(1); - - // Test copy assignment - { - T b1(typename T::key_compare(), allocator1); - T b2(typename T::key_compare(), allocator2); - - int64_t original_bytes1 = bytes1; - b1.insert(generator(0)); - EXPECT_GT(bytes1, original_bytes1); - - // This should propagate the allocator. - b1 = b2; - EXPECT_EQ(b1.size(), 0); - EXPECT_EQ(b2.size(), 0); - EXPECT_EQ(bytes1, original_bytes1); - - for (int i = 1; i < 1000; i++) { - b1.insert(generator(i)); - } - - // We should have allocated out of allocator2. - EXPECT_GT(bytes2, bytes1); - } - - // Test move assignment - { - T b1(typename T::key_compare(), allocator1); - T b2(typename T::key_compare(), allocator2); - - int64_t original_bytes1 = bytes1; - b1.insert(generator(0)); - EXPECT_GT(bytes1, original_bytes1); - - // This should propagate the allocator. - b1 = std::move(b2); - EXPECT_EQ(b1.size(), 0); - EXPECT_EQ(bytes1, original_bytes1); - - for (int i = 1; i < 1000; i++) { - b1.insert(generator(i)); - } - - // We should have allocated out of allocator2. - EXPECT_GT(bytes2, bytes1); - } - - // Test swap - { - T b1(typename T::key_compare(), allocator1); - T b2(typename T::key_compare(), allocator2); - - int64_t original_bytes1 = bytes1; - b1.insert(generator(0)); - EXPECT_GT(bytes1, original_bytes1); - - // This should swap the allocators. - swap(b1, b2); - EXPECT_EQ(b1.size(), 0); - EXPECT_EQ(b2.size(), 1); - EXPECT_GT(bytes1, original_bytes1); - - for (int i = 1; i < 1000; i++) { - b1.insert(generator(i)); - } - - // We should have allocated out of allocator2. - EXPECT_GT(bytes2, bytes1); - } - - allocator1.deallocate(unused1, 1); - allocator2.deallocate(unused2, 1); -} - -template <typename T> -void BtreeMapTest() { - using value_type = typename T::value_type; - using mapped_type = typename T::mapped_type; - - mapped_type m = Generator<mapped_type>(0)(0); - (void)m; - - T b; - - // Verify we can insert using operator[]. - for (int i = 0; i < 1000; i++) { - value_type v = Generator<value_type>(1000)(i); - b[v.first] = v.second; - } - EXPECT_EQ(b.size(), 1000); - - // Test whether we can use the "->" operator on iterators and - // reverse_iterators. This stresses the btree_map_params::pair_pointer - // mechanism. - EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first); - EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second); - EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first); - EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second); -} - -template <typename T> -void BtreeMultiMapTest() { - using mapped_type = typename T::mapped_type; - mapped_type m = Generator<mapped_type>(0)(0); - (void)m; -} - -template <typename K, int N = 256> -void SetTest() { - EXPECT_EQ( - sizeof(absl::btree_set<K>), - 2 * sizeof(void *) + sizeof(typename absl::btree_set<K>::size_type)); - using BtreeSet = absl::btree_set<K>; - using CountingBtreeSet = - absl::btree_set<K, std::less<K>, PropagatingCountingAlloc<K>>; - BtreeTest<BtreeSet, std::set<K>>(); - BtreeAllocatorTest<CountingBtreeSet>(); -} - -template <typename K, int N = 256> -void MapTest() { - EXPECT_EQ( - sizeof(absl::btree_map<K, K>), - 2 * sizeof(void *) + sizeof(typename absl::btree_map<K, K>::size_type)); - using BtreeMap = absl::btree_map<K, K>; - using CountingBtreeMap = - absl::btree_map<K, K, std::less<K>, - PropagatingCountingAlloc<std::pair<const K, K>>>; - BtreeTest<BtreeMap, std::map<K, K>>(); - BtreeAllocatorTest<CountingBtreeMap>(); - BtreeMapTest<BtreeMap>(); -} - -TEST(Btree, set_int32) { SetTest<int32_t>(); } -TEST(Btree, set_int64) { SetTest<int64_t>(); } -TEST(Btree, set_string) { SetTest<std::string>(); } -TEST(Btree, set_cord) { SetTest<absl::Cord>(); } -TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); } -TEST(Btree, map_int32) { MapTest<int32_t>(); } -TEST(Btree, map_int64) { MapTest<int64_t>(); } -TEST(Btree, map_string) { MapTest<std::string>(); } -TEST(Btree, map_cord) { MapTest<absl::Cord>(); } -TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); } - -template <typename K, int N = 256> -void MultiSetTest() { - EXPECT_EQ( - sizeof(absl::btree_multiset<K>), - 2 * sizeof(void *) + sizeof(typename absl::btree_multiset<K>::size_type)); - using BtreeMSet = absl::btree_multiset<K>; - using CountingBtreeMSet = - absl::btree_multiset<K, std::less<K>, PropagatingCountingAlloc<K>>; - BtreeMultiTest<BtreeMSet, std::multiset<K>>(); - BtreeAllocatorTest<CountingBtreeMSet>(); -} - -template <typename K, int N = 256> -void MultiMapTest() { - EXPECT_EQ(sizeof(absl::btree_multimap<K, K>), - 2 * sizeof(void *) + - sizeof(typename absl::btree_multimap<K, K>::size_type)); - using BtreeMMap = absl::btree_multimap<K, K>; - using CountingBtreeMMap = - absl::btree_multimap<K, K, std::less<K>, - PropagatingCountingAlloc<std::pair<const K, K>>>; - BtreeMultiTest<BtreeMMap, std::multimap<K, K>>(); - BtreeMultiMapTest<BtreeMMap>(); - BtreeAllocatorTest<CountingBtreeMMap>(); -} - -TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); } -TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); } -TEST(Btree, multiset_string) { MultiSetTest<std::string>(); } -TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); } -TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); } -TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); } -TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); } -TEST(Btree, multimap_string) { MultiMapTest<std::string>(); } -TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); } -TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); } - -struct CompareIntToString { - bool operator()(const std::string &a, const std::string &b) const { - return a < b; - } - bool operator()(const std::string &a, int b) const { - return a < absl::StrCat(b); - } - bool operator()(int a, const std::string &b) const { - return absl::StrCat(a) < b; - } - using is_transparent = void; -}; - -struct NonTransparentCompare { - template <typename T, typename U> - bool operator()(const T &t, const U &u) const { - // Treating all comparators as transparent can cause inefficiencies (see - // N3657 C++ proposal). Test that for comparators without 'is_transparent' - // alias (like this one), we do not attempt heterogeneous lookup. - EXPECT_TRUE((std::is_same<T, U>())); - return t < u; - } -}; - -template <typename T> -bool CanEraseWithEmptyBrace(T t, decltype(t.erase({})) *) { - return true; -} - -template <typename T> -bool CanEraseWithEmptyBrace(T, ...) { - return false; -} - -template <typename T> -void TestHeterogeneous(T table) { - auto lb = table.lower_bound("3"); - EXPECT_EQ(lb, table.lower_bound(3)); - EXPECT_NE(lb, table.lower_bound(4)); - EXPECT_EQ(lb, table.lower_bound({"3"})); - EXPECT_NE(lb, table.lower_bound({})); - - auto ub = table.upper_bound("3"); - EXPECT_EQ(ub, table.upper_bound(3)); - EXPECT_NE(ub, table.upper_bound(5)); - EXPECT_EQ(ub, table.upper_bound({"3"})); - EXPECT_NE(ub, table.upper_bound({})); - - auto er = table.equal_range("3"); - EXPECT_EQ(er, table.equal_range(3)); - EXPECT_NE(er, table.equal_range(4)); - EXPECT_EQ(er, table.equal_range({"3"})); - EXPECT_NE(er, table.equal_range({})); - - auto it = table.find("3"); - EXPECT_EQ(it, table.find(3)); - EXPECT_NE(it, table.find(4)); - EXPECT_EQ(it, table.find({"3"})); - EXPECT_NE(it, table.find({})); - - EXPECT_TRUE(table.contains(3)); - EXPECT_FALSE(table.contains(4)); - EXPECT_TRUE(table.count({"3"})); - EXPECT_FALSE(table.contains({})); - - EXPECT_EQ(1, table.count(3)); - EXPECT_EQ(0, table.count(4)); - EXPECT_EQ(1, table.count({"3"})); - EXPECT_EQ(0, table.count({})); - - auto copy = table; - copy.erase(3); - EXPECT_EQ(table.size() - 1, copy.size()); - copy.erase(4); - EXPECT_EQ(table.size() - 1, copy.size()); - copy.erase({"5"}); - EXPECT_EQ(table.size() - 2, copy.size()); - EXPECT_FALSE(CanEraseWithEmptyBrace(table, nullptr)); - - // Also run it with const T&. - if (std::is_class<T>()) TestHeterogeneous<const T &>(table); -} - -TEST(Btree, HeterogeneousLookup) { - TestHeterogeneous(btree_set<std::string, CompareIntToString>{"1", "3", "5"}); - TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{ - {"1", 1}, {"3", 3}, {"5", 5}}); - TestHeterogeneous( - btree_multiset<std::string, CompareIntToString>{"1", "3", "5"}); - TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{ - {"1", 1}, {"3", 3}, {"5", 5}}); - - // Only maps have .at() - btree_map<std::string, int, CompareIntToString> map{ - {"", -1}, {"1", 1}, {"3", 3}, {"5", 5}}; - EXPECT_EQ(1, map.at(1)); - EXPECT_EQ(3, map.at({"3"})); - EXPECT_EQ(-1, map.at({})); - const auto &cmap = map; - EXPECT_EQ(1, cmap.at(1)); - EXPECT_EQ(3, cmap.at({"3"})); - EXPECT_EQ(-1, cmap.at({})); -} - -TEST(Btree, NoHeterogeneousLookupWithoutAlias) { - using StringSet = absl::btree_set<std::string, NonTransparentCompare>; - StringSet s; - ASSERT_TRUE(s.insert("hello").second); - ASSERT_TRUE(s.insert("world").second); - EXPECT_TRUE(s.end() == s.find("blah")); - EXPECT_TRUE(s.begin() == s.lower_bound("hello")); - EXPECT_EQ(1, s.count("world")); - EXPECT_TRUE(s.contains("hello")); - EXPECT_TRUE(s.contains("world")); - EXPECT_FALSE(s.contains("blah")); - - using StringMultiSet = - absl::btree_multiset<std::string, NonTransparentCompare>; - StringMultiSet ms; - ms.insert("hello"); - ms.insert("world"); - ms.insert("world"); - EXPECT_TRUE(ms.end() == ms.find("blah")); - EXPECT_TRUE(ms.begin() == ms.lower_bound("hello")); - EXPECT_EQ(2, ms.count("world")); - EXPECT_TRUE(ms.contains("hello")); - EXPECT_TRUE(ms.contains("world")); - EXPECT_FALSE(ms.contains("blah")); -} - -TEST(Btree, DefaultTransparent) { - { - // `int` does not have a default transparent comparator. - // The input value is converted to key_type. - btree_set<int> s = {1}; - double d = 1.1; - EXPECT_EQ(s.begin(), s.find(d)); - EXPECT_TRUE(s.contains(d)); - } - - { - // `std::string` has heterogeneous support. - btree_set<std::string> s = {"A"}; - EXPECT_EQ(s.begin(), s.find(absl::string_view("A"))); - EXPECT_TRUE(s.contains(absl::string_view("A"))); - } -} - -class StringLike { - public: - StringLike() = default; - - StringLike(const char *s) : s_(s) { // NOLINT - ++constructor_calls_; - } - - bool operator<(const StringLike &a) const { return s_ < a.s_; } - - static void clear_constructor_call_count() { constructor_calls_ = 0; } - - static int constructor_calls() { return constructor_calls_; } - - private: - static int constructor_calls_; - std::string s_; -}; - -int StringLike::constructor_calls_ = 0; - -TEST(Btree, HeterogeneousLookupDoesntDegradePerformance) { - using StringSet = absl::btree_set<StringLike>; - StringSet s; - for (int i = 0; i < 100; ++i) { - ASSERT_TRUE(s.insert(absl::StrCat(i).c_str()).second); - } - StringLike::clear_constructor_call_count(); - s.find("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.contains("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.count("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.lower_bound("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.upper_bound("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.equal_range("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); - - StringLike::clear_constructor_call_count(); - s.erase("50"); - ASSERT_EQ(1, StringLike::constructor_calls()); -} - -// Verify that swapping btrees swaps the key comparison functors and that we can -// use non-default constructible comparators. -struct SubstringLess { - SubstringLess() = delete; - explicit SubstringLess(int length) : n(length) {} - bool operator()(const std::string &a, const std::string &b) const { - return absl::string_view(a).substr(0, n) < - absl::string_view(b).substr(0, n); - } - int n; -}; - -TEST(Btree, SwapKeyCompare) { - using SubstringSet = absl::btree_set<std::string, SubstringLess>; - SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type()); - SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type()); - - ASSERT_TRUE(s1.insert("a").second); - ASSERT_FALSE(s1.insert("aa").second); - - ASSERT_TRUE(s2.insert("a").second); - ASSERT_TRUE(s2.insert("aa").second); - ASSERT_FALSE(s2.insert("aaa").second); - - swap(s1, s2); - - ASSERT_TRUE(s1.insert("b").second); - ASSERT_TRUE(s1.insert("bb").second); - ASSERT_FALSE(s1.insert("bbb").second); - - ASSERT_TRUE(s2.insert("b").second); - ASSERT_FALSE(s2.insert("bb").second); -} - -TEST(Btree, UpperBoundRegression) { - // Regress a bug where upper_bound would default-construct a new key_compare - // instead of copying the existing one. - using SubstringSet = absl::btree_set<std::string, SubstringLess>; - SubstringSet my_set(SubstringLess(3)); - my_set.insert("aab"); - my_set.insert("abb"); - // We call upper_bound("aaa"). If this correctly uses the length 3 - // comparator, aaa < aab < abb, so we should get aab as the result. - // If it instead uses the default-constructed length 2 comparator, - // aa == aa < ab, so we'll get abb as our result. - SubstringSet::iterator it = my_set.upper_bound("aaa"); - ASSERT_TRUE(it != my_set.end()); - EXPECT_EQ("aab", *it); -} - -TEST(Btree, Comparison) { - const int kSetSize = 1201; - absl::btree_set<int64_t> my_set; - for (int i = 0; i < kSetSize; ++i) { - my_set.insert(i); - } - absl::btree_set<int64_t> my_set_copy(my_set); - EXPECT_TRUE(my_set_copy == my_set); - EXPECT_TRUE(my_set == my_set_copy); - EXPECT_FALSE(my_set_copy != my_set); - EXPECT_FALSE(my_set != my_set_copy); - - my_set.insert(kSetSize); - EXPECT_FALSE(my_set_copy == my_set); - EXPECT_FALSE(my_set == my_set_copy); - EXPECT_TRUE(my_set_copy != my_set); - EXPECT_TRUE(my_set != my_set_copy); - - my_set.erase(kSetSize - 1); - EXPECT_FALSE(my_set_copy == my_set); - EXPECT_FALSE(my_set == my_set_copy); - EXPECT_TRUE(my_set_copy != my_set); - EXPECT_TRUE(my_set != my_set_copy); - - absl::btree_map<std::string, int64_t> my_map; - for (int i = 0; i < kSetSize; ++i) { - my_map[std::string(i, 'a')] = i; - } - absl::btree_map<std::string, int64_t> my_map_copy(my_map); - EXPECT_TRUE(my_map_copy == my_map); - EXPECT_TRUE(my_map == my_map_copy); - EXPECT_FALSE(my_map_copy != my_map); - EXPECT_FALSE(my_map != my_map_copy); - - ++my_map_copy[std::string(7, 'a')]; - EXPECT_FALSE(my_map_copy == my_map); - EXPECT_FALSE(my_map == my_map_copy); - EXPECT_TRUE(my_map_copy != my_map); - EXPECT_TRUE(my_map != my_map_copy); - - my_map_copy = my_map; - my_map["hello"] = kSetSize; - EXPECT_FALSE(my_map_copy == my_map); - EXPECT_FALSE(my_map == my_map_copy); - EXPECT_TRUE(my_map_copy != my_map); - EXPECT_TRUE(my_map != my_map_copy); - - my_map.erase(std::string(kSetSize - 1, 'a')); - EXPECT_FALSE(my_map_copy == my_map); - EXPECT_FALSE(my_map == my_map_copy); - EXPECT_TRUE(my_map_copy != my_map); - EXPECT_TRUE(my_map != my_map_copy); -} - -TEST(Btree, RangeCtorSanity) { - std::vector<int> ivec; - ivec.push_back(1); - std::map<int, int> imap; - imap.insert(std::make_pair(1, 2)); - absl::btree_multiset<int> tmset(ivec.begin(), ivec.end()); - absl::btree_multimap<int, int> tmmap(imap.begin(), imap.end()); - absl::btree_set<int> tset(ivec.begin(), ivec.end()); - absl::btree_map<int, int> tmap(imap.begin(), imap.end()); - EXPECT_EQ(1, tmset.size()); - EXPECT_EQ(1, tmmap.size()); - EXPECT_EQ(1, tset.size()); - EXPECT_EQ(1, tmap.size()); -} - -} // namespace - -class BtreeNodePeer { - public: - // Yields the size of a leaf node with a specific number of values. - template <typename ValueType> - constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) { - return btree_node< - set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>, - /*TargetNodeSize=*/256, // This parameter isn't used here. - /*Multi=*/false>>::SizeWithNValues(target_values_per_node); - } - - // Yields the number of values in a (non-root) leaf node for this btree. - template <typename Btree> - constexpr static size_t GetNumValuesPerNode() { - return btree_node<typename Btree::params_type>::kNodeValues; - } - - template <typename Btree> - constexpr static size_t GetMaxFieldType() { - return std::numeric_limits< - typename btree_node<typename Btree::params_type>::field_type>::max(); - } - - template <typename Btree> - constexpr static bool UsesLinearNodeSearch() { - return btree_node<typename Btree::params_type>::use_linear_search::value; - } -}; - -namespace { - -class BtreeMapTest : public ::testing::Test { - public: - struct Key {}; - struct Cmp { - template <typename T> - bool operator()(T, T) const { - return false; - } - }; - - struct KeyLin { - using absl_btree_prefer_linear_node_search = std::true_type; - }; - struct CmpLin : Cmp { - using absl_btree_prefer_linear_node_search = std::true_type; - }; - - struct KeyBin { - using absl_btree_prefer_linear_node_search = std::false_type; - }; - struct CmpBin : Cmp { - using absl_btree_prefer_linear_node_search = std::false_type; - }; - - template <typename K, typename C> - static bool IsLinear() { - return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>(); - } -}; - -TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) { - // Test requesting linear search by directly exporting an alias. - EXPECT_FALSE((IsLinear<Key, Cmp>())); - EXPECT_TRUE((IsLinear<KeyLin, Cmp>())); - EXPECT_TRUE((IsLinear<Key, CmpLin>())); - EXPECT_TRUE((IsLinear<KeyLin, CmpLin>())); -} - -TEST_F(BtreeMapTest, LinearChoiceTree) { - // Cmp has precedence, and is forcing binary - EXPECT_FALSE((IsLinear<Key, CmpBin>())); - EXPECT_FALSE((IsLinear<KeyLin, CmpBin>())); - EXPECT_FALSE((IsLinear<KeyBin, CmpBin>())); - EXPECT_FALSE((IsLinear<int, CmpBin>())); - EXPECT_FALSE((IsLinear<std::string, CmpBin>())); - // Cmp has precedence, and is forcing linear - EXPECT_TRUE((IsLinear<Key, CmpLin>())); - EXPECT_TRUE((IsLinear<KeyLin, CmpLin>())); - EXPECT_TRUE((IsLinear<KeyBin, CmpLin>())); - EXPECT_TRUE((IsLinear<int, CmpLin>())); - EXPECT_TRUE((IsLinear<std::string, CmpLin>())); - // Cmp has no preference, Key determines linear vs binary. - EXPECT_FALSE((IsLinear<Key, Cmp>())); - EXPECT_TRUE((IsLinear<KeyLin, Cmp>())); - EXPECT_FALSE((IsLinear<KeyBin, Cmp>())); - // arithmetic key w/ std::less or std::greater: linear - EXPECT_TRUE((IsLinear<int, std::less<int>>())); - EXPECT_TRUE((IsLinear<double, std::greater<double>>())); - // arithmetic key w/ custom compare: binary - EXPECT_FALSE((IsLinear<int, Cmp>())); - // non-arithmetic key: binary - EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>())); -} - -TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) { - absl::btree_map<std::string, std::unique_ptr<std::string>> m; - - std::unique_ptr<std::string> &v = m["A"]; - EXPECT_TRUE(v == nullptr); - v.reset(new std::string("X")); - - auto iter = m.find("A"); - EXPECT_EQ("X", *iter->second); -} - -TEST(Btree, InitializerListConstructor) { - absl::btree_set<std::string> set({"a", "b"}); - EXPECT_EQ(set.count("a"), 1); - EXPECT_EQ(set.count("b"), 1); - - absl::btree_multiset<int> mset({1, 1, 4}); - EXPECT_EQ(mset.count(1), 2); - EXPECT_EQ(mset.count(4), 1); - - absl::btree_map<int, int> map({{1, 5}, {2, 10}}); - EXPECT_EQ(map[1], 5); - EXPECT_EQ(map[2], 10); - - absl::btree_multimap<int, int> mmap({{1, 5}, {1, 10}}); - auto range = mmap.equal_range(1); - auto it = range.first; - ASSERT_NE(it, range.second); - EXPECT_EQ(it->second, 5); - ASSERT_NE(++it, range.second); - EXPECT_EQ(it->second, 10); - EXPECT_EQ(++it, range.second); -} - -TEST(Btree, InitializerListInsert) { - absl::btree_set<std::string> set; - set.insert({"a", "b"}); - EXPECT_EQ(set.count("a"), 1); - EXPECT_EQ(set.count("b"), 1); - - absl::btree_multiset<int> mset; - mset.insert({1, 1, 4}); - EXPECT_EQ(mset.count(1), 2); - EXPECT_EQ(mset.count(4), 1); - - absl::btree_map<int, int> map; - map.insert({{1, 5}, {2, 10}}); - // Test that inserting one element using an initializer list also works. - map.insert({3, 15}); - EXPECT_EQ(map[1], 5); - EXPECT_EQ(map[2], 10); - EXPECT_EQ(map[3], 15); - - absl::btree_multimap<int, int> mmap; - mmap.insert({{1, 5}, {1, 10}}); - auto range = mmap.equal_range(1); - auto it = range.first; - ASSERT_NE(it, range.second); - EXPECT_EQ(it->second, 5); - ASSERT_NE(++it, range.second); - EXPECT_EQ(it->second, 10); - EXPECT_EQ(++it, range.second); -} - -template <typename Compare, typename K> -void AssertKeyCompareToAdapted() { - using Adapted = typename key_compare_to_adapter<Compare>::type; - static_assert(!std::is_same<Adapted, Compare>::value, - "key_compare_to_adapter should have adapted this comparator."); - static_assert( - std::is_same<absl::weak_ordering, - absl::result_of_t<Adapted(const K &, const K &)>>::value, - "Adapted comparator should be a key-compare-to comparator."); -} -template <typename Compare, typename K> -void AssertKeyCompareToNotAdapted() { - using Unadapted = typename key_compare_to_adapter<Compare>::type; - static_assert( - std::is_same<Unadapted, Compare>::value, - "key_compare_to_adapter shouldn't have adapted this comparator."); - static_assert( - std::is_same<bool, - absl::result_of_t<Unadapted(const K &, const K &)>>::value, - "Un-adapted comparator should return bool."); -} - -TEST(Btree, KeyCompareToAdapter) { - AssertKeyCompareToAdapted<std::less<std::string>, std::string>(); - AssertKeyCompareToAdapted<std::greater<std::string>, std::string>(); - AssertKeyCompareToAdapted<std::less<absl::string_view>, absl::string_view>(); - AssertKeyCompareToAdapted<std::greater<absl::string_view>, - absl::string_view>(); - AssertKeyCompareToAdapted<std::less<absl::Cord>, absl::Cord>(); - AssertKeyCompareToAdapted<std::greater<absl::Cord>, absl::Cord>(); - AssertKeyCompareToNotAdapted<std::less<int>, int>(); - AssertKeyCompareToNotAdapted<std::greater<int>, int>(); -} - -TEST(Btree, RValueInsert) { - InstanceTracker tracker; - - absl::btree_set<MovableOnlyInstance> set; - set.insert(MovableOnlyInstance(1)); - set.insert(MovableOnlyInstance(3)); - MovableOnlyInstance two(2); - set.insert(set.find(MovableOnlyInstance(3)), std::move(two)); - auto it = set.find(MovableOnlyInstance(2)); - ASSERT_NE(it, set.end()); - ASSERT_NE(++it, set.end()); - EXPECT_EQ(it->value(), 3); - - absl::btree_multiset<MovableOnlyInstance> mset; - MovableOnlyInstance zero(0); - MovableOnlyInstance zero2(0); - mset.insert(std::move(zero)); - mset.insert(mset.find(MovableOnlyInstance(0)), std::move(zero2)); - EXPECT_EQ(mset.count(MovableOnlyInstance(0)), 2); - - absl::btree_map<int, MovableOnlyInstance> map; - std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)}; - std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)}; - std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)}; - map.insert(std::move(p1)); - map.insert(std::move(p3)); - map.insert(map.find(3), std::move(p2)); - ASSERT_NE(map.find(2), map.end()); - EXPECT_EQ(map.find(2)->second.value(), 10); - - absl::btree_multimap<int, MovableOnlyInstance> mmap; - std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)}; - std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)}; - mmap.insert(std::move(p4)); - mmap.insert(mmap.find(1), std::move(p5)); - auto range = mmap.equal_range(1); - auto it1 = range.first; - ASSERT_NE(it1, range.second); - EXPECT_EQ(it1->second.value(), 10); - ASSERT_NE(++it1, range.second); - EXPECT_EQ(it1->second.value(), 5); - EXPECT_EQ(++it1, range.second); - - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.swaps(), 0); -} - -// A btree set with a specific number of values per node. -template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>> -class SizedBtreeSet - : public btree_set_container<btree< - set_params<Key, Cmp, std::allocator<Key>, - BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode), - /*Multi=*/false>>> { - using Base = typename SizedBtreeSet::btree_set_container; - - public: - SizedBtreeSet() {} - using Base::Base; -}; - -template <typename Set> -void ExpectOperationCounts(const int expected_moves, - const int expected_comparisons, - const std::vector<int> &values, - InstanceTracker *tracker, Set *set) { - for (const int v : values) set->insert(MovableOnlyInstance(v)); - set->clear(); - EXPECT_EQ(tracker->moves(), expected_moves); - EXPECT_EQ(tracker->comparisons(), expected_comparisons); - EXPECT_EQ(tracker->copies(), 0); - EXPECT_EQ(tracker->swaps(), 0); - tracker->ResetCopiesMovesSwaps(); -} - -// Note: when the values in this test change, it is expected to have an impact -// on performance. -TEST(Btree, MovesComparisonsCopiesSwapsTracking) { - InstanceTracker tracker; - // Note: this is minimum number of values per node. - SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/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; - SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100> set100; - - // Don't depend on flags for random values because then the expectations will - // fail if the flags change. - std::vector<int> values = - GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23); - - EXPECT_EQ(BtreeNodePeer::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::GetNumValuesPerNode<absl::btree_set<int32_t>>(), - BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>()); - } - - // Test key insertion/deletion in random order. - 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(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(49951, 119325, values, &tracker, &set3); - ExpectOperationCounts(338813, 118266, values, &tracker, &set61); - ExpectOperationCounts(534529, 125279, values, &tracker, &set100); -} - -struct MovableOnlyInstanceThreeWayCompare { - absl::weak_ordering operator()(const MovableOnlyInstance &a, - const MovableOnlyInstance &b) const { - return a.compare(b); - } -}; - -// Note: when the values in this test change, it is expected to have an impact -// on performance. -TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) { - InstanceTracker tracker; - // Note: this is minimum number of values per node. - SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3, - MovableOnlyInstanceThreeWayCompare> - set3; - // Note: this is the default number of values per node for a set of int32s - // (with 64-bit pointers). - SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61, - MovableOnlyInstanceThreeWayCompare> - set61; - SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100, - MovableOnlyInstanceThreeWayCompare> - set100; - - // Don't depend on flags for random values because then the expectations will - // fail if the flags change. - std::vector<int> values = - GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23); - - EXPECT_EQ(BtreeNodePeer::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::GetNumValuesPerNode<absl::btree_set<int32_t>>(), - BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>()); - } - - // Test key insertion/deletion in random order. - 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(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(49951, 109326, values, &tracker, &set3); - ExpectOperationCounts(338813, 108267, values, &tracker, &set61); - ExpectOperationCounts(534529, 115280, values, &tracker, &set100); -} - -struct NoDefaultCtor { - int num; - explicit NoDefaultCtor(int i) : num(i) {} - - friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) { - return a.num < b.num; - } -}; - -TEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) { - absl::btree_map<NoDefaultCtor, NoDefaultCtor> m; - - for (int i = 1; i <= 99; ++i) { - SCOPED_TRACE(i); - EXPECT_TRUE(m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)).second); - } - EXPECT_FALSE(m.emplace(NoDefaultCtor(78), NoDefaultCtor(0)).second); - - auto iter99 = m.find(NoDefaultCtor(99)); - ASSERT_NE(iter99, m.end()); - EXPECT_EQ(iter99->second.num, 1); - - auto iter1 = m.find(NoDefaultCtor(1)); - ASSERT_NE(iter1, m.end()); - EXPECT_EQ(iter1->second.num, 99); - - auto iter50 = m.find(NoDefaultCtor(50)); - ASSERT_NE(iter50, m.end()); - EXPECT_EQ(iter50->second.num, 50); - - auto iter25 = m.find(NoDefaultCtor(25)); - ASSERT_NE(iter25, m.end()); - EXPECT_EQ(iter25->second.num, 75); -} - -TEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) { - absl::btree_multimap<NoDefaultCtor, NoDefaultCtor> m; - - for (int i = 1; i <= 99; ++i) { - SCOPED_TRACE(i); - m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)); - } - - auto iter99 = m.find(NoDefaultCtor(99)); - ASSERT_NE(iter99, m.end()); - EXPECT_EQ(iter99->second.num, 1); - - auto iter1 = m.find(NoDefaultCtor(1)); - ASSERT_NE(iter1, m.end()); - EXPECT_EQ(iter1->second.num, 99); - - auto iter50 = m.find(NoDefaultCtor(50)); - ASSERT_NE(iter50, m.end()); - EXPECT_EQ(iter50->second.num, 50); - - auto iter25 = m.find(NoDefaultCtor(25)); - ASSERT_NE(iter25, m.end()); - EXPECT_EQ(iter25->second.num, 75); -} - -TEST(Btree, MapAt) { - absl::btree_map<int, int> map = {{1, 2}, {2, 4}}; - EXPECT_EQ(map.at(1), 2); - EXPECT_EQ(map.at(2), 4); - map.at(2) = 8; - const absl::btree_map<int, int> &const_map = map; - EXPECT_EQ(const_map.at(1), 2); - EXPECT_EQ(const_map.at(2), 8); -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(map.at(3), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at"); -#endif -} - -TEST(Btree, BtreeMultisetEmplace) { - const int value_to_insert = 123456; - absl::btree_multiset<int> s; - auto iter = s.emplace(value_to_insert); - ASSERT_NE(iter, s.end()); - EXPECT_EQ(*iter, value_to_insert); - auto iter2 = s.emplace(value_to_insert); - EXPECT_NE(iter2, iter); - ASSERT_NE(iter2, s.end()); - EXPECT_EQ(*iter2, value_to_insert); - auto result = s.equal_range(value_to_insert); - EXPECT_EQ(std::distance(result.first, result.second), 2); -} - -TEST(Btree, BtreeMultisetEmplaceHint) { - const int value_to_insert = 123456; - absl::btree_multiset<int> s; - auto iter = s.emplace(value_to_insert); - ASSERT_NE(iter, s.end()); - EXPECT_EQ(*iter, value_to_insert); - auto emplace_iter = s.emplace_hint(iter, value_to_insert); - EXPECT_NE(emplace_iter, iter); - ASSERT_NE(emplace_iter, s.end()); - EXPECT_EQ(*emplace_iter, value_to_insert); -} - -TEST(Btree, BtreeMultimapEmplace) { - const int key_to_insert = 123456; - const char value0[] = "a"; - absl::btree_multimap<int, std::string> s; - auto iter = s.emplace(key_to_insert, value0); - ASSERT_NE(iter, s.end()); - EXPECT_EQ(iter->first, key_to_insert); - EXPECT_EQ(iter->second, value0); - const char value1[] = "b"; - auto iter2 = s.emplace(key_to_insert, value1); - EXPECT_NE(iter2, iter); - ASSERT_NE(iter2, s.end()); - EXPECT_EQ(iter2->first, key_to_insert); - EXPECT_EQ(iter2->second, value1); - auto result = s.equal_range(key_to_insert); - EXPECT_EQ(std::distance(result.first, result.second), 2); -} - -TEST(Btree, BtreeMultimapEmplaceHint) { - const int key_to_insert = 123456; - const char value0[] = "a"; - absl::btree_multimap<int, std::string> s; - auto iter = s.emplace(key_to_insert, value0); - ASSERT_NE(iter, s.end()); - EXPECT_EQ(iter->first, key_to_insert); - EXPECT_EQ(iter->second, value0); - const char value1[] = "b"; - auto emplace_iter = s.emplace_hint(iter, key_to_insert, value1); - EXPECT_NE(emplace_iter, iter); - ASSERT_NE(emplace_iter, s.end()); - EXPECT_EQ(emplace_iter->first, key_to_insert); - EXPECT_EQ(emplace_iter->second, value1); -} - -TEST(Btree, ConstIteratorAccessors) { - absl::btree_set<int> set; - for (int i = 0; i < 100; ++i) { - set.insert(i); - } - - auto it = set.cbegin(); - auto r_it = set.crbegin(); - for (int i = 0; i < 100; ++i, ++it, ++r_it) { - ASSERT_EQ(*it, i); - ASSERT_EQ(*r_it, 99 - i); - } - EXPECT_EQ(it, set.cend()); - EXPECT_EQ(r_it, set.crend()); -} - -TEST(Btree, StrSplitCompatible) { - const absl::btree_set<std::string> split_set = absl::StrSplit("a,b,c", ','); - const absl::btree_set<std::string> expected_set = {"a", "b", "c"}; - - EXPECT_EQ(split_set, expected_set); -} - -// We can't use EXPECT_EQ/etc. to compare absl::weak_ordering because they -// convert literal 0 to int and absl::weak_ordering can only be compared with -// literal 0. Defining this function allows for avoiding ClangTidy warnings. -bool Identity(const bool b) { return b; } - -TEST(Btree, ValueComp) { - absl::btree_set<int> s; - EXPECT_TRUE(s.value_comp()(1, 2)); - EXPECT_FALSE(s.value_comp()(2, 2)); - EXPECT_FALSE(s.value_comp()(2, 1)); - - absl::btree_map<int, int> m1; - EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0))); - EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0))); - EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0))); - - absl::btree_map<std::string, int> m2; - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)) < 0)); - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)) == 0)); - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)) > 0)); -} - -TEST(Btree, DefaultConstruction) { - absl::btree_set<int> s; - absl::btree_map<int, int> m; - absl::btree_multiset<int> ms; - absl::btree_multimap<int, int> mm; - - EXPECT_TRUE(s.empty()); - EXPECT_TRUE(m.empty()); - EXPECT_TRUE(ms.empty()); - EXPECT_TRUE(mm.empty()); -} - -TEST(Btree, SwissTableHashable) { - static constexpr int kValues = 10000; - std::vector<int> values(kValues); - std::iota(values.begin(), values.end(), 0); - std::vector<std::pair<int, int>> map_values; - for (int v : values) map_values.emplace_back(v, -v); - - using set = absl::btree_set<int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ - set{}, - set{1}, - set{2}, - set{1, 2}, - set{2, 1}, - set(values.begin(), values.end()), - set(values.rbegin(), values.rend()), - })); - - using mset = absl::btree_multiset<int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ - mset{}, - mset{1}, - mset{1, 1}, - mset{2}, - mset{2, 2}, - mset{1, 2}, - mset{1, 1, 2}, - mset{1, 2, 2}, - mset{1, 1, 2, 2}, - mset(values.begin(), values.end()), - mset(values.rbegin(), values.rend()), - })); - - using map = absl::btree_map<int, int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ - map{}, - map{{1, 0}}, - map{{1, 1}}, - map{{2, 0}}, - map{{2, 2}}, - map{{1, 0}, {2, 1}}, - map(map_values.begin(), map_values.end()), - map(map_values.rbegin(), map_values.rend()), - })); - - using mmap = absl::btree_multimap<int, int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ - mmap{}, - mmap{{1, 0}}, - mmap{{1, 1}}, - mmap{{1, 0}, {1, 1}}, - mmap{{1, 1}, {1, 0}}, - mmap{{2, 0}}, - mmap{{2, 2}}, - mmap{{1, 0}, {2, 1}}, - mmap(map_values.begin(), map_values.end()), - mmap(map_values.rbegin(), map_values.rend()), - })); -} - -TEST(Btree, ComparableSet) { - absl::btree_set<int> s1 = {1, 2}; - absl::btree_set<int> s2 = {2, 3}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_LE(s1, s1); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); - EXPECT_GE(s1, s1); -} - -TEST(Btree, ComparableSetsDifferentLength) { - absl::btree_set<int> s1 = {1, 2}; - absl::btree_set<int> s2 = {1, 2, 3}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); -} - -TEST(Btree, ComparableMultiset) { - absl::btree_multiset<int> s1 = {1, 2}; - absl::btree_multiset<int> s2 = {2, 3}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_LE(s1, s1); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); - EXPECT_GE(s1, s1); -} - -TEST(Btree, ComparableMap) { - absl::btree_map<int, int> s1 = {{1, 2}}; - absl::btree_map<int, int> s2 = {{2, 3}}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_LE(s1, s1); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); - EXPECT_GE(s1, s1); -} - -TEST(Btree, ComparableMultimap) { - absl::btree_multimap<int, int> s1 = {{1, 2}}; - absl::btree_multimap<int, int> s2 = {{2, 3}}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_LE(s1, s1); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); - EXPECT_GE(s1, s1); -} - -TEST(Btree, ComparableSetWithCustomComparator) { - // As specified by - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf section - // [container.requirements.general].12, ordering associative containers always - // uses default '<' operator - // - even if otherwise the container uses custom functor. - absl::btree_set<int, std::greater<int>> s1 = {1, 2}; - absl::btree_set<int, std::greater<int>> s2 = {2, 3}; - EXPECT_LT(s1, s2); - EXPECT_LE(s1, s2); - EXPECT_LE(s1, s1); - EXPECT_GT(s2, s1); - EXPECT_GE(s2, s1); - EXPECT_GE(s1, s1); -} - -TEST(Btree, EraseReturnsIterator) { - absl::btree_set<int> set = {1, 2, 3, 4, 5}; - auto result_it = set.erase(set.begin(), set.find(3)); - EXPECT_EQ(result_it, set.find(3)); - result_it = set.erase(set.find(5)); - EXPECT_EQ(result_it, set.end()); -} - -TEST(Btree, ExtractAndInsertNodeHandleSet) { - absl::btree_set<int> src1 = {1, 2, 3, 4, 5}; - auto nh = src1.extract(src1.find(3)); - EXPECT_THAT(src1, ElementsAre(1, 2, 4, 5)); - absl::btree_set<int> other; - absl::btree_set<int>::insert_return_type res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(3)); - EXPECT_EQ(res.position, other.find(3)); - EXPECT_TRUE(res.inserted); - EXPECT_TRUE(res.node.empty()); - - absl::btree_set<int> src2 = {3, 4}; - nh = src2.extract(src2.find(3)); - EXPECT_THAT(src2, ElementsAre(4)); - res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(3)); - EXPECT_EQ(res.position, other.find(3)); - EXPECT_FALSE(res.inserted); - ASSERT_FALSE(res.node.empty()); - EXPECT_EQ(res.node.value(), 3); -} - -template <typename Set> -void TestExtractWithTrackingForSet() { - InstanceTracker tracker; - { - Set s; - // Add enough elements to make sure we test internal nodes too. - const size_t kSize = 1000; - while (s.size() < kSize) { - s.insert(MovableOnlyInstance(s.size())); - } - for (int i = 0; i < kSize; ++i) { - // Extract with key - auto nh = s.extract(MovableOnlyInstance(i)); - EXPECT_EQ(s.size(), kSize - 1); - EXPECT_EQ(nh.value().value(), i); - // Insert with node - s.insert(std::move(nh)); - EXPECT_EQ(s.size(), kSize); - - // Extract with iterator - auto it = s.find(MovableOnlyInstance(i)); - nh = s.extract(it); - EXPECT_EQ(s.size(), kSize - 1); - EXPECT_EQ(nh.value().value(), i); - // Insert with node and hint - s.insert(s.begin(), std::move(nh)); - EXPECT_EQ(s.size(), kSize); - } - } - EXPECT_EQ(0, tracker.instances()); -} - -template <typename Map> -void TestExtractWithTrackingForMap() { - InstanceTracker tracker; - { - Map m; - // Add enough elements to make sure we test internal nodes too. - const size_t kSize = 1000; - while (m.size() < kSize) { - m.insert( - {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())}); - } - for (int i = 0; i < kSize; ++i) { - // Extract with key - auto nh = m.extract(CopyableMovableInstance(i)); - EXPECT_EQ(m.size(), kSize - 1); - EXPECT_EQ(nh.key().value(), i); - EXPECT_EQ(nh.mapped().value(), i); - // Insert with node - m.insert(std::move(nh)); - EXPECT_EQ(m.size(), kSize); - - // Extract with iterator - auto it = m.find(CopyableMovableInstance(i)); - nh = m.extract(it); - EXPECT_EQ(m.size(), kSize - 1); - EXPECT_EQ(nh.key().value(), i); - EXPECT_EQ(nh.mapped().value(), i); - // Insert with node and hint - m.insert(m.begin(), std::move(nh)); - EXPECT_EQ(m.size(), kSize); - } - } - EXPECT_EQ(0, tracker.instances()); -} - -TEST(Btree, ExtractTracking) { - TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>(); - TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>(); - TestExtractWithTrackingForMap< - absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>(); - TestExtractWithTrackingForMap< - absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>(); -} - -TEST(Btree, ExtractAndInsertNodeHandleMultiSet) { - absl::btree_multiset<int> src1 = {1, 2, 3, 3, 4, 5}; - auto nh = src1.extract(src1.find(3)); - EXPECT_THAT(src1, ElementsAre(1, 2, 3, 4, 5)); - absl::btree_multiset<int> other; - auto res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(3)); - EXPECT_EQ(res, other.find(3)); - - absl::btree_multiset<int> src2 = {3, 4}; - nh = src2.extract(src2.find(3)); - EXPECT_THAT(src2, ElementsAre(4)); - res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(3, 3)); - EXPECT_EQ(res, ++other.find(3)); -} - -TEST(Btree, ExtractAndInsertNodeHandleMap) { - absl::btree_map<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}}; - auto nh = src1.extract(src1.find(3)); - EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6))); - absl::btree_map<int, int> other; - absl::btree_map<int, int>::insert_return_type res = - other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(Pair(3, 4))); - EXPECT_EQ(res.position, other.find(3)); - EXPECT_TRUE(res.inserted); - EXPECT_TRUE(res.node.empty()); - - absl::btree_map<int, int> src2 = {{3, 6}}; - nh = src2.extract(src2.find(3)); - EXPECT_TRUE(src2.empty()); - res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(Pair(3, 4))); - EXPECT_EQ(res.position, other.find(3)); - EXPECT_FALSE(res.inserted); - ASSERT_FALSE(res.node.empty()); - EXPECT_EQ(res.node.key(), 3); - EXPECT_EQ(res.node.mapped(), 6); -} - -TEST(Btree, ExtractAndInsertNodeHandleMultiMap) { - absl::btree_multimap<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}}; - auto nh = src1.extract(src1.find(3)); - EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6))); - absl::btree_multimap<int, int> other; - auto res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(Pair(3, 4))); - EXPECT_EQ(res, other.find(3)); - - absl::btree_multimap<int, int> src2 = {{3, 6}}; - nh = src2.extract(src2.find(3)); - EXPECT_TRUE(src2.empty()); - res = other.insert(std::move(nh)); - EXPECT_THAT(other, ElementsAre(Pair(3, 4), Pair(3, 6))); - EXPECT_EQ(res, ++other.begin()); -} - -// For multisets, insert with hint also affects correctness because we need to -// insert immediately before the hint if possible. -struct InsertMultiHintData { - int key; - int not_key; - bool operator==(const InsertMultiHintData other) const { - return key == other.key && not_key == other.not_key; - } -}; - -struct InsertMultiHintDataKeyCompare { - using is_transparent = void; - bool operator()(const InsertMultiHintData a, - const InsertMultiHintData b) const { - return a.key < b.key; - } - bool operator()(const int a, const InsertMultiHintData b) const { - return a < b.key; - } - bool operator()(const InsertMultiHintData a, const int b) const { - return a.key < b; - } -}; - -TEST(Btree, InsertHintNodeHandle) { - // For unique sets, insert with hint is just a performance optimization. - // Test that insert works correctly when the hint is right or wrong. - { - absl::btree_set<int> src = {1, 2, 3, 4, 5}; - auto nh = src.extract(src.find(3)); - EXPECT_THAT(src, ElementsAre(1, 2, 4, 5)); - absl::btree_set<int> other = {0, 100}; - // Test a correct hint. - auto it = other.insert(other.lower_bound(3), std::move(nh)); - EXPECT_THAT(other, ElementsAre(0, 3, 100)); - EXPECT_EQ(it, other.find(3)); - - nh = src.extract(src.find(5)); - // Test an incorrect hint. - it = other.insert(other.end(), std::move(nh)); - EXPECT_THAT(other, ElementsAre(0, 3, 5, 100)); - EXPECT_EQ(it, other.find(5)); - } - - absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> src = - {{1, 2}, {3, 4}, {3, 5}}; - auto nh = src.extract(src.lower_bound(3)); - EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4})); - absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> - other = {{3, 1}, {3, 2}, {3, 3}}; - auto it = other.insert(--other.end(), std::move(nh)); - EXPECT_THAT( - other, ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2}, - InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3})); - EXPECT_EQ(it, --(--other.end())); - - nh = src.extract(src.find(3)); - EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5})); - it = other.insert(other.begin(), std::move(nh)); - EXPECT_THAT(other, - ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1}, - InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4}, - InsertMultiHintData{3, 3})); - EXPECT_EQ(it, other.begin()); -} - -struct IntCompareToCmp { - absl::weak_ordering operator()(int a, int b) const { - if (a < b) return absl::weak_ordering::less; - if (a > b) return absl::weak_ordering::greater; - return absl::weak_ordering::equivalent; - } -}; - -TEST(Btree, MergeIntoUniqueContainers) { - absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3}; - absl::btree_multiset<int> src2 = {3, 4, 4, 5}; - absl::btree_set<int> dst; - - dst.merge(src1); - EXPECT_TRUE(src1.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3)); - dst.merge(src2); - EXPECT_THAT(src2, ElementsAre(3, 4)); - EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5)); -} - -TEST(Btree, MergeIntoUniqueContainersWithCompareTo) { - absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3}; - absl::btree_multiset<int> src2 = {3, 4, 4, 5}; - absl::btree_set<int, IntCompareToCmp> dst; - - dst.merge(src1); - EXPECT_TRUE(src1.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3)); - dst.merge(src2); - EXPECT_THAT(src2, ElementsAre(3, 4)); - EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5)); -} - -TEST(Btree, MergeIntoMultiContainers) { - absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3}; - absl::btree_multiset<int> src2 = {3, 4, 4, 5}; - absl::btree_multiset<int> dst; - - dst.merge(src1); - EXPECT_TRUE(src1.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3)); - dst.merge(src2); - EXPECT_TRUE(src2.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5)); -} - -TEST(Btree, MergeIntoMultiContainersWithCompareTo) { - absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3}; - absl::btree_multiset<int> src2 = {3, 4, 4, 5}; - absl::btree_multiset<int, IntCompareToCmp> dst; - - dst.merge(src1); - EXPECT_TRUE(src1.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3)); - dst.merge(src2); - EXPECT_TRUE(src2.empty()); - EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5)); -} - -TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) { - absl::btree_map<int, int, IntCompareToCmp> src1 = {{1, 1}, {2, 2}, {3, 3}}; - absl::btree_multimap<int, int, std::greater<int>> src2 = { - {5, 5}, {4, 1}, {4, 4}, {3, 2}}; - absl::btree_multimap<int, int> dst; - - dst.merge(src1); - EXPECT_TRUE(src1.empty()); - EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3))); - dst.merge(src2); - EXPECT_TRUE(src2.empty()); - EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(3, 2), - Pair(4, 1), Pair(4, 4), Pair(5, 5))); -} - -TEST(Btree, MergeIntoSetMovableOnly) { - absl::btree_set<MovableOnlyInstance> src; - src.insert(MovableOnlyInstance(1)); - absl::btree_multiset<MovableOnlyInstance> dst1; - dst1.insert(MovableOnlyInstance(2)); - absl::btree_set<MovableOnlyInstance> dst2; - - // Test merge into multiset. - dst1.merge(src); - - EXPECT_TRUE(src.empty()); - // ElementsAre/ElementsAreArray don't work with move-only types. - ASSERT_THAT(dst1, SizeIs(2)); - EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1)); - EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2)); - - // Test merge into set. - dst2.merge(dst1); - - EXPECT_TRUE(dst1.empty()); - ASSERT_THAT(dst2, SizeIs(2)); - EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1)); - EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2)); -} - -struct KeyCompareToWeakOrdering { - template <typename T> - absl::weak_ordering operator()(const T &a, const T &b) const { - return a < b ? absl::weak_ordering::less - : a == b ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; - } -}; - -struct KeyCompareToStrongOrdering { - template <typename T> - absl::strong_ordering operator()(const T &a, const T &b) const { - return a < b ? absl::strong_ordering::less - : a == b ? absl::strong_ordering::equal - : absl::strong_ordering::greater; - } -}; - -TEST(Btree, UserProvidedKeyCompareToComparators) { - absl::btree_set<int, KeyCompareToWeakOrdering> weak_set = {1, 2, 3}; - EXPECT_TRUE(weak_set.contains(2)); - EXPECT_FALSE(weak_set.contains(4)); - - absl::btree_set<int, KeyCompareToStrongOrdering> strong_set = {1, 2, 3}; - EXPECT_TRUE(strong_set.contains(2)); - EXPECT_FALSE(strong_set.contains(4)); -} - -TEST(Btree, TryEmplaceBasicTest) { - absl::btree_map<int, std::string> m; - - // Should construct a string from the literal. - m.try_emplace(1, "one"); - EXPECT_EQ(1, m.size()); - - // Try other string constructors and const lvalue key. - const int key(42); - m.try_emplace(key, 3, 'a'); - m.try_emplace(2, std::string("two")); - - EXPECT_TRUE(std::is_sorted(m.begin(), m.end())); - EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, std::string>>{ - {1, "one"}, {2, "two"}, {42, "aaa"}})); -} - -TEST(Btree, TryEmplaceWithHintWorks) { - // Use a counting comparator here to verify that hint is used. - int calls = 0; - auto cmp = [&calls](int x, int y) { - ++calls; - return x < y; - }; - using Cmp = decltype(cmp); - - absl::btree_map<int, int, Cmp> m(cmp); - for (int i = 0; i < 128; ++i) { - m.emplace(i, i); - } - - // Sanity check for the comparator - calls = 0; - m.emplace(127, 127); - EXPECT_GE(calls, 4); - - // Try with begin hint: - calls = 0; - auto it = m.try_emplace(m.begin(), -1, -1); - EXPECT_EQ(129, m.size()); - EXPECT_EQ(it, m.begin()); - EXPECT_LE(calls, 2); - - // Try with end hint: - calls = 0; - std::pair<int, int> pair1024 = {1024, 1024}; - it = m.try_emplace(m.end(), pair1024.first, pair1024.second); - EXPECT_EQ(130, m.size()); - EXPECT_EQ(it, --m.end()); - EXPECT_LE(calls, 2); - - // Try value already present, bad hint; ensure no duplicate added: - calls = 0; - it = m.try_emplace(m.end(), 16, 17); - EXPECT_EQ(130, m.size()); - EXPECT_GE(calls, 4); - EXPECT_EQ(it, m.find(16)); - - // Try value already present, hint points directly to it: - calls = 0; - it = m.try_emplace(it, 16, 17); - EXPECT_EQ(130, m.size()); - EXPECT_LE(calls, 2); - EXPECT_EQ(it, m.find(16)); - - m.erase(2); - EXPECT_EQ(129, m.size()); - auto hint = m.find(3); - // Try emplace in the middle of two other elements. - calls = 0; - m.try_emplace(hint, 2, 2); - EXPECT_EQ(130, m.size()); - EXPECT_LE(calls, 2); - - EXPECT_TRUE(std::is_sorted(m.begin(), m.end())); -} - -TEST(Btree, TryEmplaceWithBadHint) { - absl::btree_map<int, int> m = {{1, 1}, {9, 9}}; - - // Bad hint (too small), should still emplace: - auto it = m.try_emplace(m.begin(), 2, 2); - EXPECT_EQ(it, ++m.begin()); - EXPECT_THAT(m, ElementsAreArray( - std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}})); - - // Bad hint, too large this time: - it = m.try_emplace(++(++m.begin()), 0, 0); - EXPECT_EQ(it, m.begin()); - EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, int>>{ - {0, 0}, {1, 1}, {2, 2}, {9, 9}})); -} - -TEST(Btree, TryEmplaceMaintainsSortedOrder) { - absl::btree_map<int, std::string> m; - std::pair<int, std::string> pair5 = {5, "five"}; - - // Test both lvalue & rvalue emplace. - m.try_emplace(10, "ten"); - m.try_emplace(pair5.first, pair5.second); - EXPECT_EQ(2, m.size()); - EXPECT_TRUE(std::is_sorted(m.begin(), m.end())); - - int int100{100}; - m.try_emplace(int100, "hundred"); - m.try_emplace(1, "one"); - EXPECT_EQ(4, m.size()); - EXPECT_TRUE(std::is_sorted(m.begin(), m.end())); -} - -TEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) { - absl::btree_map<int, int> m; - m.try_emplace(m.end(), 1); - EXPECT_EQ(0, m[1]); -} - -TEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) { - absl::btree_map<int, std::string> m; - m.try_emplace(m.end(), 1, 10, 'a'); - EXPECT_EQ(std::string(10, 'a'), m[1]); -} - -TEST(Btree, MoveAssignmentAllocatorPropagation) { - InstanceTracker tracker; - - int64_t bytes1 = 0, bytes2 = 0; - PropagatingCountingAlloc<MovableOnlyInstance> allocator1(&bytes1); - PropagatingCountingAlloc<MovableOnlyInstance> allocator2(&bytes2); - std::less<MovableOnlyInstance> cmp; - - // Test propagating allocator_type. - { - absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>, - PropagatingCountingAlloc<MovableOnlyInstance>> - set1(cmp, allocator1), set2(cmp, allocator2); - - for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i)); - - tracker.ResetCopiesMovesSwaps(); - set2 = std::move(set1); - EXPECT_EQ(tracker.moves(), 0); - } - // Test non-propagating allocator_type with equal allocators. - { - absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>, - CountingAllocator<MovableOnlyInstance>> - set1(cmp, allocator1), set2(cmp, allocator1); - - for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i)); - - tracker.ResetCopiesMovesSwaps(); - set2 = std::move(set1); - EXPECT_EQ(tracker.moves(), 0); - } - // Test non-propagating allocator_type with different allocators. - { - absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>, - CountingAllocator<MovableOnlyInstance>> - set1(cmp, allocator1), set2(cmp, allocator2); - - for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i)); - - tracker.ResetCopiesMovesSwaps(); - set2 = std::move(set1); - EXPECT_GE(tracker.moves(), 100); - } -} - -TEST(Btree, EmptyTree) { - absl::btree_set<int> s; - EXPECT_TRUE(s.empty()); - EXPECT_EQ(s.size(), 0); - EXPECT_GT(s.max_size(), 0); -} - -bool IsEven(int k) { return k % 2 == 0; } - -TEST(Btree, EraseIf) { - // Test that erase_if works with all the container types and supports lambdas. - { - absl::btree_set<int> s = {1, 3, 5, 6, 100}; - erase_if(s, [](int k) { return k > 3; }); - EXPECT_THAT(s, ElementsAre(1, 3)); - } - { - absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100}; - erase_if(s, [](int k) { return k <= 3; }); - EXPECT_THAT(s, ElementsAre(5, 6, 6, 100)); - } - { - absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}}; - erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; }); - EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3))); - } - { - absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6}, - {6, 6}, {6, 7}, {100, 6}}; - erase_if(m, [](std::pair<const int, int> kv) { return kv.second == 6; }); - EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7))); - } - // Test that erasing all elements from a large set works and test support for - // function pointers. - { - absl::btree_set<int> s; - for (int i = 0; i < 1000; ++i) s.insert(2 * i); - erase_if(s, IsEven); - EXPECT_THAT(s, IsEmpty()); - } - // Test that erase_if supports other format of function pointers. - { - absl::btree_set<int> s = {1, 3, 5, 6, 100}; - erase_if(s, &IsEven); - EXPECT_THAT(s, ElementsAre(1, 3, 5)); - } -} - -TEST(Btree, InsertOrAssign) { - absl::btree_map<int, int> m = {{1, 1}, {3, 3}}; - using value_type = typename decltype(m)::value_type; - - auto ret = m.insert_or_assign(4, 4); - EXPECT_EQ(*ret.first, value_type(4, 4)); - EXPECT_TRUE(ret.second); - ret = m.insert_or_assign(3, 100); - EXPECT_EQ(*ret.first, value_type(3, 100)); - EXPECT_FALSE(ret.second); - - auto hint_ret = m.insert_or_assign(ret.first, 3, 200); - EXPECT_EQ(*hint_ret, value_type(3, 200)); - hint_ret = m.insert_or_assign(m.find(1), 0, 1); - EXPECT_EQ(*hint_ret, value_type(0, 1)); - // Test with bad hint. - hint_ret = m.insert_or_assign(m.end(), -1, 1); - EXPECT_EQ(*hint_ret, value_type(-1, 1)); - - EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200), - Pair(4, 4))); -} - -TEST(Btree, InsertOrAssignMovableOnly) { - absl::btree_map<int, MovableOnlyInstance> m; - using value_type = typename decltype(m)::value_type; - - auto ret = m.insert_or_assign(4, MovableOnlyInstance(4)); - EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4))); - EXPECT_TRUE(ret.second); - ret = m.insert_or_assign(4, MovableOnlyInstance(100)); - EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100))); - EXPECT_FALSE(ret.second); - - auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200)); - EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200))); - - EXPECT_EQ(m.size(), 2); -} - -TEST(Btree, BitfieldArgument) { - union { - int n : 1; - }; - n = 0; - absl::btree_map<int, int> m; - m.erase(n); - m.count(n); - m.find(n); - m.contains(n); - m.equal_range(n); - m.insert_or_assign(n, n); - m.insert_or_assign(m.end(), n, n); - m.try_emplace(n); - m.try_emplace(m.end(), n); - m.at(n); - m[n]; -} - -TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) { - const absl::string_view names[] = {"n1", "n2"}; - - absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)}; - EXPECT_THAT(name_set1, ElementsAreArray(names)); - - absl::btree_set<std::string> name_set2; - name_set2.insert(std::begin(names), std::end(names)); - EXPECT_THAT(name_set2, ElementsAreArray(names)); -} - -// A type that is explicitly convertible from int and counts constructor calls. -struct ConstructorCounted { - explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; } - bool operator==(int other) const { return i == other; } - - int i; - static int constructor_calls; -}; -int ConstructorCounted::constructor_calls = 0; - -struct ConstructorCountedCompare { - bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; } - bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; } - bool operator()(const ConstructorCounted &a, - const ConstructorCounted &b) const { - return a.i < b.i; - } - using is_transparent = void; -}; - -TEST(Btree, - SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) { - const int i[] = {0, 1, 1}; - ConstructorCounted::constructor_calls = 0; - - absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{ - std::begin(i), std::end(i)}; - EXPECT_THAT(set, ElementsAre(0, 1)); - EXPECT_EQ(ConstructorCounted::constructor_calls, 2); - - set.insert(std::begin(i), std::end(i)); - EXPECT_THAT(set, ElementsAre(0, 1)); - EXPECT_EQ(ConstructorCounted::constructor_calls, 2); -} - -TEST(Btree, - SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) { - const int i[] = {0, 1}; - - absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)}; - EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull()))); - - absl::btree_set<std::vector<void *>> s2; - s2.insert(std::begin(i), std::end(i)); - EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull()))); -} - -// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that -// prevents explicit conversions between pair types. -// We only run this test for the libstdc++ from GCC 7 or newer because we can't -// reliably check the libstdc++ version prior to that release. -#if !defined(__GLIBCXX__) || \ - (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7) -TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) { - const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}}; - - absl::btree_map<std::string, int> name_map1{std::begin(names), - std::end(names)}; - EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2))); - - absl::btree_map<std::string, int> name_map2; - name_map2.insert(std::begin(names), std::end(names)); - EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2))); -} - -TEST(Btree, - MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) { - const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}}; - ConstructorCounted::constructor_calls = 0; - - absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{ - std::begin(i), std::end(i)}; - EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2))); - EXPECT_EQ(ConstructorCounted::constructor_calls, 2); - - map.insert(std::begin(i), std::end(i)); - EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2))); - EXPECT_EQ(ConstructorCounted::constructor_calls, 2); -} - -TEST(Btree, - MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) { - const std::pair<int, int> i[] = {{0, 1}, {1, 2}}; - - absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)}; - EXPECT_THAT(m1, - ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2))); - - absl::btree_map<std::vector<void *>, int> m2; - m2.insert(std::begin(i), std::end(i)); - EXPECT_THAT(m2, - ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2))); -} - -TEST(Btree, HeterogeneousTryEmplace) { - absl::btree_map<std::string, int> m; - std::string s = "key"; - absl::string_view sv = s; - m.try_emplace(sv, 1); - EXPECT_EQ(m[s], 1); - - m.try_emplace(m.end(), sv, 2); - EXPECT_EQ(m[s], 1); -} - -TEST(Btree, HeterogeneousOperatorMapped) { - absl::btree_map<std::string, int> m; - std::string s = "key"; - absl::string_view sv = s; - m[sv] = 1; - EXPECT_EQ(m[s], 1); - - m[sv] = 2; - EXPECT_EQ(m[s], 2); -} - -TEST(Btree, HeterogeneousInsertOrAssign) { - absl::btree_map<std::string, int> m; - std::string s = "key"; - absl::string_view sv = s; - m.insert_or_assign(sv, 1); - EXPECT_EQ(m[s], 1); - - m.insert_or_assign(m.end(), sv, 2); - EXPECT_EQ(m[s], 2); -} -#endif - -// This test requires std::launder for mutable key access in node handles. -#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 -TEST(Btree, NodeHandleMutableKeyAccess) { - { - absl::btree_map<std::string, std::string> map; - - map["key1"] = "mapped"; - - auto nh = map.extract(map.begin()); - nh.key().resize(3); - map.insert(std::move(nh)); - - EXPECT_THAT(map, ElementsAre(Pair("key", "mapped"))); - } - // Also for multimap. - { - absl::btree_multimap<std::string, std::string> map; - - map.emplace("key1", "mapped"); - - auto nh = map.extract(map.begin()); - nh.key().resize(3); - map.insert(std::move(nh)); - - EXPECT_THAT(map, ElementsAre(Pair("key", "mapped"))); - } -} -#endif - -struct MultiKey { - int i1; - int i2; -}; - -bool operator==(const MultiKey a, const MultiKey b) { - return a.i1 == b.i1 && a.i2 == b.i2; -} - -// A heterogeneous comparator that has different equivalence classes for -// different lookup types. -struct MultiKeyComp { - using is_transparent = void; - bool operator()(const MultiKey a, const MultiKey b) const { - if (a.i1 != b.i1) return a.i1 < b.i1; - return a.i2 < b.i2; - } - bool operator()(const int a, const MultiKey b) const { return a < b.i1; } - bool operator()(const MultiKey a, const int b) const { return a.i1 < b; } -}; - -TEST(Btree, MultiKeyEqualRange) { - absl::btree_set<MultiKey, MultiKeyComp> 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); - EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i; - } -} - -TEST(Btree, MultiKeyErase) { - absl::btree_set<MultiKey, MultiKeyComp> 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})); -} - -TEST(Btree, MultiKeyCount) { - const absl::btree_set<MultiKey, MultiKeyComp> set = { - {1, 1}, {2, 1}, {2, 2}, {3, 1}}; - EXPECT_EQ(set.count(2), 2); -} - -TEST(Btree, AllocConstructor) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used = 0; - Alloc alloc(&bytes_used); - Set set(alloc); - - set.insert({1, 2, 3}); - - EXPECT_THAT(set, ElementsAre(1, 2, 3)); - EXPECT_GT(bytes_used, set.size() * sizeof(int)); -} - -TEST(Btree, AllocInitializerListConstructor) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used = 0; - Alloc alloc(&bytes_used); - Set set({1, 2, 3}, alloc); - - EXPECT_THAT(set, ElementsAre(1, 2, 3)); - EXPECT_GT(bytes_used, set.size() * sizeof(int)); -} - -TEST(Btree, AllocRangeConstructor) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used = 0; - Alloc alloc(&bytes_used); - std::vector<int> v = {1, 2, 3}; - Set set(v.begin(), v.end(), alloc); - - EXPECT_THAT(set, ElementsAre(1, 2, 3)); - EXPECT_GT(bytes_used, set.size() * sizeof(int)); -} - -TEST(Btree, AllocCopyConstructor) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used1 = 0; - Alloc alloc1(&bytes_used1); - Set set1(alloc1); - - set1.insert({1, 2, 3}); - - int64_t bytes_used2 = 0; - Alloc alloc2(&bytes_used2); - Set set2(set1, alloc2); - - EXPECT_THAT(set1, ElementsAre(1, 2, 3)); - EXPECT_THAT(set2, ElementsAre(1, 2, 3)); - EXPECT_GT(bytes_used1, set1.size() * sizeof(int)); - EXPECT_EQ(bytes_used1, bytes_used2); -} - -TEST(Btree, AllocMoveConstructor_SameAlloc) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used = 0; - Alloc alloc(&bytes_used); - Set set1(alloc); - - set1.insert({1, 2, 3}); - - const int64_t original_bytes_used = bytes_used; - EXPECT_GT(original_bytes_used, set1.size() * sizeof(int)); - - Set set2(std::move(set1), alloc); - - EXPECT_THAT(set2, ElementsAre(1, 2, 3)); - EXPECT_EQ(bytes_used, original_bytes_used); -} - -TEST(Btree, AllocMoveConstructor_DifferentAlloc) { - using Alloc = CountingAllocator<int>; - using Set = absl::btree_set<int, std::less<int>, Alloc>; - int64_t bytes_used1 = 0; - Alloc alloc1(&bytes_used1); - Set set1(alloc1); - - set1.insert({1, 2, 3}); - - const int64_t original_bytes_used = bytes_used1; - EXPECT_GT(original_bytes_used, set1.size() * sizeof(int)); - - int64_t bytes_used2 = 0; - Alloc alloc2(&bytes_used2); - Set set2(std::move(set1), alloc2); - - EXPECT_THAT(set2, ElementsAre(1, 2, 3)); - // We didn't free these bytes allocated by `set1` yet. - EXPECT_EQ(bytes_used1, original_bytes_used); - EXPECT_EQ(bytes_used2, original_bytes_used); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/btree_test.h b/third_party/abseil_cpp/absl/container/btree_test.h deleted file mode 100644 index 624908072d59..000000000000 --- a/third_party/abseil_cpp/absl/container/btree_test.h +++ /dev/null @@ -1,166 +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. - -#ifndef ABSL_CONTAINER_BTREE_TEST_H_ -#define ABSL_CONTAINER_BTREE_TEST_H_ - -#include <algorithm> -#include <cassert> -#include <random> -#include <string> -#include <utility> -#include <vector> - -#include "absl/container/btree_map.h" -#include "absl/container/btree_set.h" -#include "absl/container/flat_hash_set.h" -#include "absl/strings/cord.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// Like remove_const but propagates the removal through std::pair. -template <typename T> -struct remove_pair_const { - using type = typename std::remove_const<T>::type; -}; -template <typename T, typename U> -struct remove_pair_const<std::pair<T, U> > { - using type = std::pair<typename remove_pair_const<T>::type, - typename remove_pair_const<U>::type>; -}; - -// Utility class to provide an accessor for a key given a value. The default -// behavior is to treat the value as a pair and return the first element. -template <typename K, typename V> -struct KeyOfValue { - struct type { - const K& operator()(const V& p) const { return p.first; } - }; -}; - -// Partial specialization of KeyOfValue class for when the key and value are -// the same type such as in set<> and btree_set<>. -template <typename K> -struct KeyOfValue<K, K> { - struct type { - const K& operator()(const K& k) const { return k; } - }; -}; - -inline char* GenerateDigits(char buf[16], unsigned val, unsigned maxval) { - assert(val <= maxval); - constexpr unsigned kBase = 64; // avoid integer division. - unsigned p = 15; - buf[p--] = 0; - while (maxval > 0) { - buf[p--] = ' ' + (val % kBase); - val /= kBase; - maxval /= kBase; - } - return buf + p + 1; -} - -template <typename K> -struct Generator { - int maxval; - explicit Generator(int m) : maxval(m) {} - K operator()(int i) const { - assert(i <= maxval); - return K(i); - } -}; - -template <> -struct Generator<absl::Time> { - int maxval; - explicit Generator(int m) : maxval(m) {} - absl::Time operator()(int i) const { return absl::FromUnixMillis(i); } -}; - -template <> -struct Generator<std::string> { - int maxval; - explicit Generator(int m) : maxval(m) {} - std::string operator()(int i) const { - char buf[16]; - return GenerateDigits(buf, i, maxval); - } -}; - -template <> -struct Generator<Cord> { - int maxval; - explicit Generator(int m) : maxval(m) {} - Cord operator()(int i) const { - char buf[16]; - return Cord(GenerateDigits(buf, i, maxval)); - } -}; - -template <typename T, typename U> -struct Generator<std::pair<T, U> > { - Generator<typename remove_pair_const<T>::type> tgen; - Generator<typename remove_pair_const<U>::type> ugen; - - explicit Generator(int m) : tgen(m), ugen(m) {} - std::pair<T, U> operator()(int i) const { - return std::make_pair(tgen(i), ugen(i)); - } -}; - -// Generate n values for our tests and benchmarks. Value range is [0, maxval]. -inline std::vector<int> GenerateNumbersWithSeed(int n, int maxval, int seed) { - // NOTE: Some tests rely on generated numbers not changing between test runs. - // We use std::minstd_rand0 because it is well-defined, but don't use - // std::uniform_int_distribution because platforms use different algorithms. - std::minstd_rand0 rng(seed); - - std::vector<int> values; - absl::flat_hash_set<int> unique_values; - if (values.size() < n) { - for (int i = values.size(); i < n; i++) { - int value; - do { - value = static_cast<int>(rng()) % (maxval + 1); - } while (!unique_values.insert(value).second); - - values.push_back(value); - } - } - return values; -} - -// Generates n values in the range [0, maxval]. -template <typename V> -std::vector<V> GenerateValuesWithSeed(int n, int maxval, int seed) { - const std::vector<int> nums = GenerateNumbersWithSeed(n, maxval, seed); - Generator<V> gen(maxval); - std::vector<V> vec; - - vec.reserve(n); - for (int i = 0; i < n; i++) { - vec.push_back(gen(nums[i])); - } - - return vec; -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_BTREE_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/fixed_array.h b/third_party/abseil_cpp/absl/container/fixed_array.h deleted file mode 100644 index fcb3e545b243..000000000000 --- a/third_party/abseil_cpp/absl/container/fixed_array.h +++ /dev/null @@ -1,532 +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: fixed_array.h -// ----------------------------------------------------------------------------- -// -// A `FixedArray<T>` represents a non-resizable array of `T` where the length of -// the array can be determined at run-time. It is a good replacement for -// non-standard and deprecated uses of `alloca()` and variable length arrays -// within the GCC extension. (See -// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html). -// -// `FixedArray` allocates small arrays inline, keeping performance fast by -// avoiding heap operations. It also helps reduce the chances of -// accidentally overflowing your stack if large input is passed to -// your function. - -#ifndef ABSL_CONTAINER_FIXED_ARRAY_H_ -#define ABSL_CONTAINER_FIXED_ARRAY_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <initializer_list> -#include <iterator> -#include <limits> -#include <memory> -#include <new> -#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" -#include "absl/base/optimization.h" -#include "absl/base/port.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1); - -// ----------------------------------------------------------------------------- -// FixedArray -// ----------------------------------------------------------------------------- -// -// A `FixedArray` provides a run-time fixed-size array, allocating a small array -// inline for efficiency. -// -// Most users should not specify an `inline_elements` argument and let -// `FixedArray` automatically determine the number of elements -// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the -// `FixedArray` implementation will use inline storage for arrays with a -// length <= `inline_elements`. -// -// Note that a `FixedArray` constructed with a `size_type` argument will -// default-initialize its values by leaving trivially constructible types -// 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 { - static_assert(!std::is_array<T>::value || std::extent<T>::value > 0, - "Arrays with unknown bounds cannot be used with FixedArray."); - - static constexpr size_t kInlineBytesDefault = 256; - - using AllocatorTraits = std::allocator_traits<A>; - // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17, - // but this seems to be mostly pedantic. - template <typename Iterator> - using EnableIfForwardIterator = absl::enable_if_t<std::is_convertible< - typename std::iterator_traits<Iterator>::iterator_category, - std::forward_iterator_tag>::value>; - static constexpr bool NoexceptCopyable() { - return std::is_nothrow_copy_constructible<StorageElement>::value && - absl::allocator_is_nothrow<allocator_type>::value; - } - static constexpr bool NoexceptMovable() { - return std::is_nothrow_move_constructible<StorageElement>::value && - absl::allocator_is_nothrow<allocator_type>::value; - } - static constexpr bool DefaultConstructorIsNonTrivial() { - return !absl::is_trivially_default_constructible<StorageElement>::value; - } - - 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 iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - static constexpr size_type inline_elements = - (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type) - : static_cast<size_type>(N)); - - FixedArray( - const FixedArray& other, - const allocator_type& a = allocator_type()) noexcept(NoexceptCopyable()) - : FixedArray(other.begin(), other.end(), a) {} - - FixedArray( - FixedArray&& other, - const allocator_type& a = allocator_type()) noexcept(NoexceptMovable()) - : FixedArray(std::make_move_iterator(other.begin()), - std::make_move_iterator(other.end()), a) {} - - // Creates an array object that can store `n` elements. - // Note that trivially constructible elements will be uninitialized. - explicit FixedArray(size_type n, const allocator_type& a = allocator_type()) - : storage_(n, a) { - if (DefaultConstructorIsNonTrivial()) { - memory_internal::ConstructRange(storage_.alloc(), storage_.begin(), - storage_.end()); - } - } - - // Creates an array initialized with `n` copies of `val`. - FixedArray(size_type n, const value_type& val, - const allocator_type& a = allocator_type()) - : storage_(n, a) { - memory_internal::ConstructRange(storage_.alloc(), storage_.begin(), - storage_.end(), val); - } - - // Creates an array initialized with the size and contents of `init_list`. - FixedArray(std::initializer_list<value_type> init_list, - const allocator_type& a = allocator_type()) - : FixedArray(init_list.begin(), init_list.end(), a) {} - - // Creates an array initialized with the elements from the input - // range. The array's size will always be `std::distance(first, last)`. - // REQUIRES: Iterator must be a forward_iterator or better. - template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr> - FixedArray(Iterator first, Iterator last, - const allocator_type& a = allocator_type()) - : storage_(std::distance(first, last), a) { - memory_internal::CopyRange(storage_.alloc(), storage_.begin(), first, last); - } - - ~FixedArray() noexcept { - for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) { - AllocatorTraits::destroy(storage_.alloc(), cur); - } - } - - // Assignments are deleted because they break the invariant that the size of a - // `FixedArray` never changes. - void operator=(FixedArray&&) = delete; - void operator=(const FixedArray&) = delete; - - // FixedArray::size() - // - // Returns the length of the fixed array. - size_type size() const { return storage_.size(); } - - // FixedArray::max_size() - // - // Returns the largest possible value of `std::distance(begin(), end())` for a - // `FixedArray<T>`. This is equivalent to the most possible addressable bytes - // over the number of bytes taken by T. - constexpr size_type max_size() const { - return (std::numeric_limits<difference_type>::max)() / sizeof(value_type); - } - - // FixedArray::empty() - // - // Returns whether or not the fixed array is empty. - bool empty() const { return size() == 0; } - - // FixedArray::memsize() - // - // Returns the memory size of the fixed array in bytes. - size_t memsize() const { return size() * sizeof(value_type); } - - // FixedArray::data() - // - // Returns a const T* pointer to elements of the `FixedArray`. This pointer - // can be used to access (but not modify) the contained elements. - const_pointer data() const { return AsValueType(storage_.begin()); } - - // Overload of FixedArray::data() to return a T* pointer to elements of the - // fixed array. This pointer can be used to access and modify the contained - // elements. - pointer data() { return AsValueType(storage_.begin()); } - - // FixedArray::operator[] - // - // Returns a reference the ith element of the fixed array. - // REQUIRES: 0 <= i < size() - reference operator[](size_type i) { - ABSL_HARDENING_ASSERT(i < size()); - return data()[i]; - } - - // Overload of FixedArray::operator()[] to return a const reference to the - // ith element of the fixed array. - // REQUIRES: 0 <= i < size() - const_reference operator[](size_type i) const { - ABSL_HARDENING_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 - reference at(size_type i) { - if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check"); - } - return data()[i]; - } - - // Overload of FixedArray::at() to return a const reference to the ith element - // of the fixed array. - const_reference at(size_type i) const { - if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check"); - } - return data()[i]; - } - - // FixedArray::front() - // - // Returns a reference to the first element of the fixed array. - reference front() { - ABSL_HARDENING_ASSERT(!empty()); - return data()[0]; - } - - // Overload of FixedArray::front() to return a reference to the first element - // of a fixed array of const values. - const_reference front() const { - ABSL_HARDENING_ASSERT(!empty()); - return data()[0]; - } - - // FixedArray::back() - // - // Returns a reference to the last element of the fixed array. - reference back() { - ABSL_HARDENING_ASSERT(!empty()); - return data()[size() - 1]; - } - - // Overload of FixedArray::back() to return a reference to the last element - // of a fixed array of const values. - const_reference back() const { - ABSL_HARDENING_ASSERT(!empty()); - return data()[size() - 1]; - } - - // FixedArray::begin() - // - // Returns an iterator to the beginning of the fixed array. - iterator begin() { return data(); } - - // Overload of FixedArray::begin() to return a const iterator to the - // beginning of the fixed array. - const_iterator begin() const { return data(); } - - // FixedArray::cbegin() - // - // Returns a const iterator to the beginning of the fixed array. - const_iterator cbegin() const { return begin(); } - - // FixedArray::end() - // - // Returns an iterator to the end of the fixed array. - iterator end() { return data() + size(); } - - // Overload of FixedArray::end() to return a const iterator to the end of the - // fixed array. - const_iterator end() const { return data() + size(); } - - // FixedArray::cend() - // - // Returns a const iterator to the end of the fixed array. - const_iterator cend() const { return end(); } - - // FixedArray::rbegin() - // - // Returns a reverse iterator from the end of the fixed array. - reverse_iterator rbegin() { return reverse_iterator(end()); } - - // Overload of FixedArray::rbegin() to return a const reverse iterator from - // the end of the fixed array. - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - - // FixedArray::crbegin() - // - // Returns a const reverse iterator from the end of the fixed array. - const_reverse_iterator crbegin() const { return rbegin(); } - - // FixedArray::rend() - // - // Returns a reverse iterator from the beginning of the fixed array. - reverse_iterator rend() { return reverse_iterator(begin()); } - - // Overload of FixedArray::rend() for returning a const reverse iterator - // from the beginning of the fixed array. - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - // FixedArray::crend() - // - // Returns a reverse iterator from the beginning of the fixed array. - const_reverse_iterator crend() const { return rend(); } - - // FixedArray::fill() - // - // Assigns the given `value` to all elements in the fixed array. - void fill(const value_type& val) { std::fill(begin(), end(), val); } - - // Relational operators. Equality operators are elementwise using - // `operator==`, while order operators order FixedArrays lexicographically. - friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) { - return absl::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); - } - - friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) { - return !(lhs == rhs); - } - - friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), - rhs.end()); - } - - friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) { - return rhs < lhs; - } - - friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) { - return !(rhs < lhs); - } - - friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) { - return !(lhs < rhs); - } - - template <typename H> - friend H AbslHashValue(H h, const FixedArray& v) { - return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), - v.size()); - } - - private: - // StorageElement - // - // For FixedArrays with a C-style-array value_type, StorageElement is a POD - // wrapper struct called StorageElementWrapper that holds the value_type - // instance inside. This is needed for construction and destruction of the - // entire array regardless of how many dimensions it has. For all other cases, - // StorageElement is just an alias of value_type. - // - // Maintainer's Note: The simpler solution would be to simply wrap value_type - // in a struct whether it's an array or not. That causes some paranoid - // diagnostics to misfire, believing that 'data()' returns a pointer to a - // single element, rather than the packed array that it really is. - // e.g.: - // - // FixedArray<char> buf(1); - // sprintf(buf.data(), "foo"); - // - // error: call to int __builtin___sprintf_chk(etc...) - // will always overflow destination buffer [-Werror] - // - template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>, - size_t InnerN = std::extent<OuterT>::value> - struct StorageElementWrapper { - InnerT array[InnerN]; - }; - - using StorageElement = - absl::conditional_t<std::is_array<value_type>::value, - StorageElementWrapper<value_type>, value_type>; - - static pointer AsValueType(pointer ptr) { return ptr; } - static pointer AsValueType(StorageElementWrapper<value_type>* ptr) { - return std::addressof(ptr->array); - } - - static_assert(sizeof(StorageElement) == sizeof(value_type), ""); - static_assert(alignof(StorageElement) == alignof(value_type), ""); - - class NonEmptyInlinedStorage { - public: - StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); } - void AnnotateConstruct(size_type n); - void AnnotateDestruct(size_type n); - -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - void* RedzoneBegin() { return &redzone_begin_; } - void* RedzoneEnd() { return &redzone_end_ + 1; } -#endif // ABSL_HAVE_ADDRESS_SANITIZER - - private: - ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_); - alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])]; - ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_); - }; - - class EmptyInlinedStorage { - public: - StorageElement* data() { return nullptr; } - void AnnotateConstruct(size_type) {} - void AnnotateDestruct(size_type) {} - }; - - using InlinedStorage = - absl::conditional_t<inline_elements == 0, EmptyInlinedStorage, - NonEmptyInlinedStorage>; - - // Storage - // - // An instance of Storage manages the inline and out-of-line memory for - // instances of FixedArray. This guarantees that even when construction of - // individual elements fails in the FixedArray constructor body, the - // destructor for Storage will still be called and out-of-line memory will be - // properly deallocated. - // - class Storage : public InlinedStorage { - public: - Storage(size_type n, const allocator_type& a) - : size_alloc_(n, a), data_(InitializeData()) {} - - ~Storage() noexcept { - if (UsingInlinedStorage(size())) { - InlinedStorage::AnnotateDestruct(size()); - } else { - AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size()); - } - } - - size_type size() const { return size_alloc_.template get<0>(); } - StorageElement* begin() const { return data_; } - StorageElement* end() const { return begin() + size(); } - allocator_type& alloc() { return size_alloc_.template get<1>(); } - - private: - static bool UsingInlinedStorage(size_type n) { - return n <= inline_elements; - } - - StorageElement* InitializeData() { - if (UsingInlinedStorage(size())) { - InlinedStorage::AnnotateConstruct(size()); - return InlinedStorage::data(); - } else { - return reinterpret_cast<StorageElement*>( - AllocatorTraits::allocate(alloc(), size())); - } - } - - // `CompressedTuple` takes advantage of EBCO for stateless `allocator_type`s - container_internal::CompressedTuple<size_type, allocator_type> size_alloc_; - StorageElement* data_; - }; - - Storage storage_; -}; - -template <typename T, size_t N, typename A> -constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault; - -template <typename T, size_t N, typename A> -constexpr typename FixedArray<T, N, A>::size_type - FixedArray<T, N, A>::inline_elements; - -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 - 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 - 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 - 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 - static_cast<void>(n); // Mark used when not in asan mode -} -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_FIXED_ARRAY_H_ diff --git a/third_party/abseil_cpp/absl/container/fixed_array_benchmark.cc b/third_party/abseil_cpp/absl/container/fixed_array_benchmark.cc deleted file mode 100644 index 3c7a5a723450..000000000000 --- a/third_party/abseil_cpp/absl/container/fixed_array_benchmark.cc +++ /dev/null @@ -1,67 +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 <stddef.h> - -#include <string> - -#include "benchmark/benchmark.h" -#include "absl/container/fixed_array.h" - -namespace { - -// For benchmarking -- simple class with constructor and destructor that -// set an int to a constant.. -class SimpleClass { - public: - SimpleClass() : i(3) {} - ~SimpleClass() { i = 0; } - - private: - int i; -}; - -template <typename C, size_t stack_size> -void BM_FixedArray(benchmark::State& state) { - const int size = state.range(0); - for (auto _ : state) { - absl::FixedArray<C, stack_size> fa(size); - benchmark::DoNotOptimize(fa.data()); - } -} -BENCHMARK_TEMPLATE(BM_FixedArray, char, absl::kFixedArrayUseDefault) - ->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, char, 0)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, char, 1)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, char, 16)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, char, 256)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, char, 65536)->Range(0, 1 << 16); - -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, absl::kFixedArrayUseDefault) - ->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 0)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 1)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 16)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 256)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 65536)->Range(0, 1 << 16); - -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, absl::kFixedArrayUseDefault) - ->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 0)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 1)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 16)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 256)->Range(0, 1 << 16); -BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 65536)->Range(0, 1 << 16); - -} // namespace 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 deleted file mode 100644 index e5f59299b358..000000000000 --- a/third_party/abseil_cpp/absl/container/fixed_array_exception_safety_test.cc +++ /dev/null @@ -1,201 +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/container/fixed_array.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include <initializer_list> - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -constexpr size_t kInlined = 25; -constexpr size_t kSmallSize = kInlined / 2; -constexpr size_t kLargeSize = kInlined * 2; - -constexpr int kInitialValue = 5; -constexpr int kUpdatedValue = 10; - -using ::testing::TestThrowingCtor; - -using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; -using ThrowAlloc = - testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>; -using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using MoveThrowAlloc = - testing::ThrowingAllocator<MoveThrower, - testing::AllocSpec::kEverythingThrows>; - -using FixedArr = absl::FixedArray<Thrower, kInlined>; -using FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>; - -using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>; -using MoveFixedArrWithAlloc = - absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>; - -TEST(FixedArrayExceptionSafety, CopyConstructor) { - auto small = FixedArr(kSmallSize); - TestThrowingCtor<FixedArr>(small); - - auto large = FixedArr(kLargeSize); - TestThrowingCtor<FixedArr>(large); -} - -TEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) { - auto small = FixedArrWithAlloc(kSmallSize); - TestThrowingCtor<FixedArrWithAlloc>(small); - - auto large = FixedArrWithAlloc(kLargeSize); - TestThrowingCtor<FixedArrWithAlloc>(large); -} - -TEST(FixedArrayExceptionSafety, MoveConstructor) { - TestThrowingCtor<FixedArr>(FixedArr(kSmallSize)); - TestThrowingCtor<FixedArr>(FixedArr(kLargeSize)); - - // TypeSpec::kNoThrowMove - TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kSmallSize)); - TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize)); -} - -TEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) { - TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize)); - TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize)); - - // TypeSpec::kNoThrowMove - TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize)); - TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize)); -} - -TEST(FixedArrayExceptionSafety, SizeConstructor) { - TestThrowingCtor<FixedArr>(kSmallSize); - TestThrowingCtor<FixedArr>(kLargeSize); -} - -TEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) { - TestThrowingCtor<FixedArrWithAlloc>(kSmallSize); - TestThrowingCtor<FixedArrWithAlloc>(kLargeSize); -} - -TEST(FixedArrayExceptionSafety, SizeValueConstructor) { - TestThrowingCtor<FixedArr>(kSmallSize, Thrower()); - TestThrowingCtor<FixedArr>(kLargeSize, Thrower()); -} - -TEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) { - TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower()); - TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower()); -} - -TEST(FixedArrayExceptionSafety, IteratorConstructor) { - auto small = FixedArr(kSmallSize); - TestThrowingCtor<FixedArr>(small.begin(), small.end()); - - auto large = FixedArr(kLargeSize); - TestThrowingCtor<FixedArr>(large.begin(), large.end()); -} - -TEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) { - auto small = FixedArrWithAlloc(kSmallSize); - TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end()); - - auto large = FixedArrWithAlloc(kLargeSize); - TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end()); -} - -TEST(FixedArrayExceptionSafety, InitListConstructor) { - constexpr int small_inlined = 3; - using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>; - - TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{}); - // Test inlined allocation - TestThrowingCtor<SmallFixedArr>( - std::initializer_list<Thrower>{Thrower{}, Thrower{}}); - // Test out of line allocation - TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{ - Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}}); -} - -TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) { - constexpr int small_inlined = 3; - using SmallFixedArrWithAlloc = - absl::FixedArray<Thrower, small_inlined, ThrowAlloc>; - - TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{}); - // Test inlined allocation - TestThrowingCtor<SmallFixedArrWithAlloc>( - std::initializer_list<Thrower>{Thrower{}, Thrower{}}); - // Test out of line allocation - TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{ - Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}}); -} - -template <typename FixedArrT> -testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) { - int sum = 0; - for (const auto& thrower : *fixed_arr) { - sum += thrower.Get(); - } - return testing::AssertionSuccess() << "Values sum to [" << sum << "]"; -} - -TEST(FixedArrayExceptionSafety, Fill) { - auto test_fill = testing::MakeExceptionSafetyTester() - .WithContracts(ReadMemory<FixedArr>) - .WithOperation([&](FixedArr* fixed_arr_ptr) { - auto thrower = - Thrower(kUpdatedValue, testing::nothrow_ctor); - fixed_arr_ptr->fill(thrower); - }); - - EXPECT_TRUE( - test_fill.WithInitialValue(FixedArr(kSmallSize, Thrower(kInitialValue))) - .Test()); - EXPECT_TRUE( - test_fill.WithInitialValue(FixedArr(kLargeSize, Thrower(kInitialValue))) - .Test()); -} - -TEST(FixedArrayExceptionSafety, FillWithAlloc) { - auto test_fill = testing::MakeExceptionSafetyTester() - .WithContracts(ReadMemory<FixedArrWithAlloc>) - .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) { - auto thrower = - Thrower(kUpdatedValue, testing::nothrow_ctor); - fixed_arr_ptr->fill(thrower); - }); - - EXPECT_TRUE(test_fill - .WithInitialValue( - FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue))) - .Test()); - EXPECT_TRUE(test_fill - .WithInitialValue( - FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue))) - .Test()); -} - -} // namespace - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_EXCEPTIONS diff --git a/third_party/abseil_cpp/absl/container/fixed_array_test.cc b/third_party/abseil_cpp/absl/container/fixed_array_test.cc deleted file mode 100644 index 49598e7a053c..000000000000 --- a/third_party/abseil_cpp/absl/container/fixed_array_test.cc +++ /dev/null @@ -1,837 +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/container/fixed_array.h" - -#include <stdio.h> - -#include <cstring> -#include <list> -#include <memory> -#include <numeric> -#include <scoped_allocator> -#include <stdexcept> -#include <string> -#include <vector> - -#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" - -using ::testing::ElementsAreArray; - -namespace { - -// Helper routine to determine if a absl::FixedArray used stack allocation. -template <typename ArrayType> -static bool IsOnStack(const ArrayType& a) { - return a.size() <= ArrayType::inline_elements; -} - -class ConstructionTester { - public: - ConstructionTester() : self_ptr_(this), value_(0) { constructions++; } - ~ConstructionTester() { - assert(self_ptr_ == this); - self_ptr_ = nullptr; - destructions++; - } - - // These are incremented as elements are constructed and destructed so we can - // be sure all elements are properly cleaned up. - static int constructions; - static int destructions; - - void CheckConstructed() { assert(self_ptr_ == this); } - - void set(int value) { value_ = value; } - int get() { return value_; } - - private: - // self_ptr_ should always point to 'this' -- that's how we can be sure the - // constructor has been called. - ConstructionTester* self_ptr_; - int value_; -}; - -int ConstructionTester::constructions = 0; -int ConstructionTester::destructions = 0; - -// ThreeInts will initialize its three ints to the value stored in -// ThreeInts::counter. The constructor increments counter so that each object -// in an array of ThreeInts will have different values. -class ThreeInts { - public: - ThreeInts() { - x_ = counter; - y_ = counter; - z_ = counter; - ++counter; - } - - static int counter; - - int x_, y_, z_; -}; - -int ThreeInts::counter = 0; - -TEST(FixedArrayTest, CopyCtor) { - absl::FixedArray<int, 10> on_stack(5); - std::iota(on_stack.begin(), on_stack.end(), 0); - absl::FixedArray<int, 10> stack_copy = on_stack; - EXPECT_THAT(stack_copy, ElementsAreArray(on_stack)); - EXPECT_TRUE(IsOnStack(stack_copy)); - - absl::FixedArray<int, 10> allocated(15); - std::iota(allocated.begin(), allocated.end(), 0); - absl::FixedArray<int, 10> alloced_copy = allocated; - EXPECT_THAT(alloced_copy, ElementsAreArray(allocated)); - EXPECT_FALSE(IsOnStack(alloced_copy)); -} - -TEST(FixedArrayTest, MoveCtor) { - absl::FixedArray<std::unique_ptr<int>, 10> on_stack(5); - for (int i = 0; i < 5; ++i) { - on_stack[i] = absl::make_unique<int>(i); - } - - absl::FixedArray<std::unique_ptr<int>, 10> stack_copy = std::move(on_stack); - for (int i = 0; i < 5; ++i) EXPECT_EQ(*(stack_copy[i]), i); - EXPECT_EQ(stack_copy.size(), on_stack.size()); - - absl::FixedArray<std::unique_ptr<int>, 10> allocated(15); - for (int i = 0; i < 15; ++i) { - allocated[i] = absl::make_unique<int>(i); - } - - absl::FixedArray<std::unique_ptr<int>, 10> alloced_copy = - std::move(allocated); - for (int i = 0; i < 15; ++i) EXPECT_EQ(*(alloced_copy[i]), i); - EXPECT_EQ(allocated.size(), alloced_copy.size()); -} - -TEST(FixedArrayTest, SmallObjects) { - // Small object arrays - { - // Short arrays should be on the stack - absl::FixedArray<int> array(4); - EXPECT_TRUE(IsOnStack(array)); - } - - { - // Large arrays should be on the heap - absl::FixedArray<int> array(1048576); - EXPECT_FALSE(IsOnStack(array)); - } - - { - // Arrays of <= default size should be on the stack - absl::FixedArray<int, 100> array(100); - EXPECT_TRUE(IsOnStack(array)); - } - - { - // Arrays of > default size should be on the heap - absl::FixedArray<int, 100> array(101); - EXPECT_FALSE(IsOnStack(array)); - } - - { - // Arrays with different size elements should use approximately - // same amount of stack space - absl::FixedArray<int> array1(0); - absl::FixedArray<char> array2(0); - EXPECT_LE(sizeof(array1), sizeof(array2) + 100); - EXPECT_LE(sizeof(array2), sizeof(array1) + 100); - } - - { - // Ensure that vectors are properly constructed inside a fixed array. - absl::FixedArray<std::vector<int>> array(2); - EXPECT_EQ(0, array[0].size()); - EXPECT_EQ(0, array[1].size()); - } - - { - // Regardless of absl::FixedArray implementation, check that a type with a - // low alignment requirement and a non power-of-two size is initialized - // correctly. - ThreeInts::counter = 1; - absl::FixedArray<ThreeInts> array(2); - EXPECT_EQ(1, array[0].x_); - EXPECT_EQ(1, array[0].y_); - EXPECT_EQ(1, array[0].z_); - EXPECT_EQ(2, array[1].x_); - EXPECT_EQ(2, array[1].y_); - EXPECT_EQ(2, array[1].z_); - } -} - -TEST(FixedArrayTest, AtThrows) { - absl::FixedArray<int> a = {1, 2, 3}; - EXPECT_EQ(a.at(2), 3); - ABSL_BASE_INTERNAL_EXPECT_FAIL(a.at(3), std::out_of_range, - "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); - std::iota(a1.begin(), a1.end(), 0); - absl::FixedArray<int, 5> a2(a1.begin(), a1.end()); - - EXPECT_TRUE(a1 == a2); - EXPECT_FALSE(a1 != a2); - EXPECT_TRUE(a2 == a1); - EXPECT_FALSE(a2 != a1); - EXPECT_FALSE(a1 < a2); - EXPECT_FALSE(a1 > a2); - EXPECT_FALSE(a2 < a1); - EXPECT_FALSE(a2 > a1); - EXPECT_TRUE(a1 <= a2); - EXPECT_TRUE(a1 >= a2); - EXPECT_TRUE(a2 <= a1); - EXPECT_TRUE(a2 >= a1); - } -} - -TEST(FixedArrayRelationalsTest, UnequalArrays) { - for (int i = 1; i < 10; ++i) { - absl::FixedArray<int, 5> a1(i); - std::iota(a1.begin(), a1.end(), 0); - absl::FixedArray<int, 5> a2(a1.begin(), a1.end()); - --a2[i / 2]; - - EXPECT_FALSE(a1 == a2); - EXPECT_TRUE(a1 != a2); - EXPECT_FALSE(a2 == a1); - EXPECT_TRUE(a2 != a1); - EXPECT_FALSE(a1 < a2); - EXPECT_TRUE(a1 > a2); - EXPECT_TRUE(a2 < a1); - EXPECT_FALSE(a2 > a1); - EXPECT_FALSE(a1 <= a2); - EXPECT_TRUE(a1 >= a2); - EXPECT_TRUE(a2 <= a1); - EXPECT_FALSE(a2 >= a1); - } -} - -template <int stack_elements> -static void TestArray(int n) { - SCOPED_TRACE(n); - SCOPED_TRACE(stack_elements); - ConstructionTester::constructions = 0; - ConstructionTester::destructions = 0; - { - absl::FixedArray<ConstructionTester, stack_elements> array(n); - - EXPECT_THAT(array.size(), n); - EXPECT_THAT(array.memsize(), sizeof(ConstructionTester) * n); - EXPECT_THAT(array.begin() + n, array.end()); - - // Check that all elements were constructed - for (int i = 0; i < n; i++) { - array[i].CheckConstructed(); - } - // Check that no other elements were constructed - EXPECT_THAT(ConstructionTester::constructions, n); - - // Test operator[] - for (int i = 0; i < n; i++) { - array[i].set(i); - } - for (int i = 0; i < n; i++) { - EXPECT_THAT(array[i].get(), i); - EXPECT_THAT(array.data()[i].get(), i); - } - - // Test data() - for (int i = 0; i < n; i++) { - array.data()[i].set(i + 1); - } - for (int i = 0; i < n; i++) { - EXPECT_THAT(array[i].get(), i + 1); - EXPECT_THAT(array.data()[i].get(), i + 1); - } - } // Close scope containing 'array'. - - // Check that all constructed elements were destructed. - EXPECT_EQ(ConstructionTester::constructions, - ConstructionTester::destructions); -} - -template <int elements_per_inner_array, int inline_elements> -static void TestArrayOfArrays(int n) { - SCOPED_TRACE(n); - SCOPED_TRACE(inline_elements); - SCOPED_TRACE(elements_per_inner_array); - ConstructionTester::constructions = 0; - ConstructionTester::destructions = 0; - { - using InnerArray = ConstructionTester[elements_per_inner_array]; - // Heap-allocate the FixedArray to avoid blowing the stack frame. - auto array_ptr = - absl::make_unique<absl::FixedArray<InnerArray, inline_elements>>(n); - auto& array = *array_ptr; - - ASSERT_EQ(array.size(), n); - ASSERT_EQ(array.memsize(), - sizeof(ConstructionTester) * elements_per_inner_array * n); - ASSERT_EQ(array.begin() + n, array.end()); - - // Check that all elements were constructed - for (int i = 0; i < n; i++) { - for (int j = 0; j < elements_per_inner_array; j++) { - (array[i])[j].CheckConstructed(); - } - } - // Check that no other elements were constructed - ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array); - - // Test operator[] - for (int i = 0; i < n; i++) { - for (int j = 0; j < elements_per_inner_array; j++) { - (array[i])[j].set(i * elements_per_inner_array + j); - } - } - for (int i = 0; i < n; i++) { - for (int j = 0; j < elements_per_inner_array; j++) { - ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j); - ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j); - } - } - - // Test data() - for (int i = 0; i < n; i++) { - for (int j = 0; j < elements_per_inner_array; j++) { - (array.data()[i])[j].set((i + 1) * elements_per_inner_array + j); - } - } - for (int i = 0; i < n; i++) { - for (int j = 0; j < elements_per_inner_array; j++) { - ASSERT_EQ((array[i])[j].get(), (i + 1) * elements_per_inner_array + j); - ASSERT_EQ((array.data()[i])[j].get(), - (i + 1) * elements_per_inner_array + j); - } - } - } // Close scope containing 'array'. - - // Check that all constructed elements were destructed. - EXPECT_EQ(ConstructionTester::constructions, - ConstructionTester::destructions); -} - -TEST(IteratorConstructorTest, NonInline) { - int const kInput[] = {2, 3, 5, 7, 11, 13, 17}; - absl::FixedArray<int, ABSL_ARRAYSIZE(kInput) - 1> const fixed( - kInput, kInput + ABSL_ARRAYSIZE(kInput)); - ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size()); - for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) { - ASSERT_EQ(kInput[i], fixed[i]); - } -} - -TEST(IteratorConstructorTest, Inline) { - int const kInput[] = {2, 3, 5, 7, 11, 13, 17}; - absl::FixedArray<int, ABSL_ARRAYSIZE(kInput)> const fixed( - kInput, kInput + ABSL_ARRAYSIZE(kInput)); - ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size()); - for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) { - ASSERT_EQ(kInput[i], fixed[i]); - } -} - -TEST(IteratorConstructorTest, NonPod) { - char const* kInput[] = {"red", "orange", "yellow", "green", - "blue", "indigo", "violet"}; - absl::FixedArray<std::string> const fixed(kInput, - kInput + ABSL_ARRAYSIZE(kInput)); - ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size()); - for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) { - ASSERT_EQ(kInput[i], fixed[i]); - } -} - -TEST(IteratorConstructorTest, FromEmptyVector) { - std::vector<int> const empty; - absl::FixedArray<int> const fixed(empty.begin(), empty.end()); - EXPECT_EQ(0, fixed.size()); - EXPECT_EQ(empty.size(), fixed.size()); -} - -TEST(IteratorConstructorTest, FromNonEmptyVector) { - int const kInput[] = {2, 3, 5, 7, 11, 13, 17}; - std::vector<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput)); - absl::FixedArray<int> const fixed(items.begin(), items.end()); - ASSERT_EQ(items.size(), fixed.size()); - for (size_t i = 0; i < items.size(); ++i) { - ASSERT_EQ(items[i], fixed[i]); - } -} - -TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) { - int const kInput[] = {2, 3, 5, 7, 11, 13, 17}; - std::list<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput)); - absl::FixedArray<int> const fixed(items.begin(), items.end()); - EXPECT_THAT(fixed, testing::ElementsAreArray(kInput)); -} - -TEST(InitListConstructorTest, InitListConstruction) { - absl::FixedArray<int> fixed = {1, 2, 3}; - EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3})); -} - -TEST(FillConstructorTest, NonEmptyArrays) { - absl::FixedArray<int> stack_array(4, 1); - EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1})); - - absl::FixedArray<int, 0> heap_array(4, 1); - EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1})); -} - -TEST(FillConstructorTest, EmptyArray) { - absl::FixedArray<int> empty_fill(0, 1); - absl::FixedArray<int> empty_size(0); - EXPECT_EQ(empty_fill, empty_size); -} - -TEST(FillConstructorTest, NotTriviallyCopyable) { - std::string str = "abcd"; - absl::FixedArray<std::string> strings = {str, str, str, str}; - - absl::FixedArray<std::string> array(4, str); - EXPECT_EQ(array, strings); -} - -TEST(FillConstructorTest, Disambiguation) { - absl::FixedArray<size_t> a(1, 2); - EXPECT_THAT(a, testing::ElementsAre(2)); -} - -TEST(FixedArrayTest, ManySizedArrays) { - std::vector<int> sizes; - for (int i = 1; i < 100; i++) sizes.push_back(i); - for (int i = 100; i <= 1000; i += 100) sizes.push_back(i); - for (int n : sizes) { - TestArray<0>(n); - TestArray<1>(n); - TestArray<64>(n); - TestArray<1000>(n); - } -} - -TEST(FixedArrayTest, ManySizedArraysOfArraysOf1) { - for (int n = 1; n < 1000; n++) { - ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n))); - ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n))); - ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n))); - ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n))); - } -} - -TEST(FixedArrayTest, ManySizedArraysOfArraysOf2) { - for (int n = 1; n < 1000; n++) { - TestArrayOfArrays<2, 0>(n); - TestArrayOfArrays<2, 1>(n); - TestArrayOfArrays<2, 64>(n); - TestArrayOfArrays<2, 1000>(n); - } -} - -// If value_type is put inside of a struct container, -// we might evoke this error in a hardened build unless data() is carefully -// written, so check on that. -// error: call to int __builtin___sprintf_chk(etc...) -// will always overflow destination buffer [-Werror] -TEST(FixedArrayTest, AvoidParanoidDiagnostics) { - absl::FixedArray<char, 32> buf(32); - sprintf(buf.data(), "foo"); // NOLINT(runtime/printf) -} - -TEST(FixedArrayTest, TooBigInlinedSpace) { - struct TooBig { - char c[1 << 20]; - }; // too big for even one on the stack - - // Simulate the data members of absl::FixedArray, a pointer and a size_t. - struct Data { - TooBig* p; - size_t size; - }; - - // Make sure TooBig objects are not inlined for 0 or default size. - static_assert(sizeof(absl::FixedArray<TooBig, 0>) == sizeof(Data), - "0-sized absl::FixedArray should have same size as Data."); - static_assert(alignof(absl::FixedArray<TooBig, 0>) == alignof(Data), - "0-sized absl::FixedArray should have same alignment as Data."); - static_assert(sizeof(absl::FixedArray<TooBig>) == sizeof(Data), - "default-sized absl::FixedArray should have same size as Data"); - static_assert( - alignof(absl::FixedArray<TooBig>) == alignof(Data), - "default-sized absl::FixedArray should have same alignment as Data."); -} - -// PickyDelete EXPECTs its class-scope deallocation funcs are unused. -struct PickyDelete { - PickyDelete() {} - ~PickyDelete() {} - void operator delete(void* p) { - EXPECT_TRUE(false) << __FUNCTION__; - ::operator delete(p); - } - void operator delete[](void* p) { - EXPECT_TRUE(false) << __FUNCTION__; - ::operator delete[](p); - } -}; - -TEST(FixedArrayTest, UsesGlobalAlloc) { absl::FixedArray<PickyDelete, 0> a(5); } - -TEST(FixedArrayTest, Data) { - static const int kInput[] = {2, 3, 5, 7, 11, 13, 17}; - absl::FixedArray<int> fa(std::begin(kInput), std::end(kInput)); - EXPECT_EQ(fa.data(), &*fa.begin()); - EXPECT_EQ(fa.data(), &fa[0]); - - const absl::FixedArray<int>& cfa = fa; - EXPECT_EQ(cfa.data(), &*cfa.begin()); - EXPECT_EQ(cfa.data(), &cfa[0]); -} - -TEST(FixedArrayTest, Empty) { - absl::FixedArray<int> empty(0); - absl::FixedArray<int> inline_filled(1); - absl::FixedArray<int, 0> heap_filled(1); - EXPECT_TRUE(empty.empty()); - EXPECT_FALSE(inline_filled.empty()); - EXPECT_FALSE(heap_filled.empty()); -} - -TEST(FixedArrayTest, FrontAndBack) { - absl::FixedArray<int, 3 * sizeof(int)> inlined = {1, 2, 3}; - EXPECT_EQ(inlined.front(), 1); - EXPECT_EQ(inlined.back(), 3); - - absl::FixedArray<int, 0> allocated = {1, 2, 3}; - EXPECT_EQ(allocated.front(), 1); - EXPECT_EQ(allocated.back(), 3); - - absl::FixedArray<int> one_element = {1}; - EXPECT_EQ(one_element.front(), one_element.back()); -} - -TEST(FixedArrayTest, ReverseIteratorInlined) { - absl::FixedArray<int, 5 * sizeof(int)> a = {0, 1, 2, 3, 4}; - - int counter = 5; - for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin(); - iter != a.rend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = 5; - for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin(); - iter != a.rend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = 5; - for (auto iter = a.crbegin(); iter != a.crend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); -} - -TEST(FixedArrayTest, ReverseIteratorAllocated) { - absl::FixedArray<int, 0> a = {0, 1, 2, 3, 4}; - - int counter = 5; - for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin(); - iter != a.rend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = 5; - for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin(); - iter != a.rend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = 5; - for (auto iter = a.crbegin(); iter != a.crend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); -} - -TEST(FixedArrayTest, Fill) { - absl::FixedArray<int, 5 * sizeof(int)> inlined(5); - int fill_val = 42; - inlined.fill(fill_val); - for (int i : inlined) EXPECT_EQ(i, fill_val); - - absl::FixedArray<int, 0> allocated(5); - allocated.fill(fill_val); - for (int i : allocated) EXPECT_EQ(i, fill_val); - - // It doesn't do anything, just make sure this compiles. - absl::FixedArray<int> empty(0); - empty.fill(fill_val); -} - -#ifndef __GNUC__ -TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) { - using T = char; - constexpr auto capacity = 10; - using FixedArrType = absl::FixedArray<T, capacity>; - constexpr auto scrubbed_bits = 0x95; - constexpr auto length = capacity / 2; - - alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)]; - std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType)); - - FixedArrType* arr = - ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length); - EXPECT_THAT(*arr, testing::Each(scrubbed_bits)); - arr->~FixedArrType(); -} -#endif // __GNUC__ - -TEST(AllocatorSupportTest, CountInlineAllocations) { - constexpr size_t inlined_size = 4; - using Alloc = absl::container_internal::CountingAllocator<int>; - using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; - - int64_t allocated = 0; - int64_t active_instances = 0; - - { - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; - - Alloc alloc(&allocated, &active_instances); - - AllocFxdArr arr(ia, ia + inlined_size, alloc); - static_cast<void>(arr); - } - - EXPECT_EQ(allocated, 0); - EXPECT_EQ(active_instances, 0); -} - -TEST(AllocatorSupportTest, CountOutoflineAllocations) { - constexpr size_t inlined_size = 4; - using Alloc = absl::container_internal::CountingAllocator<int>; - using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; - - int64_t allocated = 0; - int64_t active_instances = 0; - - { - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; - Alloc alloc(&allocated, &active_instances); - - AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc); - - EXPECT_EQ(allocated, arr.size() * sizeof(int)); - static_cast<void>(arr); - } - - EXPECT_EQ(active_instances, 0); -} - -TEST(AllocatorSupportTest, CountCopyInlineAllocations) { - constexpr size_t inlined_size = 4; - using Alloc = absl::container_internal::CountingAllocator<int>; - using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; - - int64_t allocated1 = 0; - int64_t allocated2 = 0; - int64_t active_instances = 0; - Alloc alloc(&allocated1, &active_instances); - Alloc alloc2(&allocated2, &active_instances); - - { - int initial_value = 1; - - AllocFxdArr arr1(inlined_size / 2, initial_value, alloc); - - EXPECT_EQ(allocated1, 0); - - AllocFxdArr arr2(arr1, alloc2); - - EXPECT_EQ(allocated2, 0); - static_cast<void>(arr1); - static_cast<void>(arr2); - } - - EXPECT_EQ(active_instances, 0); -} - -TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) { - constexpr size_t inlined_size = 4; - using Alloc = absl::container_internal::CountingAllocator<int>; - using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; - - int64_t allocated1 = 0; - int64_t allocated2 = 0; - int64_t active_instances = 0; - Alloc alloc(&allocated1, &active_instances); - Alloc alloc2(&allocated2, &active_instances); - - { - int initial_value = 1; - - AllocFxdArr arr1(inlined_size * 2, initial_value, alloc); - - EXPECT_EQ(allocated1, arr1.size() * sizeof(int)); - - AllocFxdArr arr2(arr1, alloc2); - - EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int)); - static_cast<void>(arr1); - static_cast<void>(arr2); - } - - EXPECT_EQ(active_instances, 0); -} - -TEST(AllocatorSupportTest, SizeValAllocConstructor) { - using testing::AllOf; - using testing::Each; - using testing::SizeIs; - - constexpr size_t inlined_size = 4; - using Alloc = absl::container_internal::CountingAllocator<int>; - using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; - - { - auto len = inlined_size / 2; - auto val = 0; - int64_t allocated = 0; - AllocFxdArr arr(len, val, Alloc(&allocated)); - - EXPECT_EQ(allocated, 0); - EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0))); - } - - { - auto len = inlined_size * 2; - auto val = 0; - int64_t allocated = 0; - AllocFxdArr arr(len, val, Alloc(&allocated)); - - EXPECT_EQ(allocated, len * sizeof(int)); - EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0))); - } -} - -#ifdef ABSL_HAVE_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"); -} - -TEST(FixedArrayTest, AddressSanitizerAnnotations2) { - absl::FixedArray<char, 17> a(12); - 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"); -} - -TEST(FixedArrayTest, AddressSanitizerAnnotations3) { - absl::FixedArray<uint64_t, 20> a(20); - 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"); -} - -TEST(FixedArrayTest, AddressSanitizerAnnotations4) { - absl::FixedArray<ThreeInts> a(10); - ThreeInts* raw = a.data(); - raw[0] = ThreeInts(); - raw[9] = ThreeInts(); - // Note: raw[-1] is pointing to 12 bytes before the container range. However, - // there is only a 8-byte red zone before the container range, so we only - // access the last 4 bytes of the struct to make sure it stays within the red - // zone. - EXPECT_DEATH_IF_SUPPORTED(raw[-1].z_ = 0, "container-overflow"); - EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), "container-overflow"); - // The actual size of storage is kDefaultBytes=256, 21*12 = 252, - // so reading raw[21] should still trigger the correct warning. - EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow"); -} -#endif // ABSL_HAVE_ADDRESS_SANITIZER - -TEST(FixedArrayTest, AbslHashValueWorks) { - using V = absl::FixedArray<int>; - std::vector<V> cases; - - // Generate a variety of vectors some of these are small enough for the inline - // space but are stored out of line. - for (int i = 0; i < 10; ++i) { - V v(i); - for (int j = 0; j < i; ++j) { - v[j] = j; - } - cases.push_back(v); - } - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/container/flat_hash_map.h b/third_party/abseil_cpp/absl/container/flat_hash_map.h deleted file mode 100644 index 74def0df0e33..000000000000 --- a/third_party/abseil_cpp/absl/container/flat_hash_map.h +++ /dev/null @@ -1,606 +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: flat_hash_map.h -// ----------------------------------------------------------------------------- -// -// An `absl::flat_hash_map<K, V>` is an unordered associative container of -// unique keys and associated values designed to be a more efficient replacement -// for `std::unordered_map`. Like `unordered_map`, search, insertion, and -// deletion of map elements can be done as an `O(1)` operation. However, -// `flat_hash_map` (and other unordered associative containers known as the -// collection of Abseil "Swiss tables") contain other optimizations that result -// in both memory and computation advantages. -// -// In most cases, your default choice for a hash map should be a map of type -// `flat_hash_map`. - -#ifndef ABSL_CONTAINER_FLAT_HASH_MAP_H_ -#define ABSL_CONTAINER_FLAT_HASH_MAP_H_ - -#include <cstddef> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/algorithm/container.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export -#include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -template <class K, class V> -struct FlatHashMapPolicy; -} // namespace container_internal - -// ----------------------------------------------------------------------------- -// absl::flat_hash_map -// ----------------------------------------------------------------------------- -// -// An `absl::flat_hash_map<K, V>` is an unordered associative container which -// has been optimized for both speed and memory footprint in most common use -// cases. Its interface is similar to that of `std::unordered_map<K, V>` with -// the following notable differences: -// -// * Requires keys that are CopyConstructible -// * Requires values that are MoveConstructible -// * Supports heterogeneous lookup, through `find()`, `operator[]()` and -// `insert()`, provided that the map is provided a compatible heterogeneous -// hashing function and equality operator. -// * Invalidates any references and pointers to elements within the table after -// `rehash()`. -// * Contains a `capacity()` member function indicating the number of element -// slots (open, deleted, and empty) within the hash map. -// * Returns `void` from the `erase(iterator)` overload. -// -// By default, `flat_hash_map` uses the `absl::Hash` hashing framework. -// All fundamental and Abseil types that support the `absl::Hash` framework have -// a compatible equality operator for comparing insertions into `flat_hash_map`. -// If your type is not yet supported by the `absl::Hash` framework, see -// absl/hash/hash.h for information on extending Abseil hashing to user-defined -// types. -// -// NOTE: A `flat_hash_map` stores its value types directly inside its -// implementation array to avoid memory indirection. Because a `flat_hash_map` -// is designed to move data when rehashed, map values will not retain pointer -// stability. If you require pointer stability, or if your values are large, -// consider using `absl::flat_hash_map<Key, std::unique_ptr<Value>>` instead. -// If your types are not moveable or you require pointer stability for keys, -// consider `absl::node_hash_map`. -// -// Example: -// -// // Create a flat hash map of three strings (that map to strings) -// absl::flat_hash_map<std::string, std::string> ducks = -// {{"a", "huey"}, {"b", "dewey"}, {"c", "louie"}}; -// -// // Insert a new element into the flat hash map -// ducks.insert({"d", "donald"}); -// -// // Force a rehash of the flat hash map -// ducks.rehash(0); -// -// // Find the element with the key "b" -// std::string search_key = "b"; -// auto result = ducks.find(search_key); -// if (result != ducks.end()) { -// std::cout << "Result: " << result->second << std::endl; -// } -template <class K, class V, - class Hash = absl::container_internal::hash_default_hash<K>, - class Eq = absl::container_internal::hash_default_eq<K>, - class Allocator = std::allocator<std::pair<const K, V>>> -class flat_hash_map : public absl::container_internal::raw_hash_map< - absl::container_internal::FlatHashMapPolicy<K, V>, - Hash, Eq, Allocator> { - using Base = typename flat_hash_map::raw_hash_map; - - public: - // Constructors and Assignment Operators - // - // A flat_hash_map supports the same overload set as `std::unordered_map` - // for construction and assignment: - // - // * Default constructor - // - // // No allocation for the table's elements is made. - // absl::flat_hash_map<int, std::string> map1; - // - // * Initializer List constructor - // - // absl::flat_hash_map<int, std::string> map2 = - // {{1, "huey"}, {2, "dewey"}, {3, "louie"},}; - // - // * Copy constructor - // - // absl::flat_hash_map<int, std::string> map3(map2); - // - // * Copy assignment operator - // - // // Hash functor and Comparator are copied as well - // absl::flat_hash_map<int, std::string> map4; - // map4 = map3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::flat_hash_map<int, std::string> map5(std::move(map4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::flat_hash_map<int, std::string> map6; - // map6 = std::move(map5); - // - // * Range constructor - // - // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; - // absl::flat_hash_map<int, std::string> map7(v.begin(), v.end()); - flat_hash_map() {} - using Base::Base; - - // flat_hash_map::begin() - // - // Returns an iterator to the beginning of the `flat_hash_map`. - using Base::begin; - - // flat_hash_map::cbegin() - // - // Returns a const iterator to the beginning of the `flat_hash_map`. - using Base::cbegin; - - // flat_hash_map::cend() - // - // Returns a const iterator to the end of the `flat_hash_map`. - using Base::cend; - - // flat_hash_map::end() - // - // Returns an iterator to the end of the `flat_hash_map`. - using Base::end; - - // flat_hash_map::capacity() - // - // Returns the number of element slots (assigned, deleted, and empty) - // available within the `flat_hash_map`. - // - // NOTE: this member function is particular to `absl::flat_hash_map` and is - // not provided in the `std::unordered_map` API. - using Base::capacity; - - // flat_hash_map::empty() - // - // Returns whether or not the `flat_hash_map` is empty. - using Base::empty; - - // flat_hash_map::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `flat_hash_map` under current memory constraints. This value can be thought - // of the largest value of `std::distance(begin(), end())` for a - // `flat_hash_map<K, V>`. - using Base::max_size; - - // flat_hash_map::size() - // - // Returns the number of elements currently within the `flat_hash_map`. - using Base::size; - - // flat_hash_map::clear() - // - // Removes all elements from the `flat_hash_map`. Invalidates any references, - // pointers, or iterators referring to contained elements. - // - // NOTE: this operation may shrink the underlying buffer. To avoid shrinking - // the underlying buffer call `erase(begin(), end())`. - using Base::clear; - - // flat_hash_map::erase() - // - // Erases elements within the `flat_hash_map`. Erasing does not trigger a - // rehash. Overloads are listed below. - // - // void erase(const_iterator pos): - // - // Erases the element at `position` of the `flat_hash_map`, returning - // `void`. - // - // NOTE: returning `void` in this case is different than that of STL - // containers in general and `std::unordered_map` in particular (which - // return an iterator to the element following the erased element). If that - // iterator is needed, simply post increment the iterator: - // - // map.erase(it++); - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning an - // iterator pointing to `last`. - // - // size_type erase(const key_type& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // flat_hash_map::insert() - // - // Inserts an element of the specified value into the `flat_hash_map`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If rehashing occurs - // due to the insertion, all iterators are invalidated. Overloads are listed - // below. - // - // std::pair<iterator,bool> insert(const init_type& value): - // - // Inserts a value into the `flat_hash_map`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a bool denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(T&& value): - // std::pair<iterator,bool> insert(init_type&& value): - // - // Inserts a moveable value into the `flat_hash_map`. Returns a pair - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a bool denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const init_type& value): - // iterator insert(const_iterator hint, T&& value): - // iterator insert(const_iterator hint, init_type&& value); - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently, for `flat_hash_map` we guarantee the - // first match is inserted. - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently within the initializer list, for - // `flat_hash_map` we guarantee the first match is inserted. - using Base::insert; - - // flat_hash_map::insert_or_assign() - // - // Inserts an element of the specified value into the `flat_hash_map` provided - // that a value with the given key does not already exist, or replaces it with - // the element value if a key for that value already exists, returning an - // iterator pointing to the newly inserted element. If rehashing occurs due - // to the insertion, all existing iterators are invalidated. Overloads are - // listed below. - // - // pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj): - // pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `flat_hash_map`. - // - // iterator insert_or_assign(const_iterator hint, - // const init_type& k, T&& obj): - // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `flat_hash_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - using Base::insert_or_assign; - - // flat_hash_map::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `flat_hash_map`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace; - - // flat_hash_map::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `flat_hash_map`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace_hint; - - // flat_hash_map::try_emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `flat_hash_map`, provided that no element with the given key - // already exists. Unlike `emplace()`, if an element with the given key - // already exists, we guarantee that no element is constructed. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - // Overloads are listed below. - // - // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args): - // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `flat_hash_map`. - // - // iterator try_emplace(const_iterator hint, - // const init_type& k, Args&&... args): - // iterator try_emplace(const_iterator hint, init_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `flat_hash_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - // - // All `try_emplace()` overloads make the same guarantees regarding rvalue - // arguments as `std::unordered_map::try_emplace()`, namely that these - // functions will not move from rvalue arguments if insertions do not happen. - using Base::try_emplace; - - // flat_hash_map::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the key,value pair of the element at the indicated position and - // returns a node handle owning that extracted data. - // - // node_type extract(const key_type& x): - // - // Extracts the key,value pair of the element with a key matching the passed - // key value and returns a node handle owning that extracted data. If the - // `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() - // - // Extracts elements from a given `source` flat hash map into this - // `flat_hash_map`. If the destination `flat_hash_map` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // flat_hash_map::swap(flat_hash_map& other) - // - // Exchanges the contents of this `flat_hash_map` with those of the `other` - // flat hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `flat_hash_map` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - // - // `swap()` requires that the flat hash map's hashing and key equivalence - // functions be Swappable, and are exchanged using unqualified calls to - // non-member `swap()`. If the map's allocator has - // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value` - // set to `true`, the allocators are also exchanged using an unqualified call - // to non-member `swap()`; otherwise, the allocators are not swapped. - using Base::swap; - - // flat_hash_map::rehash(count) - // - // Rehashes the `flat_hash_map`, setting the number of slots to be at least - // the passed value. If the new number of slots increases the load factor more - // than the current maximum load factor - // (`count` < `size()` / `max_load_factor()`), then the new number of slots - // will be at least `size()` / `max_load_factor()`. - // - // To force a rehash, pass rehash(0). - // - // NOTE: unlike behavior in `std::unordered_map`, references are also - // invalidated upon a `rehash()`. - using Base::rehash; - - // flat_hash_map::reserve(count) - // - // Sets the number of slots in the `flat_hash_map` to the number needed to - // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. - using Base::reserve; - - // flat_hash_map::at() - // - // Returns a reference to the mapped value of the element with key equivalent - // to the passed key. - using Base::at; - - // flat_hash_map::contains() - // - // Determines whether an element with a key comparing equal to the given `key` - // exists within the `flat_hash_map`, returning `true` if so or `false` - // otherwise. - using Base::contains; - - // flat_hash_map::count(const Key& key) const - // - // Returns the number of elements with a key comparing equal to the given - // `key` within the `flat_hash_map`. note that this function will return - // either `1` or `0` since duplicate keys are not allowed within a - // `flat_hash_map`. - using Base::count; - - // flat_hash_map::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `flat_hash_map`. - using Base::equal_range; - - // flat_hash_map::find() - // - // Finds an element with the passed `key` within the `flat_hash_map`. - using Base::find; - - // flat_hash_map::operator[]() - // - // Returns a reference to the value mapped to the passed key within the - // `flat_hash_map`, performing an `insert()` if the key does not already - // exist. - // - // If an insertion occurs and results in a rehashing of the container, all - // iterators are invalidated. Otherwise iterators are not affected and - // references are not invalidated. Overloads are listed below. - // - // T& operator[](const Key& key): - // - // Inserts an init_type object constructed in-place if the element with the - // given key does not exist. - // - // T& operator[](Key&& key): - // - // Inserts an init_type object constructed in-place provided that an element - // with the given key does not exist. - using Base::operator[]; - - // flat_hash_map::bucket_count() - // - // Returns the number of "buckets" within the `flat_hash_map`. Note that - // because a flat hash map contains all elements within its internal storage, - // this value simply equals the current capacity of the `flat_hash_map`. - using Base::bucket_count; - - // flat_hash_map::load_factor() - // - // Returns the current load factor of the `flat_hash_map` (the average number - // of slots occupied with a value within the hash map). - using Base::load_factor; - - // flat_hash_map::max_load_factor() - // - // Manages the maximum load factor of the `flat_hash_map`. Overloads are - // listed below. - // - // float flat_hash_map::max_load_factor() - // - // Returns the current maximum load factor of the `flat_hash_map`. - // - // void flat_hash_map::max_load_factor(float ml) - // - // Sets the maximum load factor of the `flat_hash_map` to the passed value. - // - // NOTE: This overload is provided only for API compatibility with the STL; - // `flat_hash_map` will ignore any set load factor and manage its rehashing - // internally as an implementation detail. - using Base::max_load_factor; - - // flat_hash_map::get_allocator() - // - // Returns the allocator function associated with this `flat_hash_map`. - using Base::get_allocator; - - // flat_hash_map::hash_function() - // - // Returns the hashing function used to hash the keys within this - // `flat_hash_map`. - using Base::hash_function; - - // flat_hash_map::key_eq() - // - // Returns the function used for comparing keys equality. - using Base::key_eq; -}; - -// erase_if(flat_hash_map<>, Pred) -// -// Erases all elements that satisfy the predicate `pred` from the container `c`. -template <typename K, typename V, typename H, typename E, typename A, - typename Predicate> -void erase_if(flat_hash_map<K, V, H, E, A>& c, Predicate pred) { - container_internal::EraseIf(pred, &c); -} - -namespace container_internal { - -template <class K, class V> -struct FlatHashMapPolicy { - using slot_policy = container_internal::map_slot_policy<K, V>; - using slot_type = typename slot_policy::slot_type; - using key_type = K; - using mapped_type = V; - using init_type = std::pair</*non const*/ key_type, mapped_type>; - - template <class Allocator, class... Args> - static void construct(Allocator* alloc, slot_type* slot, Args&&... args) { - slot_policy::construct(alloc, slot, std::forward<Args>(args)...); - } - - template <class Allocator> - static void destroy(Allocator* alloc, slot_type* slot) { - slot_policy::destroy(alloc, slot); - } - - template <class Allocator> - static void transfer(Allocator* alloc, slot_type* new_slot, - slot_type* old_slot) { - slot_policy::transfer(alloc, new_slot, old_slot); - } - - template <class F, class... Args> - static decltype(absl::container_internal::DecomposePair( - std::declval<F>(), std::declval<Args>()...)) - apply(F&& f, Args&&... args) { - return absl::container_internal::DecomposePair(std::forward<F>(f), - std::forward<Args>(args)...); - } - - static size_t space_used(const slot_type*) { return 0; } - - static std::pair<const K, V>& element(slot_type* slot) { return slot->value; } - - static V& value(std::pair<const K, V>* kv) { return kv->second; } - static const V& value(const std::pair<const K, V>* kv) { return kv->second; } -}; - -} // namespace container_internal - -namespace container_algorithm_internal { - -// Specialization of trait in absl/algorithm/container.h -template <class Key, class T, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer< - absl::flat_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {}; - -} // namespace container_algorithm_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_FLAT_HASH_MAP_H_ 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 deleted file mode 100644 index 89ec60c916ed..000000000000 --- a/third_party/abseil_cpp/absl/container/flat_hash_map_test.cc +++ /dev/null @@ -1,288 +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/flat_hash_map.h" - -#include <memory> - -#include "absl/base/internal/raw_logging.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/unordered_map_constructor_test.h" -#include "absl/container/internal/unordered_map_lookup_test.h" -#include "absl/container/internal/unordered_map_members_test.h" -#include "absl/container/internal/unordered_map_modifiers_test.h" -#include "absl/types/any.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { -using ::absl::container_internal::hash_internal::Enum; -using ::absl::container_internal::hash_internal::EnumClass; -using ::testing::_; -using ::testing::IsEmpty; -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -// Check that absl::flat_hash_map works in a global constructor. -struct BeforeMain { - BeforeMain() { - absl::flat_hash_map<int, int> x; - x.insert({1, 1}); - ABSL_RAW_CHECK(x.find(0) == x.end(), "x should not contain 0"); - auto it = x.find(1); - ABSL_RAW_CHECK(it != x.end(), "x should contain 1"); - ABSL_RAW_CHECK(it->second, "1 should map to 1"); - } -}; -const BeforeMain before_main; - -template <class K, class V> -using Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::pair<const K, V>>>; - -static_assert(!std::is_standard_layout<NonStandardLayout>(), ""); - -using MapTypes = - ::testing::Types<Map<int, int>, Map<std::string, int>, - Map<Enum, std::string>, Map<EnumClass, int>, - Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes); - -using UniquePtrMapTypes = ::testing::Types<Map<int, std::unique_ptr<int>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, UniquePtrModifiersTest, - UniquePtrMapTypes); - -TEST(FlatHashMap, StandardLayout) { - struct Int { - explicit Int(size_t value) : value(value) {} - Int() : value(0) { ADD_FAILURE(); } - Int(const Int& other) : value(other.value) { ADD_FAILURE(); } - Int(Int&&) = default; - bool operator==(const Int& other) const { return value == other.value; } - size_t value; - }; - static_assert(std::is_standard_layout<Int>(), ""); - - struct Hash { - size_t operator()(const Int& obj) const { return obj.value; } - }; - - // Verify that neither the key nor the value get default-constructed or - // copy-constructed. - { - flat_hash_map<Int, Int, Hash> m; - m.try_emplace(Int(1), Int(2)); - m.try_emplace(Int(3), Int(4)); - m.erase(Int(1)); - m.rehash(2 * m.bucket_count()); - } - { - flat_hash_map<Int, Int, Hash> m; - m.try_emplace(Int(1), Int(2)); - m.try_emplace(Int(3), Int(4)); - m.erase(Int(1)); - m.clear(); - } -} - -// gcc becomes unhappy if this is inside the method, so pull it out here. -struct balast {}; - -TEST(FlatHashMap, IteratesMsan) { - // Because SwissTable randomizes on pointer addresses, we keep old tables - // around to ensure we don't reuse old memory. - std::vector<absl::flat_hash_map<int, balast>> garbage; - for (int i = 0; i < 100; ++i) { - absl::flat_hash_map<int, balast> t; - for (int j = 0; j < 100; ++j) { - t[j]; - for (const auto& p : t) EXPECT_THAT(p, Pair(_, _)); - } - garbage.push_back(std::move(t)); - } -} - -// Demonstration of the "Lazy Key" pattern. This uses heterogeneous insert to -// avoid creating expensive key elements when the item is already present in the -// map. -struct LazyInt { - explicit LazyInt(size_t value, int* tracker) - : value(value), tracker(tracker) {} - - explicit operator size_t() const { - ++*tracker; - return value; - } - - size_t value; - int* tracker; -}; - -struct Hash { - using is_transparent = void; - int* tracker; - size_t operator()(size_t obj) const { - ++*tracker; - return obj; - } - size_t operator()(const LazyInt& obj) const { - ++*tracker; - return obj.value; - } -}; - -struct Eq { - using is_transparent = void; - bool operator()(size_t lhs, size_t rhs) const { - return lhs == rhs; - } - bool operator()(size_t lhs, const LazyInt& rhs) const { - return lhs == rhs.value; - } -}; - -TEST(FlatHashMap, LazyKeyPattern) { - // hashes are only guaranteed in opt mode, we use assertions to track internal - // state that can cause extra calls to hash. - int conversions = 0; - int hashes = 0; - flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes}); - m.reserve(3); - - m[LazyInt(1, &conversions)] = 1; - EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1))); - EXPECT_EQ(conversions, 1); -#ifdef NDEBUG - EXPECT_EQ(hashes, 1); -#endif - - m[LazyInt(1, &conversions)] = 2; - EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2))); - EXPECT_EQ(conversions, 1); -#ifdef NDEBUG - EXPECT_EQ(hashes, 2); -#endif - - m.try_emplace(LazyInt(2, &conversions), 3); - EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3))); - EXPECT_EQ(conversions, 2); -#ifdef NDEBUG - EXPECT_EQ(hashes, 3); -#endif - - m.try_emplace(LazyInt(2, &conversions), 4); - EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3))); - EXPECT_EQ(conversions, 2); -#ifdef NDEBUG - EXPECT_EQ(hashes, 4); -#endif -} - -TEST(FlatHashMap, BitfieldArgument) { - union { - int n : 1; - }; - n = 0; - flat_hash_map<int, int> m; - m.erase(n); - m.count(n); - m.prefetch(n); - m.find(n); - m.contains(n); - m.equal_range(n); - m.insert_or_assign(n, n); - m.insert_or_assign(m.end(), n, n); - m.try_emplace(n); - m.try_emplace(m.end(), n); - m.at(n); - m[n]; -} - -TEST(FlatHashMap, MergeExtractInsert) { - // We can't test mutable keys, or non-copyable keys with flat_hash_map. - // Test that the nodes have the proper API. - absl::flat_hash_map<int, int> m = {{1, 7}, {2, 9}}; - auto node = m.extract(1); - EXPECT_TRUE(node); - EXPECT_EQ(node.key(), 1); - EXPECT_EQ(node.mapped(), 7); - EXPECT_THAT(m, UnorderedElementsAre(Pair(2, 9))); - - node.mapped() = 17; - m.insert(std::move(node)); - EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9))); -} - -bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; } - -TEST(FlatHashMap, EraseIf) { - // Erase all elements. - { - flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, [](std::pair<const int, int>) { return true; }); - EXPECT_THAT(s, IsEmpty()); - } - // Erase no elements. - { - flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, [](std::pair<const int, int>) { return false; }); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), - Pair(4, 4), Pair(5, 5))); - } - // Erase specific elements. - { - flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, - [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; }); - EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); - } - // Predicate is function reference. - { - flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, FirstIsEven); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); - } - // Predicate is function pointer. - { - flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, &FirstIsEven); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); - } -} - -// This test requires std::launder for mutable key access in node handles. -#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 -TEST(FlatHashMap, NodeHandleMutableKeyAccess) { - flat_hash_map<std::string, std::string> map; - - map["key1"] = "mapped"; - - auto nh = map.extract(map.begin()); - nh.key().resize(3); - map.insert(std::move(nh)); - - EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped"))); -} -#endif - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/flat_hash_set.h b/third_party/abseil_cpp/absl/container/flat_hash_set.h deleted file mode 100644 index 6b89da65714c..000000000000 --- a/third_party/abseil_cpp/absl/container/flat_hash_set.h +++ /dev/null @@ -1,504 +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: flat_hash_set.h -// ----------------------------------------------------------------------------- -// -// An `absl::flat_hash_set<T>` is an unordered associative container designed to -// be a more efficient replacement for `std::unordered_set`. Like -// `unordered_set`, search, insertion, and deletion of set elements can be done -// as an `O(1)` operation. However, `flat_hash_set` (and other unordered -// associative containers known as the collection of Abseil "Swiss tables") -// contain other optimizations that result in both memory and computation -// advantages. -// -// In most cases, your default choice for a hash set should be a set of type -// `flat_hash_set`. -#ifndef ABSL_CONTAINER_FLAT_HASH_SET_H_ -#define ABSL_CONTAINER_FLAT_HASH_SET_H_ - -#include <type_traits> -#include <utility> - -#include "absl/algorithm/container.h" -#include "absl/base/macros.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export -#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -template <typename T> -struct FlatHashSetPolicy; -} // namespace container_internal - -// ----------------------------------------------------------------------------- -// absl::flat_hash_set -// ----------------------------------------------------------------------------- -// -// An `absl::flat_hash_set<T>` is an unordered associative container which has -// been optimized for both speed and memory footprint in most common use cases. -// Its interface is similar to that of `std::unordered_set<T>` with the -// following notable differences: -// -// * Requires keys that are CopyConstructible -// * Supports heterogeneous lookup, through `find()` and `insert()`, provided -// that the set is provided a compatible heterogeneous hashing function and -// equality operator. -// * Invalidates any references and pointers to elements within the table after -// `rehash()`. -// * Contains a `capacity()` member function indicating the number of element -// slots (open, deleted, and empty) within the hash set. -// * Returns `void` from the `erase(iterator)` overload. -// -// By default, `flat_hash_set` uses the `absl::Hash` hashing framework. All -// fundamental and Abseil types that support the `absl::Hash` framework have a -// compatible equality operator for comparing insertions into `flat_hash_map`. -// If your type is not yet supported by the `absl::Hash` framework, see -// absl/hash/hash.h for information on extending Abseil hashing to user-defined -// types. -// -// NOTE: A `flat_hash_set` stores its keys directly inside its implementation -// array to avoid memory indirection. Because a `flat_hash_set` is designed to -// move data when rehashed, set keys will not retain pointer stability. If you -// require pointer stability, consider using -// `absl::flat_hash_set<std::unique_ptr<T>>`. If your type is not moveable and -// you require pointer stability, consider `absl::node_hash_set` instead. -// -// Example: -// -// // Create a flat hash set of three strings -// absl::flat_hash_set<std::string> ducks = -// {"huey", "dewey", "louie"}; -// -// // Insert a new element into the flat hash set -// ducks.insert("donald"); -// -// // Force a rehash of the flat hash set -// ducks.rehash(0); -// -// // See if "dewey" is present -// if (ducks.contains("dewey")) { -// std::cout << "We found dewey!" << std::endl; -// } -template <class T, class Hash = absl::container_internal::hash_default_hash<T>, - class Eq = absl::container_internal::hash_default_eq<T>, - class Allocator = std::allocator<T>> -class flat_hash_set - : public absl::container_internal::raw_hash_set< - absl::container_internal::FlatHashSetPolicy<T>, Hash, Eq, Allocator> { - using Base = typename flat_hash_set::raw_hash_set; - - public: - // Constructors and Assignment Operators - // - // A flat_hash_set supports the same overload set as `std::unordered_map` - // for construction and assignment: - // - // * Default constructor - // - // // No allocation for the table's elements is made. - // absl::flat_hash_set<std::string> set1; - // - // * Initializer List constructor - // - // absl::flat_hash_set<std::string> set2 = - // {{"huey"}, {"dewey"}, {"louie"},}; - // - // * Copy constructor - // - // absl::flat_hash_set<std::string> set3(set2); - // - // * Copy assignment operator - // - // // Hash functor and Comparator are copied as well - // absl::flat_hash_set<std::string> set4; - // set4 = set3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::flat_hash_set<std::string> set5(std::move(set4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::flat_hash_set<std::string> set6; - // set6 = std::move(set5); - // - // * Range constructor - // - // std::vector<std::string> v = {"a", "b"}; - // absl::flat_hash_set<std::string> set7(v.begin(), v.end()); - flat_hash_set() {} - using Base::Base; - - // flat_hash_set::begin() - // - // Returns an iterator to the beginning of the `flat_hash_set`. - using Base::begin; - - // flat_hash_set::cbegin() - // - // Returns a const iterator to the beginning of the `flat_hash_set`. - using Base::cbegin; - - // flat_hash_set::cend() - // - // Returns a const iterator to the end of the `flat_hash_set`. - using Base::cend; - - // flat_hash_set::end() - // - // Returns an iterator to the end of the `flat_hash_set`. - using Base::end; - - // flat_hash_set::capacity() - // - // Returns the number of element slots (assigned, deleted, and empty) - // available within the `flat_hash_set`. - // - // NOTE: this member function is particular to `absl::flat_hash_set` and is - // not provided in the `std::unordered_map` API. - using Base::capacity; - - // flat_hash_set::empty() - // - // Returns whether or not the `flat_hash_set` is empty. - using Base::empty; - - // flat_hash_set::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `flat_hash_set` under current memory constraints. This value can be thought - // of the largest value of `std::distance(begin(), end())` for a - // `flat_hash_set<T>`. - using Base::max_size; - - // flat_hash_set::size() - // - // Returns the number of elements currently within the `flat_hash_set`. - using Base::size; - - // flat_hash_set::clear() - // - // Removes all elements from the `flat_hash_set`. Invalidates any references, - // pointers, or iterators referring to contained elements. - // - // NOTE: this operation may shrink the underlying buffer. To avoid shrinking - // the underlying buffer call `erase(begin(), end())`. - using Base::clear; - - // flat_hash_set::erase() - // - // Erases elements within the `flat_hash_set`. Erasing does not trigger a - // rehash. Overloads are listed below. - // - // void erase(const_iterator pos): - // - // Erases the element at `position` of the `flat_hash_set`, returning - // `void`. - // - // NOTE: returning `void` in this case is different than that of STL - // containers in general and `std::unordered_set` in particular (which - // return an iterator to the element following the erased element). If that - // iterator is needed, simply post increment the iterator: - // - // set.erase(it++); - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning an - // iterator pointing to `last`. - // - // size_type erase(const key_type& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // flat_hash_set::insert() - // - // Inserts an element of the specified value into the `flat_hash_set`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If rehashing occurs - // due to the insertion, all iterators are invalidated. Overloads are listed - // below. - // - // std::pair<iterator,bool> insert(const T& value): - // - // Inserts a value into the `flat_hash_set`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a bool denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(T&& value): - // - // Inserts a moveable value into the `flat_hash_set`. Returns a pair - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a bool denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const T& value): - // iterator insert(const_iterator hint, T&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently, for `flat_hash_set` we guarantee the - // first match is inserted. - // - // void insert(std::initializer_list<T> ilist): - // - // Inserts the elements within the initializer list `ilist`. - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently within the initializer list, for - // `flat_hash_set` we guarantee the first match is inserted. - using Base::insert; - - // flat_hash_set::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `flat_hash_set`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace; - - // flat_hash_set::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `flat_hash_set`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace_hint; - - // flat_hash_set::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // node_type extract(const key_type& x): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `flat_hash_set` - // does not contain an element with a matching key, this function returns an - // empty node handle. - using Base::extract; - - // flat_hash_set::merge() - // - // Extracts elements from a given `source` flat hash set into this - // `flat_hash_set`. If the destination `flat_hash_set` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // flat_hash_set::swap(flat_hash_set& other) - // - // Exchanges the contents of this `flat_hash_set` with those of the `other` - // flat hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `flat_hash_set` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - // - // `swap()` requires that the flat hash set's hashing and key equivalence - // functions be Swappable, and are exchaged using unqualified calls to - // non-member `swap()`. If the map's allocator has - // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value` - // set to `true`, the allocators are also exchanged using an unqualified call - // to non-member `swap()`; otherwise, the allocators are not swapped. - using Base::swap; - - // flat_hash_set::rehash(count) - // - // Rehashes the `flat_hash_set`, setting the number of slots to be at least - // the passed value. If the new number of slots increases the load factor more - // than the current maximum load factor - // (`count` < `size()` / `max_load_factor()`), then the new number of slots - // will be at least `size()` / `max_load_factor()`. - // - // To force a rehash, pass rehash(0). - // - // NOTE: unlike behavior in `std::unordered_set`, references are also - // invalidated upon a `rehash()`. - using Base::rehash; - - // flat_hash_set::reserve(count) - // - // Sets the number of slots in the `flat_hash_set` to the number needed to - // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. - using Base::reserve; - - // flat_hash_set::contains() - // - // Determines whether an element comparing equal to the given `key` exists - // within the `flat_hash_set`, returning `true` if so or `false` otherwise. - using Base::contains; - - // flat_hash_set::count(const Key& key) const - // - // Returns the number of elements comparing equal to the given `key` within - // the `flat_hash_set`. note that this function will return either `1` or `0` - // since duplicate elements are not allowed within a `flat_hash_set`. - using Base::count; - - // flat_hash_set::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `flat_hash_set`. - using Base::equal_range; - - // flat_hash_set::find() - // - // Finds an element with the passed `key` within the `flat_hash_set`. - using Base::find; - - // flat_hash_set::bucket_count() - // - // Returns the number of "buckets" within the `flat_hash_set`. Note that - // because a flat hash map contains all elements within its internal storage, - // this value simply equals the current capacity of the `flat_hash_set`. - using Base::bucket_count; - - // flat_hash_set::load_factor() - // - // Returns the current load factor of the `flat_hash_set` (the average number - // of slots occupied with a value within the hash map). - using Base::load_factor; - - // flat_hash_set::max_load_factor() - // - // Manages the maximum load factor of the `flat_hash_set`. Overloads are - // listed below. - // - // float flat_hash_set::max_load_factor() - // - // Returns the current maximum load factor of the `flat_hash_set`. - // - // void flat_hash_set::max_load_factor(float ml) - // - // Sets the maximum load factor of the `flat_hash_set` to the passed value. - // - // NOTE: This overload is provided only for API compatibility with the STL; - // `flat_hash_set` will ignore any set load factor and manage its rehashing - // internally as an implementation detail. - using Base::max_load_factor; - - // flat_hash_set::get_allocator() - // - // Returns the allocator function associated with this `flat_hash_set`. - using Base::get_allocator; - - // flat_hash_set::hash_function() - // - // Returns the hashing function used to hash the keys within this - // `flat_hash_set`. - using Base::hash_function; - - // flat_hash_set::key_eq() - // - // Returns the function used for comparing keys equality. - using Base::key_eq; -}; - -// erase_if(flat_hash_set<>, Pred) -// -// Erases all elements that satisfy the predicate `pred` from the container `c`. -template <typename T, typename H, typename E, typename A, typename Predicate> -void erase_if(flat_hash_set<T, H, E, A>& c, Predicate pred) { - container_internal::EraseIf(pred, &c); -} - -namespace container_internal { - -template <class T> -struct FlatHashSetPolicy { - using slot_type = T; - using key_type = T; - using init_type = T; - using constant_iterators = std::true_type; - - 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); - } - - template <class Allocator> - static void transfer(Allocator* alloc, slot_type* new_slot, - slot_type* old_slot) { - construct(alloc, new_slot, std::move(*old_slot)); - destroy(alloc, old_slot); - } - - static T& element(slot_type* slot) { return *slot; } - - template <class F, class... Args> - static decltype(absl::container_internal::DecomposeValue( - std::declval<F>(), std::declval<Args>()...)) - apply(F&& f, Args&&... args) { - return absl::container_internal::DecomposeValue( - std::forward<F>(f), std::forward<Args>(args)...); - } - - static size_t space_used(const T*) { return 0; } -}; -} // namespace container_internal - -namespace container_algorithm_internal { - -// Specialization of trait in absl/algorithm/container.h -template <class Key, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>> - : std::true_type {}; - -} // namespace container_algorithm_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_FLAT_HASH_SET_H_ 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 deleted file mode 100644 index 8f6f9944ca4e..000000000000 --- a/third_party/abseil_cpp/absl/container/flat_hash_set_test.cc +++ /dev/null @@ -1,178 +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/flat_hash_set.h" - -#include <vector> - -#include "absl/base/internal/raw_logging.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/unordered_set_constructor_test.h" -#include "absl/container/internal/unordered_set_lookup_test.h" -#include "absl/container/internal/unordered_set_members_test.h" -#include "absl/container/internal/unordered_set_modifiers_test.h" -#include "absl/memory/memory.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::absl::container_internal::hash_internal::Enum; -using ::absl::container_internal::hash_internal::EnumClass; -using ::testing::IsEmpty; -using ::testing::Pointee; -using ::testing::UnorderedElementsAre; -using ::testing::UnorderedElementsAreArray; - -// Check that absl::flat_hash_set works in a global constructor. -struct BeforeMain { - BeforeMain() { - absl::flat_hash_set<int> x; - x.insert(1); - ABSL_RAW_CHECK(!x.contains(0), "x should not contain 0"); - ABSL_RAW_CHECK(x.contains(1), "x should contain 1"); - } -}; -const BeforeMain before_main; - -template <class T> -using Set = - absl::flat_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>; - -using SetTypes = - ::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, MembersTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes); - -TEST(FlatHashSet, EmplaceString) { - std::vector<std::string> v = {"a", "b"}; - absl::flat_hash_set<absl::string_view> hs(v.begin(), v.end()); - EXPECT_THAT(hs, UnorderedElementsAreArray(v)); -} - -TEST(FlatHashSet, BitfieldArgument) { - union { - int n : 1; - }; - n = 0; - absl::flat_hash_set<int> s = {n}; - s.insert(n); - s.insert(s.end(), n); - s.insert({n}); - s.erase(n); - s.count(n); - s.prefetch(n); - s.find(n); - s.contains(n); - s.equal_range(n); -} - -TEST(FlatHashSet, MergeExtractInsert) { - struct Hash { - size_t operator()(const std::unique_ptr<int>& p) const { return *p; } - }; - struct Eq { - bool operator()(const std::unique_ptr<int>& a, - const std::unique_ptr<int>& b) const { - return *a == *b; - } - }; - absl::flat_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2; - set1.insert(absl::make_unique<int>(7)); - set1.insert(absl::make_unique<int>(17)); - - set2.insert(absl::make_unique<int>(7)); - set2.insert(absl::make_unique<int>(19)); - - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17))); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(19))); - - set1.merge(set2); - - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17), Pointee(19))); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7))); - - auto node = set1.extract(absl::make_unique<int>(7)); - EXPECT_TRUE(node); - EXPECT_THAT(node.value(), Pointee(7)); - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(17), Pointee(19))); - - auto insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_FALSE(insert_result.inserted); - EXPECT_TRUE(insert_result.node); - EXPECT_THAT(insert_result.node.value(), Pointee(7)); - EXPECT_EQ(**insert_result.position, 7); - EXPECT_NE(insert_result.position->get(), insert_result.node.value().get()); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7))); - - node = set1.extract(absl::make_unique<int>(17)); - EXPECT_TRUE(node); - EXPECT_THAT(node.value(), Pointee(17)); - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(19))); - - node.value() = absl::make_unique<int>(23); - - insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_TRUE(insert_result.inserted); - EXPECT_FALSE(insert_result.node); - EXPECT_EQ(**insert_result.position, 23); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23))); -} - -bool IsEven(int k) { return k % 2 == 0; } - -TEST(FlatHashSet, EraseIf) { - // Erase all elements. - { - flat_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int) { return true; }); - EXPECT_THAT(s, IsEmpty()); - } - // Erase no elements. - { - flat_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int) { return false; }); - EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); - } - // Erase specific elements. - { - flat_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int k) { return k % 2 == 1; }); - EXPECT_THAT(s, UnorderedElementsAre(2, 4)); - } - // Predicate is function reference. - { - flat_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, IsEven); - EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); - } - // Predicate is function pointer. - { - flat_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, &IsEven); - EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); - } -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/inlined_vector.h b/third_party/abseil_cpp/absl/container/inlined_vector.h deleted file mode 100644 index 90bb96e8325c..000000000000 --- a/third_party/abseil_cpp/absl/container/inlined_vector.h +++ /dev/null @@ -1,845 +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. -// -// ----------------------------------------------------------------------------- -// File: inlined_vector.h -// ----------------------------------------------------------------------------- -// -// This header file contains the declaration and definition of an "inlined -// vector" which behaves in an equivalent fashion to a `std::vector`, except -// that storage for small sequences of the vector are provided inline without -// requiring any heap allocation. -// -// An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of -// its template parameters. Instances where `size() <= N` hold contained -// elements in inline space. Typically `N` is very small so that sequences that -// are expected to be short do not require allocations. -// -// An `absl::InlinedVector` does not usually require a specific allocator. If -// the inlined vector grows beyond its initial constraints, it will need to -// allocate (as any normal `std::vector` would). This is usually performed with -// the default allocator (defined as `std::allocator<T>`). Optionally, a custom -// allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`. - -#ifndef ABSL_CONTAINER_INLINED_VECTOR_H_ -#define ABSL_CONTAINER_INLINED_VECTOR_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdlib> -#include <cstring> -#include <initializer_list> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> - -#include "absl/algorithm/algorithm.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" -#include "absl/container/internal/inlined_vector.h" -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -// ----------------------------------------------------------------------------- -// InlinedVector -// ----------------------------------------------------------------------------- -// -// An `absl::InlinedVector` is designed to be a drop-in replacement for -// `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 -// designed to cover the same API footprint as covered by `std::vector`. -template <typename T, size_t N, typename A = std::allocator<T>> -class InlinedVector { - static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity."); - - using Storage = inlined_vector_internal::Storage<T, N, A>; - - using AllocatorTraits = typename Storage::AllocatorTraits; - using RValueReference = typename Storage::RValueReference; - using MoveIterator = typename Storage::MoveIterator; - using IsMemcpyOk = typename Storage::IsMemcpyOk; - - template <typename Iterator> - using IteratorValueAdapter = - 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>; - template <typename Iterator> - using DisableIfAtLeastForwardIterator = absl::enable_if_t< - !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>; - - public: - using allocator_type = typename Storage::allocator_type; - using value_type = typename Storage::value_type; - using pointer = typename Storage::pointer; - using const_pointer = typename Storage::const_pointer; - using size_type = typename Storage::size_type; - using difference_type = typename Storage::difference_type; - using reference = typename Storage::reference; - using const_reference = typename Storage::const_reference; - using iterator = typename Storage::iterator; - using const_iterator = typename Storage::const_iterator; - using reverse_iterator = typename Storage::reverse_iterator; - using const_reverse_iterator = typename Storage::const_reverse_iterator; - - // --------------------------------------------------------------------------- - // InlinedVector Constructors and Destructor - // --------------------------------------------------------------------------- - - // Creates an empty inlined vector with a value-initialized allocator. - InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {} - - // 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& 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& 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& alloc = allocator_type()) - : InlinedVector(list.begin(), list.end(), alloc) {} - - // Creates an inlined vector with elements constructed from the provided - // forward iterator range [`first`, `last`). - // - // NOTE: the `enable_if` prevents ambiguous interpretation between a call to - // this constructor with two integral arguments and a call to the above - // `InlinedVector(size_type, const_reference)` constructor. - template <typename ForwardIterator, - EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr> - InlinedVector(ForwardIterator first, ForwardIterator last, - const allocator_type& alloc = allocator_type()) - : storage_(alloc) { - storage_.Initialize(IteratorValueAdapter<ForwardIterator>(first), - std::distance(first, last)); - } - - // Creates an inlined vector with elements constructed from the provided input - // iterator range [`first`, `last`). - template <typename InputIterator, - DisableIfAtLeastForwardIterator<InputIterator>* = nullptr> - InlinedVector(InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()) - : 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_.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_.Initialize(IteratorValueAdapter<const_pointer>(other.data()), - other.size()); - } - } - - // Creates an inlined vector by moving in the contents of `other` without - // allocating. If `other` contains allocated memory, the newly-created inlined - // vector will take ownership of that memory. However, if `other` does not - // contain allocated memory, the newly-created inlined vector will perform - // element-wise move construction of the contents of `other`. - // - // NOTE: since no allocation is performed for the inlined vector in either - // case, the `noexcept(...)` specification depends on whether moving the - // underlying objects can throw. It is assumed assumed that... - // a) move constructors should only throw due to allocation failure. - // b) if `value_type`'s move constructor allocates, it uses the same - // allocation function as the inlined vector's allocator. - // Thus, the move constructor is non-throwing if the allocator is non-throwing - // or `value_type`'s move constructor is specified as `noexcept`. - InlinedVector(InlinedVector&& other) noexcept( - absl::allocator_is_nothrow<allocator_type>::value || - std::is_nothrow_move_constructible<value_type>::value) - : storage_(*other.storage_.GetAllocPtr()) { - if (IsMemcpyOk::value) { - storage_.MemcpyFrom(other.storage_); - - other.storage_.SetInlinedSize(0); - } else if (other.storage_.GetIsAllocated()) { - storage_.SetAllocatedData(other.storage_.GetAllocatedData(), - other.storage_.GetAllocatedCapacity()); - storage_.SetAllocatedSize(other.storage_.GetSize()); - - other.storage_.SetInlinedSize(0); - } else { - IteratorValueAdapter<MoveIterator> other_values( - MoveIterator(other.storage_.GetInlinedData())); - - inlined_vector_internal::ConstructElements( - storage_.GetAllocPtr(), storage_.GetInlinedData(), &other_values, - other.storage_.GetSize()); - - storage_.SetInlinedSize(other.storage_.GetSize()); - } - } - - // Creates an inlined vector by moving in the contents of `other` with a copy - // of `alloc`. - // - // NOTE: if `other`'s allocator is not equal to `alloc`, even if `other` - // contains allocated memory, this move constructor will still allocate. Since - // allocation is performed, this constructor can only be `noexcept` if the - // specified allocator is also `noexcept`. - InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept( - absl::allocator_is_nothrow<allocator_type>::value) - : storage_(alloc) { - if (IsMemcpyOk::value) { - storage_.MemcpyFrom(other.storage_); - - other.storage_.SetInlinedSize(0); - } else if ((*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) && - other.storage_.GetIsAllocated()) { - storage_.SetAllocatedData(other.storage_.GetAllocatedData(), - other.storage_.GetAllocatedCapacity()); - storage_.SetAllocatedSize(other.storage_.GetSize()); - - other.storage_.SetInlinedSize(0); - } else { - storage_.Initialize( - IteratorValueAdapter<MoveIterator>(MoveIterator(other.data())), - other.size()); - } - } - - ~InlinedVector() {} - - // --------------------------------------------------------------------------- - // InlinedVector Member Accessors - // --------------------------------------------------------------------------- - - // `InlinedVector::empty()` - // - // Returns whether the inlined vector contains no elements. - bool empty() const noexcept { return !size(); } - - // `InlinedVector::size()` - // - // Returns the number of elements in the inlined vector. - size_type size() const noexcept { return storage_.GetSize(); } - - // `InlinedVector::max_size()` - // - // Returns the maximum number of elements the inlined vector can hold. - size_type max_size() const noexcept { - // One bit of the size storage is used to indicate whether the inlined - // vector contains allocated memory. As a result, the maximum size that the - // inlined vector can express is half of the max for `size_type`. - return (std::numeric_limits<size_type>::max)() / 2; - } - - // `InlinedVector::capacity()` - // - // Returns the number of elements that could be stored in the inlined vector - // without requiring a reallocation. - // - // NOTE: for most inlined vectors, `capacity()` should be equal to the - // template parameter `N`. For inlined vectors which exceed this capacity, - // they will no longer be inlined and `capacity()` will equal the capactity of - // the allocated memory. - size_type capacity() const noexcept { - return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity() - : storage_.GetInlinedCapacity(); - } - - // `InlinedVector::data()` - // - // Returns a `pointer` to the elements of the inlined vector. This pointer - // can be used to access and modify the contained elements. - // - // NOTE: only elements within [`data()`, `data() + size()`) are valid. - pointer data() noexcept { - return storage_.GetIsAllocated() ? storage_.GetAllocatedData() - : storage_.GetInlinedData(); - } - - // Overload of `InlinedVector::data()` that returns a `const_pointer` to the - // elements of the inlined vector. This pointer can be used to access but not - // modify the contained elements. - // - // NOTE: only elements within [`data()`, `data() + size()`) are valid. - const_pointer data() const noexcept { - return storage_.GetIsAllocated() ? storage_.GetAllocatedData() - : storage_.GetInlinedData(); - } - - // `InlinedVector::operator[](...)` - // - // Returns a `reference` to the `i`th element of the inlined vector. - reference operator[](size_type i) { - ABSL_HARDENING_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()); - return data()[i]; - } - - // `InlinedVector::at(...)` - // - // Returns a `reference` to the `i`th element of the inlined vector. - // - // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`, - // in both debug and non-debug builds, `std::out_of_range` will be thrown. - reference at(size_type i) { - if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange( - "`InlinedVector::at(size_type)` failed bounds check"); - } - return data()[i]; - } - - // Overload of `InlinedVector::at(...)` that returns a `const_reference` to - // the `i`th element of the inlined vector. - // - // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`, - // in both debug and non-debug builds, `std::out_of_range` will be thrown. - const_reference at(size_type i) const { - if (ABSL_PREDICT_FALSE(i >= size())) { - base_internal::ThrowStdOutOfRange( - "`InlinedVector::at(size_type) const` failed bounds check"); - } - return data()[i]; - } - - // `InlinedVector::front()` - // - // Returns a `reference` to the first element of the inlined vector. - reference front() { - ABSL_HARDENING_ASSERT(!empty()); - return data()[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]; - } - - // `InlinedVector::back()` - // - // Returns a `reference` to the last element of the inlined vector. - reference back() { - ABSL_HARDENING_ASSERT(!empty()); - return data()[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]; - } - - // `InlinedVector::begin()` - // - // Returns an `iterator` to the beginning of the inlined vector. - iterator begin() noexcept { return data(); } - - // Overload of `InlinedVector::begin()` that returns a `const_iterator` to - // the beginning of the inlined vector. - const_iterator begin() const noexcept { return data(); } - - // `InlinedVector::end()` - // - // Returns an `iterator` to the end of the inlined vector. - iterator end() noexcept { return data() + size(); } - - // Overload of `InlinedVector::end()` that returns a `const_iterator` to the - // end of the inlined vector. - const_iterator end() const noexcept { return data() + size(); } - - // `InlinedVector::cbegin()` - // - // Returns a `const_iterator` to the beginning of the inlined vector. - const_iterator cbegin() const noexcept { return begin(); } - - // `InlinedVector::cend()` - // - // Returns a `const_iterator` to the end of the inlined vector. - const_iterator cend() const noexcept { return end(); } - - // `InlinedVector::rbegin()` - // - // Returns a `reverse_iterator` from the end of the inlined vector. - reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - - // Overload of `InlinedVector::rbegin()` that returns a - // `const_reverse_iterator` from the end of the inlined vector. - const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end()); - } - - // `InlinedVector::rend()` - // - // Returns a `reverse_iterator` from the beginning of the inlined vector. - reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - - // Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator` - // from the beginning of the inlined vector. - const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin()); - } - - // `InlinedVector::crbegin()` - // - // Returns a `const_reverse_iterator` from the end of the inlined vector. - const_reverse_iterator crbegin() const noexcept { return rbegin(); } - - // `InlinedVector::crend()` - // - // Returns a `const_reverse_iterator` from the beginning of the inlined - // vector. - const_reverse_iterator crend() const noexcept { return rend(); } - - // `InlinedVector::get_allocator()` - // - // Returns a copy of the inlined vector's allocator. - allocator_type get_allocator() const { return *storage_.GetAllocPtr(); } - - // --------------------------------------------------------------------------- - // InlinedVector Member Mutators - // --------------------------------------------------------------------------- - - // `InlinedVector::operator=(...)` - // - // Replaces the elements of the inlined vector with copies of the elements of - // `list`. - InlinedVector& operator=(std::initializer_list<value_type> list) { - assign(list.begin(), list.end()); - - return *this; - } - - // Overload of `InlinedVector::operator=(...)` that replaces the elements of - // the inlined vector with copies of the elements of `other`. - InlinedVector& operator=(const InlinedVector& other) { - if (ABSL_PREDICT_TRUE(this != std::addressof(other))) { - const_pointer other_data = other.data(); - assign(other_data, other_data + other.size()); - } - - return *this; - } - - // Overload of `InlinedVector::operator=(...)` that moves the elements of - // `other` into the inlined vector. - // - // NOTE: as a result of calling this overload, `other` is left in a valid but - // unspecified state. - InlinedVector& operator=(InlinedVector&& other) { - if (ABSL_PREDICT_TRUE(this != std::addressof(other))) { - if (IsMemcpyOk::value || other.storage_.GetIsAllocated()) { - inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(), - size()); - storage_.DeallocateIfAllocated(); - storage_.MemcpyFrom(other.storage_); - - other.storage_.SetInlinedSize(0); - } else { - storage_.Assign(IteratorValueAdapter<MoveIterator>( - MoveIterator(other.storage_.GetInlinedData())), - other.size()); - } - } - - return *this; - } - - // `InlinedVector::assign(...)` - // - // Replaces the contents of the inlined vector with `n` copies of `v`. - void assign(size_type n, const_reference v) { - storage_.Assign(CopyValueAdapter(v), n); - } - - // Overload of `InlinedVector::assign(...)` that replaces the contents of the - // inlined vector with copies of the elements of `list`. - void assign(std::initializer_list<value_type> list) { - assign(list.begin(), list.end()); - } - - // Overload of `InlinedVector::assign(...)` to replace the contents of the - // inlined vector with the range [`first`, `last`). - // - // NOTE: this overload is for iterators that are "forward" category or better. - template <typename ForwardIterator, - EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr> - void assign(ForwardIterator first, ForwardIterator last) { - storage_.Assign(IteratorValueAdapter<ForwardIterator>(first), - std::distance(first, last)); - } - - // Overload of `InlinedVector::assign(...)` to replace the contents of the - // inlined vector with the range [`first`, `last`). - // - // NOTE: this overload is for iterators that are "input" category. - template <typename InputIterator, - DisableIfAtLeastForwardIterator<InputIterator>* = nullptr> - void assign(InputIterator first, InputIterator last) { - size_type i = 0; - for (; i < size() && first != last; ++i, static_cast<void>(++first)) { - data()[i] = *first; - } - - erase(data() + i, data() + size()); - std::copy(first, last, std::back_inserter(*this)); - } - - // `InlinedVector::resize(...)` - // - // Resizes the inlined vector to contain `n` elements. - // - // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n` - // is larger than `size()`, new elements are value-initialized. - void resize(size_type n) { - ABSL_HARDENING_ASSERT(n <= max_size()); - storage_.Resize(DefaultValueAdapter(), n); - } - - // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to - // contain `n` elements. - // - // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n` - // is larger than `size()`, new elements are copied-constructed from `v`. - void resize(size_type n, const_reference v) { - ABSL_HARDENING_ASSERT(n <= max_size()); - storage_.Resize(CopyValueAdapter(v), n); - } - - // `InlinedVector::insert(...)` - // - // Inserts a copy of `v` at `pos`, returning an `iterator` to the newly - // inserted element. - iterator insert(const_iterator pos, const_reference v) { - return emplace(pos, v); - } - - // Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using - // move semantics, returning an `iterator` to the newly inserted element. - iterator insert(const_iterator pos, RValueReference v) { - return emplace(pos, std::move(v)); - } - - // Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies - // of `v` starting at `pos`, returning an `iterator` pointing to the first of - // the newly inserted elements. - iterator insert(const_iterator pos, size_type n, const_reference v) { - ABSL_HARDENING_ASSERT(pos >= begin()); - ABSL_HARDENING_ASSERT(pos <= end()); - - if (ABSL_PREDICT_TRUE(n != 0)) { - value_type dealias = v; - return storage_.Insert(pos, CopyValueAdapter(dealias), n); - } else { - return const_cast<iterator>(pos); - } - } - - // Overload of `InlinedVector::insert(...)` that inserts copies of the - // elements of `list` starting at `pos`, returning an `iterator` pointing to - // the first of the newly inserted elements. - iterator insert(const_iterator pos, std::initializer_list<value_type> list) { - return insert(pos, list.begin(), list.end()); - } - - // Overload of `InlinedVector::insert(...)` that inserts the range [`first`, - // `last`) starting at `pos`, returning an `iterator` pointing to the first - // of the newly inserted elements. - // - // NOTE: this overload is for iterators that are "forward" category or better. - template <typename ForwardIterator, - EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr> - iterator insert(const_iterator pos, ForwardIterator first, - ForwardIterator last) { - ABSL_HARDENING_ASSERT(pos >= begin()); - ABSL_HARDENING_ASSERT(pos <= end()); - - if (ABSL_PREDICT_TRUE(first != last)) { - return storage_.Insert(pos, IteratorValueAdapter<ForwardIterator>(first), - std::distance(first, last)); - } else { - return const_cast<iterator>(pos); - } - } - - // Overload of `InlinedVector::insert(...)` that inserts the range [`first`, - // `last`) starting at `pos`, returning an `iterator` pointing to the first - // of the newly inserted elements. - // - // NOTE: this overload is for iterators that are "input" category. - template <typename InputIterator, - DisableIfAtLeastForwardIterator<InputIterator>* = nullptr> - iterator insert(const_iterator pos, InputIterator first, InputIterator last) { - ABSL_HARDENING_ASSERT(pos >= begin()); - ABSL_HARDENING_ASSERT(pos <= end()); - - size_type index = std::distance(cbegin(), pos); - for (size_type i = index; first != last; ++i, static_cast<void>(++first)) { - insert(data() + i, *first); - } - - return iterator(data() + index); - } - - // `InlinedVector::emplace(...)` - // - // Constructs and inserts an element using `args...` in the inlined vector at - // `pos`, returning an `iterator` pointing to the newly emplaced element. - template <typename... Args> - iterator emplace(const_iterator pos, Args&&... args) { - ABSL_HARDENING_ASSERT(pos >= begin()); - ABSL_HARDENING_ASSERT(pos <= end()); - - value_type dealias(std::forward<Args>(args)...); - return storage_.Insert(pos, - IteratorValueAdapter<MoveIterator>( - MoveIterator(std::addressof(dealias))), - 1); - } - - // `InlinedVector::emplace_back(...)` - // - // Constructs and inserts an element using `args...` in the inlined vector at - // `end()`, returning a `reference` to the newly emplaced element. - template <typename... Args> - reference emplace_back(Args&&... args) { - return storage_.EmplaceBack(std::forward<Args>(args)...); - } - - // `InlinedVector::push_back(...)` - // - // Inserts a copy of `v` in the inlined vector at `end()`. - void push_back(const_reference v) { static_cast<void>(emplace_back(v)); } - - // Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()` - // using move semantics. - void push_back(RValueReference v) { - static_cast<void>(emplace_back(std::move(v))); - } - - // `InlinedVector::pop_back()` - // - // Destroys the element at `back()`, reducing the size by `1`. - void pop_back() noexcept { - ABSL_HARDENING_ASSERT(!empty()); - - AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1)); - storage_.SubtractSize(1); - } - - // `InlinedVector::erase(...)` - // - // Erases the element at `pos`, returning an `iterator` pointing to where the - // erased element was located. - // - // NOTE: may return `end()`, which is not dereferencable. - iterator erase(const_iterator pos) { - ABSL_HARDENING_ASSERT(pos >= begin()); - ABSL_HARDENING_ASSERT(pos < end()); - - return storage_.Erase(pos, pos + 1); - } - - // Overload of `InlinedVector::erase(...)` that erases every element in the - // range [`from`, `to`), returning an `iterator` pointing to where the first - // erased element was located. - // - // NOTE: may return `end()`, which is not dereferencable. - iterator erase(const_iterator from, const_iterator to) { - ABSL_HARDENING_ASSERT(from >= begin()); - ABSL_HARDENING_ASSERT(from <= to); - ABSL_HARDENING_ASSERT(to <= end()); - - if (ABSL_PREDICT_TRUE(from != to)) { - return storage_.Erase(from, to); - } else { - return const_cast<iterator>(from); - } - } - - // `InlinedVector::clear()` - // - // Destroys all elements in the inlined vector, setting the size to `0` and - // deallocating any held memory. - void clear() noexcept { - inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(), - size()); - storage_.DeallocateIfAllocated(); - - storage_.SetInlinedSize(0); - } - - // `InlinedVector::reserve(...)` - // - // Ensures that there is enough room for at least `n` elements. - void reserve(size_type n) { storage_.Reserve(n); } - - // `InlinedVector::shrink_to_fit()` - // - // Reduces memory usage by freeing unused memory. After 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() > N` and `size() < capacity()`, the elements will be moved to a - // smaller allocation. - void shrink_to_fit() { - if (storage_.GetIsAllocated()) { - storage_.ShrinkToFit(); - } - } - - // `InlinedVector::swap(...)` - // - // Swaps the contents of the inlined vector with `other`. - void swap(InlinedVector& other) { - if (ABSL_PREDICT_TRUE(this != std::addressof(other))) { - storage_.Swap(std::addressof(other.storage_)); - } - } - - private: - template <typename H, typename TheT, size_t TheN, typename TheA> - friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a); - - Storage storage_; -}; - -// ----------------------------------------------------------------------------- -// InlinedVector Non-Member Functions -// ----------------------------------------------------------------------------- - -// `swap(...)` -// -// Swaps the contents of two inlined vectors. -template <typename T, size_t N, typename A> -void swap(absl::InlinedVector<T, N, A>& a, - absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) { - a.swap(b); -} - -// `operator==(...)` -// -// Tests for value-equality of two inlined vectors. -template <typename T, size_t N, typename A> -bool operator==(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - auto a_data = a.data(); - auto b_data = b.data(); - return absl::equal(a_data, a_data + a.size(), b_data, b_data + b.size()); -} - -// `operator!=(...)` -// -// Tests for value-inequality of two inlined vectors. -template <typename T, size_t N, typename A> -bool operator!=(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - return !(a == b); -} - -// `operator<(...)` -// -// Tests whether the value of an inlined vector is less than the value of -// another inlined vector using a lexicographical comparison algorithm. -template <typename T, size_t N, typename A> -bool operator<(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - auto a_data = a.data(); - auto b_data = b.data(); - return std::lexicographical_compare(a_data, a_data + a.size(), b_data, - b_data + b.size()); -} - -// `operator>(...)` -// -// Tests whether the value of an inlined vector is greater than the value of -// another inlined vector using a lexicographical comparison algorithm. -template <typename T, size_t N, typename A> -bool operator>(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - return b < a; -} - -// `operator<=(...)` -// -// Tests whether the value of an inlined vector is less than or equal to the -// value of another inlined vector using a lexicographical comparison algorithm. -template <typename T, size_t N, typename A> -bool operator<=(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - return !(b < a); -} - -// `operator>=(...)` -// -// Tests whether the value of an inlined vector is greater than or equal to the -// value of another inlined vector using a lexicographical comparison algorithm. -template <typename T, size_t N, typename A> -bool operator>=(const absl::InlinedVector<T, N, A>& a, - const absl::InlinedVector<T, N, A>& b) { - return !(a < b); -} - -// `AbslHashValue(...)` -// -// Provides `absl::Hash` support for `absl::InlinedVector`. It is uncommon to -// call this directly. -template <typename H, typename T, size_t N, typename A> -H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) { - auto size = a.size(); - return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INLINED_VECTOR_H_ diff --git a/third_party/abseil_cpp/absl/container/inlined_vector_benchmark.cc b/third_party/abseil_cpp/absl/container/inlined_vector_benchmark.cc deleted file mode 100644 index b8dafe932320..000000000000 --- a/third_party/abseil_cpp/absl/container/inlined_vector_benchmark.cc +++ /dev/null @@ -1,807 +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 <array> -#include <string> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/container/inlined_vector.h" -#include "absl/strings/str_cat.h" - -namespace { - -void BM_InlinedVectorFill(benchmark::State& state) { - const int len = state.range(0); - absl::InlinedVector<int, 8> v; - v.reserve(len); - for (auto _ : state) { - v.resize(0); // Use resize(0) as InlinedVector releases storage on clear(). - for (int i = 0; i < len; ++i) { - v.push_back(i); - } - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_InlinedVectorFill)->Range(1, 256); - -void BM_InlinedVectorFillRange(benchmark::State& state) { - const int len = state.range(0); - const std::vector<int> src(len, len); - absl::InlinedVector<int, 8> v; - v.reserve(len); - for (auto _ : state) { - benchmark::DoNotOptimize(src); - v.assign(src.begin(), src.end()); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_InlinedVectorFillRange)->Range(1, 256); - -void BM_StdVectorFill(benchmark::State& state) { - const int len = state.range(0); - std::vector<int> v; - v.reserve(len); - for (auto _ : state) { - v.clear(); - for (int i = 0; i < len; ++i) { - v.push_back(i); - } - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_StdVectorFill)->Range(1, 256); - -// The purpose of the next two benchmarks is to verify that -// absl::InlinedVector is efficient when moving is more efficent than -// copying. To do so, we use strings that are larger than the short -// string optimization. -bool StringRepresentedInline(std::string s) { - const char* chars = s.data(); - std::string s1 = std::move(s); - return s1.data() != chars; -} - -int GetNonShortStringOptimizationSize() { - for (int i = 24; i <= 192; i *= 2) { - if (!StringRepresentedInline(std::string(i, 'A'))) { - return i; - } - } - ABSL_RAW_LOG( - FATAL, - "Failed to find a string larger than the short string optimization"); - return -1; -} - -void BM_InlinedVectorFillString(benchmark::State& state) { - const int len = state.range(0); - const int no_sso = GetNonShortStringOptimizationSize(); - std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'), - std::string(no_sso, 'C'), std::string(no_sso, 'D')}; - - for (auto _ : state) { - absl::InlinedVector<std::string, 8> v; - for (int i = 0; i < len; i++) { - v.push_back(strings[i & 3]); - } - } - state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len); -} -BENCHMARK(BM_InlinedVectorFillString)->Range(0, 1024); - -void BM_StdVectorFillString(benchmark::State& state) { - const int len = state.range(0); - const int no_sso = GetNonShortStringOptimizationSize(); - std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'), - std::string(no_sso, 'C'), std::string(no_sso, 'D')}; - - for (auto _ : state) { - std::vector<std::string> v; - for (int i = 0; i < len; i++) { - v.push_back(strings[i & 3]); - } - } - state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len); -} -BENCHMARK(BM_StdVectorFillString)->Range(0, 1024); - -struct Buffer { // some arbitrary structure for benchmarking. - char* base; - int length; - int capacity; - void* user_data; -}; - -void BM_InlinedVectorAssignments(benchmark::State& state) { - const int len = state.range(0); - using BufferVec = absl::InlinedVector<Buffer, 2>; - - BufferVec src; - src.resize(len); - - BufferVec dst; - for (auto _ : state) { - benchmark::DoNotOptimize(dst); - benchmark::DoNotOptimize(src); - dst = src; - } -} -BENCHMARK(BM_InlinedVectorAssignments) - ->Arg(0) - ->Arg(1) - ->Arg(2) - ->Arg(3) - ->Arg(4) - ->Arg(20); - -void BM_CreateFromContainer(benchmark::State& state) { - for (auto _ : state) { - absl::InlinedVector<int, 4> src{1, 2, 3}; - benchmark::DoNotOptimize(src); - absl::InlinedVector<int, 4> dst(std::move(src)); - benchmark::DoNotOptimize(dst); - } -} -BENCHMARK(BM_CreateFromContainer); - -struct LargeCopyableOnly { - LargeCopyableOnly() : d(1024, 17) {} - LargeCopyableOnly(const LargeCopyableOnly& o) = default; - LargeCopyableOnly& operator=(const LargeCopyableOnly& o) = default; - - std::vector<int> d; -}; - -struct LargeCopyableSwappable { - LargeCopyableSwappable() : d(1024, 17) {} - - LargeCopyableSwappable(const LargeCopyableSwappable& o) = default; - - LargeCopyableSwappable& operator=(LargeCopyableSwappable o) { - using std::swap; - swap(*this, o); - return *this; - } - - friend void swap(LargeCopyableSwappable& a, LargeCopyableSwappable& b) { - using std::swap; - swap(a.d, b.d); - } - - std::vector<int> d; -}; - -struct LargeCopyableMovable { - LargeCopyableMovable() : d(1024, 17) {} - // Use implicitly defined copy and move. - - std::vector<int> d; -}; - -struct LargeCopyableMovableSwappable { - LargeCopyableMovableSwappable() : d(1024, 17) {} - LargeCopyableMovableSwappable(const LargeCopyableMovableSwappable& o) = - default; - LargeCopyableMovableSwappable(LargeCopyableMovableSwappable&& o) = default; - - LargeCopyableMovableSwappable& operator=(LargeCopyableMovableSwappable o) { - using std::swap; - swap(*this, o); - return *this; - } - LargeCopyableMovableSwappable& operator=(LargeCopyableMovableSwappable&& o) = - default; - - friend void swap(LargeCopyableMovableSwappable& a, - LargeCopyableMovableSwappable& b) { - using std::swap; - swap(a.d, b.d); - } - - std::vector<int> d; -}; - -template <typename ElementType> -void BM_SwapElements(benchmark::State& state) { - const int len = state.range(0); - using Vec = absl::InlinedVector<ElementType, 32>; - Vec a(len); - Vec b; - for (auto _ : state) { - using std::swap; - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - swap(a, b); - } -} -BENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableOnly)->Range(0, 1024); -BENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableSwappable)->Range(0, 1024); -BENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableMovable)->Range(0, 1024); -BENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableMovableSwappable) - ->Range(0, 1024); - -// The following benchmark is meant to track the efficiency of the vector size -// as a function of stored type via the benchmark label. It is not meant to -// output useful sizeof operator performance. The loop is a dummy operation -// to fulfill the requirement of running the benchmark. -template <typename VecType> -void BM_Sizeof(benchmark::State& state) { - int size = 0; - for (auto _ : state) { - VecType vec; - size = sizeof(vec); - } - state.SetLabel(absl::StrCat("sz=", size)); -} -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 1>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 4>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 7>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 8>); - -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 1>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 4>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 7>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 8>); - -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 1>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 4>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 7>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 8>); - -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 1>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 4>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 7>); -BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 8>); - -void BM_InlinedVectorIndexInlined(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v[4]); - } -} -BENCHMARK(BM_InlinedVectorIndexInlined); - -void BM_InlinedVectorIndexExternal(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v[4]); - } -} -BENCHMARK(BM_InlinedVectorIndexExternal); - -void BM_StdVectorIndex(benchmark::State& state) { - std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v[4]); - } -} -BENCHMARK(BM_StdVectorIndex); - -void BM_InlinedVectorDataInlined(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.data()); - } -} -BENCHMARK(BM_InlinedVectorDataInlined); - -void BM_InlinedVectorDataExternal(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.data()); - } - state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations())); -} -BENCHMARK(BM_InlinedVectorDataExternal); - -void BM_StdVectorData(benchmark::State& state) { - std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.data()); - } - state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations())); -} -BENCHMARK(BM_StdVectorData); - -void BM_InlinedVectorSizeInlined(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.size()); - } -} -BENCHMARK(BM_InlinedVectorSizeInlined); - -void BM_InlinedVectorSizeExternal(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.size()); - } -} -BENCHMARK(BM_InlinedVectorSizeExternal); - -void BM_StdVectorSize(benchmark::State& state) { - std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.size()); - } -} -BENCHMARK(BM_StdVectorSize); - -void BM_InlinedVectorEmptyInlined(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.empty()); - } -} -BENCHMARK(BM_InlinedVectorEmptyInlined); - -void BM_InlinedVectorEmptyExternal(benchmark::State& state) { - absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.empty()); - } -} -BENCHMARK(BM_InlinedVectorEmptyExternal); - -void BM_StdVectorEmpty(benchmark::State& state) { - std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - for (auto _ : state) { - benchmark::DoNotOptimize(v); - benchmark::DoNotOptimize(v.empty()); - } -} -BENCHMARK(BM_StdVectorEmpty); - -constexpr size_t kInlinedCapacity = 4; -constexpr size_t kLargeSize = kInlinedCapacity * 2; -constexpr size_t kSmallSize = kInlinedCapacity / 2; -constexpr size_t kBatchSize = 100; - -#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize); \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize) - -#define ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_FunctionTemplate, T) \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kLargeSize); \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kSmallSize); \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kLargeSize); \ - BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kSmallSize) - -template <typename T> -using InlVec = absl::InlinedVector<T, kInlinedCapacity>; - -struct TrivialType { - size_t val; -}; - -class NontrivialType { - public: - ABSL_ATTRIBUTE_NOINLINE NontrivialType() : val_() { - benchmark::DoNotOptimize(*this); - } - - ABSL_ATTRIBUTE_NOINLINE NontrivialType(const NontrivialType& other) - : val_(other.val_) { - benchmark::DoNotOptimize(*this); - } - - ABSL_ATTRIBUTE_NOINLINE NontrivialType& operator=( - const NontrivialType& other) { - val_ = other.val_; - benchmark::DoNotOptimize(*this); - return *this; - } - - ABSL_ATTRIBUTE_NOINLINE ~NontrivialType() noexcept { - benchmark::DoNotOptimize(*this); - } - - private: - size_t val_; -}; - -template <typename T, typename PrepareVecFn, typename TestVecFn> -void BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec, - TestVecFn test_vec) { - std::array<InlVec<T>, kBatchSize> vector_batch{}; - - while (state.KeepRunningBatch(kBatchSize)) { - // Prepare batch - state.PauseTiming(); - for (size_t i = 0; i < kBatchSize; ++i) { - prepare_vec(vector_batch.data() + i, i); - } - benchmark::DoNotOptimize(vector_batch); - state.ResumeTiming(); - - // Test batch - for (size_t i = 0; i < kBatchSize; ++i) { - test_vec(vector_batch.data() + i, i); - } - } -} - -template <typename T, size_t ToSize> -void BM_ConstructFromSize(benchmark::State& state) { - using VecT = InlVec<T>; - auto size = ToSize; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, - /* test_vec = */ - [&](void* ptr, size_t) { - benchmark::DoNotOptimize(size); - ::new (ptr) VecT(size); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType); - -template <typename T, size_t ToSize> -void BM_ConstructFromSizeRef(benchmark::State& state) { - using VecT = InlVec<T>; - auto size = ToSize; - auto ref = T(); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, - /* test_vec = */ - [&](void* ptr, size_t) { - benchmark::DoNotOptimize(size); - benchmark::DoNotOptimize(ref); - ::new (ptr) VecT(size, ref); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType); - -template <typename T, size_t ToSize> -void BM_ConstructFromRange(benchmark::State& state) { - using VecT = InlVec<T>; - std::array<T, ToSize> arr{}; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, - /* test_vec = */ - [&](void* ptr, size_t) { - benchmark::DoNotOptimize(arr); - ::new (ptr) VecT(arr.begin(), arr.end()); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType); - -template <typename T, size_t ToSize> -void BM_ConstructFromCopy(benchmark::State& state) { - using VecT = InlVec<T>; - VecT other_vec(ToSize); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { vec->~VecT(); }, - /* test_vec = */ - [&](void* ptr, size_t) { - benchmark::DoNotOptimize(other_vec); - ::new (ptr) VecT(other_vec); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType); - -template <typename T, size_t ToSize> -void BM_ConstructFromMove(benchmark::State& state) { - using VecT = InlVec<T>; - std::array<VecT, kBatchSize> vector_batch{}; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [&](InlVec<T>* vec, size_t i) { - vector_batch[i].clear(); - vector_batch[i].resize(ToSize); - vec->~VecT(); - }, - /* test_vec = */ - [&](void* ptr, size_t i) { - benchmark::DoNotOptimize(vector_batch[i]); - ::new (ptr) VecT(std::move(vector_batch[i])); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_AssignSizeRef(benchmark::State& state) { - auto size = ToSize; - auto ref = T(); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(size); - benchmark::DoNotOptimize(ref); - vec->assign(size, ref); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_AssignRange(benchmark::State& state) { - std::array<T, ToSize> arr{}; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(arr); - vec->assign(arr.begin(), arr.end()); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_AssignFromCopy(benchmark::State& state) { - InlVec<T> other_vec(ToSize); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(other_vec); - *vec = other_vec; - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_AssignFromMove(benchmark::State& state) { - using VecT = InlVec<T>; - std::array<VecT, kBatchSize> vector_batch{}; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [&](InlVec<T>* vec, size_t i) { - vector_batch[i].clear(); - vector_batch[i].resize(ToSize); - vec->resize(FromSize); - }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t i) { - benchmark::DoNotOptimize(vector_batch[i]); - *vec = std::move(vector_batch[i]); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_ResizeSize(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { vec->resize(ToSize); }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_ResizeSizeRef(benchmark::State& state) { - auto t = T(); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(t); - vec->resize(ToSize, t); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_InsertSizeRef(benchmark::State& state) { - auto t = T(); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(t); - auto* pos = vec->data() + (vec->size() / 2); - vec->insert(pos, t); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_InsertRange(benchmark::State& state) { - InlVec<T> other_vec(ToSize); - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t) { - benchmark::DoNotOptimize(other_vec); - auto* pos = vec->data() + (vec->size() / 2); - vec->insert(pos, other_vec.begin(), other_vec.end()); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, NontrivialType); - -template <typename T, size_t FromSize> -void BM_EmplaceBack(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { vec->emplace_back(); }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, NontrivialType); - -template <typename T, size_t FromSize> -void BM_PopBack(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { vec->pop_back(); }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, NontrivialType); - -template <typename T, size_t FromSize> -void BM_EraseOne(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { - auto* pos = vec->data() + (vec->size() / 2); - vec->erase(pos); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, NontrivialType); - -template <typename T, size_t FromSize> -void BM_EraseRange(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { - auto* pos = vec->data() + (vec->size() / 2); - vec->erase(pos, pos + 1); - }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, NontrivialType); - -template <typename T, size_t FromSize> -void BM_Clear(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); }, - /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->clear(); }); -} -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType); -ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType); - -template <typename T, size_t FromSize, size_t ToCapacity> -void BM_Reserve(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(FromSize); - }, - /* test_vec = */ - [](InlVec<T>* vec, size_t) { vec->reserve(ToCapacity); }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, NontrivialType); - -template <typename T, size_t FromCapacity, size_t ToCapacity> -void BM_ShrinkToFit(benchmark::State& state) { - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [](InlVec<T>* vec, size_t) { - vec->clear(); - vec->resize(ToCapacity); - vec->reserve(FromCapacity); - }, - /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->shrink_to_fit(); }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, NontrivialType); - -template <typename T, size_t FromSize, size_t ToSize> -void BM_Swap(benchmark::State& state) { - using VecT = InlVec<T>; - std::array<VecT, kBatchSize> vector_batch{}; - BatchedBenchmark<T>( - state, - /* prepare_vec = */ - [&](InlVec<T>* vec, size_t i) { - vector_batch[i].clear(); - vector_batch[i].resize(ToSize); - vec->resize(FromSize); - }, - /* test_vec = */ - [&](InlVec<T>* vec, size_t i) { - using std::swap; - benchmark::DoNotOptimize(vector_batch[i]); - swap(*vec, vector_batch[i]); - }); -} -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, TrivialType); -ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, NontrivialType); - -} // namespace diff --git a/third_party/abseil_cpp/absl/container/inlined_vector_exception_safety_test.cc b/third_party/abseil_cpp/absl/container/inlined_vector_exception_safety_test.cc deleted file mode 100644 index 0e6a05b5f6a7..000000000000 --- a/third_party/abseil_cpp/absl/container/inlined_vector_exception_safety_test.cc +++ /dev/null @@ -1,508 +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/container/inlined_vector.h" - -#include "absl/base/config.h" - -#if defined(ABSL_HAVE_EXCEPTIONS) - -#include <array> -#include <initializer_list> -#include <iterator> -#include <memory> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace { - -constexpr size_t kInlinedCapacity = 4; -constexpr size_t kLargeSize = kInlinedCapacity * 2; -constexpr size_t kSmallSize = kInlinedCapacity / 2; - -using Thrower = testing::ThrowingValue<>; -using MovableThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using ThrowAlloc = testing::ThrowingAllocator<Thrower>; - -using ThrowerVec = absl::InlinedVector<Thrower, kInlinedCapacity>; -using MovableThrowerVec = absl::InlinedVector<MovableThrower, kInlinedCapacity>; - -using ThrowAllocThrowerVec = - absl::InlinedVector<Thrower, kInlinedCapacity, ThrowAlloc>; -using ThrowAllocMovableThrowerVec = - absl::InlinedVector<MovableThrower, kInlinedCapacity, ThrowAlloc>; - -// In GCC, if an element of a `std::initializer_list` throws during construction -// the elements that were constructed before it are not destroyed. This causes -// incorrect exception safety test failures. Thus, `testing::nothrow_ctor` is -// required. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66139 -#define ABSL_INTERNAL_MAKE_INIT_LIST(T, N) \ - (N > kInlinedCapacity \ - ? std::initializer_list<T>{T(0, testing::nothrow_ctor), \ - T(1, testing::nothrow_ctor), \ - T(2, testing::nothrow_ctor), \ - T(3, testing::nothrow_ctor), \ - T(4, testing::nothrow_ctor), \ - T(5, testing::nothrow_ctor), \ - T(6, testing::nothrow_ctor), \ - T(7, testing::nothrow_ctor)} \ - \ - : std::initializer_list<T>{T(0, testing::nothrow_ctor), \ - T(1, testing::nothrow_ctor)}) -static_assert(kLargeSize == 8, "Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)"); -static_assert(kSmallSize == 2, "Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)"); - -template <typename TheVecT, size_t... TheSizes> -class TestParams { - public: - using VecT = TheVecT; - constexpr static size_t GetSizeAt(size_t i) { return kSizes[1 + i]; } - - private: - constexpr static size_t kSizes[1 + sizeof...(TheSizes)] = {1, TheSizes...}; -}; - -using NoSizeTestParams = - ::testing::Types<TestParams<ThrowerVec>, TestParams<MovableThrowerVec>, - TestParams<ThrowAllocThrowerVec>, - TestParams<ThrowAllocMovableThrowerVec>>; - -using OneSizeTestParams = - ::testing::Types<TestParams<ThrowerVec, kLargeSize>, - TestParams<ThrowerVec, kSmallSize>, - TestParams<MovableThrowerVec, kLargeSize>, - TestParams<MovableThrowerVec, kSmallSize>, - TestParams<ThrowAllocThrowerVec, kLargeSize>, - TestParams<ThrowAllocThrowerVec, kSmallSize>, - TestParams<ThrowAllocMovableThrowerVec, kLargeSize>, - TestParams<ThrowAllocMovableThrowerVec, kSmallSize>>; - -using TwoSizeTestParams = ::testing::Types< - TestParams<ThrowerVec, kLargeSize, kLargeSize>, - TestParams<ThrowerVec, kLargeSize, kSmallSize>, - TestParams<ThrowerVec, kSmallSize, kLargeSize>, - TestParams<ThrowerVec, kSmallSize, kSmallSize>, - TestParams<MovableThrowerVec, kLargeSize, kLargeSize>, - TestParams<MovableThrowerVec, kLargeSize, kSmallSize>, - TestParams<MovableThrowerVec, kSmallSize, kLargeSize>, - TestParams<MovableThrowerVec, kSmallSize, kSmallSize>, - TestParams<ThrowAllocThrowerVec, kLargeSize, kLargeSize>, - TestParams<ThrowAllocThrowerVec, kLargeSize, kSmallSize>, - TestParams<ThrowAllocThrowerVec, kSmallSize, kLargeSize>, - TestParams<ThrowAllocThrowerVec, kSmallSize, kSmallSize>, - TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kLargeSize>, - TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kSmallSize>, - TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kLargeSize>, - TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kSmallSize>>; - -template <typename> -struct NoSizeTest : ::testing::Test {}; -TYPED_TEST_SUITE(NoSizeTest, NoSizeTestParams); - -template <typename> -struct OneSizeTest : ::testing::Test {}; -TYPED_TEST_SUITE(OneSizeTest, OneSizeTestParams); - -template <typename> -struct TwoSizeTest : ::testing::Test {}; -TYPED_TEST_SUITE(TwoSizeTest, TwoSizeTestParams); - -template <typename VecT> -bool InlinedVectorInvariants(VecT* vec) { - if (*vec != *vec) return false; - if (vec->size() > vec->capacity()) return false; - if (vec->size() > vec->max_size()) return false; - if (vec->capacity() > vec->max_size()) return false; - if (vec->data() != std::addressof(vec->at(0))) return false; - if (vec->data() != vec->begin()) return false; - if (*vec->data() != *vec->begin()) return false; - if (vec->begin() > vec->end()) return false; - if ((vec->end() - vec->begin()) != vec->size()) return false; - if (std::distance(vec->begin(), vec->end()) != vec->size()) return false; - return true; -} - -// Function that always returns false is correct, but refactoring is required -// for clarity. It's needed to express that, as a contract, certain operations -// should not throw at all. Execution of this function means an exception was -// thrown and thus the test should fail. -// TODO(johnsoncj): Add `testing::NoThrowGuarantee` to the framework -template <typename VecT> -bool NoThrowGuarantee(VecT* /* vec */) { - return false; -} - -TYPED_TEST(NoSizeTest, DefaultConstructor) { - using VecT = typename TypeParam::VecT; - using allocator_type = typename VecT::allocator_type; - - testing::TestThrowingCtor<VecT>(); - - testing::TestThrowingCtor<VecT>(allocator_type{}); -} - -TYPED_TEST(OneSizeTest, SizeConstructor) { - using VecT = typename TypeParam::VecT; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - testing::TestThrowingCtor<VecT>(size); - - testing::TestThrowingCtor<VecT>(size, allocator_type{}); -} - -TYPED_TEST(OneSizeTest, SizeRefConstructor) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - testing::TestThrowingCtor<VecT>(size, value_type{}); - - testing::TestThrowingCtor<VecT>(size, value_type{}, allocator_type{}); -} - -TYPED_TEST(OneSizeTest, InitializerListConstructor) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - testing::TestThrowingCtor<VecT>( - ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size)); - - testing::TestThrowingCtor<VecT>( - ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size), allocator_type{}); -} - -TYPED_TEST(OneSizeTest, RangeConstructor) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - std::array<value_type, size> arr{}; - - testing::TestThrowingCtor<VecT>(arr.begin(), arr.end()); - - testing::TestThrowingCtor<VecT>(arr.begin(), arr.end(), allocator_type{}); -} - -TYPED_TEST(OneSizeTest, CopyConstructor) { - using VecT = typename TypeParam::VecT; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - VecT other_vec{size}; - - testing::TestThrowingCtor<VecT>(other_vec); - - testing::TestThrowingCtor<VecT>(other_vec, allocator_type{}); -} - -TYPED_TEST(OneSizeTest, MoveConstructor) { - using VecT = typename TypeParam::VecT; - using allocator_type = typename VecT::allocator_type; - constexpr static auto size = TypeParam::GetSizeAt(0); - - if (!absl::allocator_is_nothrow<allocator_type>::value) { - testing::TestThrowingCtor<VecT>(VecT{size}); - - testing::TestThrowingCtor<VecT>(VecT{size}, allocator_type{}); - } -} - -TYPED_TEST(TwoSizeTest, Assign) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - constexpr static auto to_size = TypeParam::GetSizeAt(1); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - *vec = ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - VecT other_vec{to_size}; - *vec = other_vec; - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - VecT other_vec{to_size}; - *vec = std::move(other_vec); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - value_type val{}; - vec->assign(to_size, val); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->assign(ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size)); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - std::array<value_type, to_size> arr{}; - vec->assign(arr.begin(), arr.end()); - })); -} - -TYPED_TEST(TwoSizeTest, Resize) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - constexpr static auto to_size = TypeParam::GetSizeAt(1); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>, - testing::strong_guarantee); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->resize(to_size); // - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->resize(to_size, value_type{}); // - })); -} - -TYPED_TEST(OneSizeTest, Insert) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->insert(it, value_type{}); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->insert(it, value_type{}); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->end(); - vec->insert(it, value_type{}); - })); -} - -TYPED_TEST(TwoSizeTest, Insert) { - using VecT = typename TypeParam::VecT; - using value_type = typename VecT::value_type; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - constexpr static auto count = TypeParam::GetSizeAt(1); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->insert(it, count, value_type{}); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->insert(it, count, value_type{}); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->end(); - vec->insert(it, count, value_type{}); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count)); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count)); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->end(); - vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count)); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - std::array<value_type, count> arr{}; - vec->insert(it, arr.begin(), arr.end()); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - std::array<value_type, count> arr{}; - vec->insert(it, arr.begin(), arr.end()); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->end(); - std::array<value_type, count> arr{}; - vec->insert(it, arr.begin(), arr.end()); - })); -} - -TYPED_TEST(OneSizeTest, EmplaceBack) { - using VecT = typename TypeParam::VecT; - constexpr static auto size = TypeParam::GetSizeAt(0); - - // For testing calls to `emplace_back(...)` that reallocate. - VecT full_vec{size}; - full_vec.resize(full_vec.capacity()); - - // For testing calls to `emplace_back(...)` that don't reallocate. - VecT nonfull_vec{size}; - nonfull_vec.reserve(size + 1); - - auto tester = testing::MakeExceptionSafetyTester().WithContracts( - InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.WithInitialValue(nonfull_vec).Test([](VecT* vec) { - vec->emplace_back(); - })); - - EXPECT_TRUE(tester.WithInitialValue(full_vec).Test( - [](VecT* vec) { vec->emplace_back(); })); -} - -TYPED_TEST(OneSizeTest, PopBack) { - using VecT = typename TypeParam::VecT; - constexpr static auto size = TypeParam::GetSizeAt(0); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{size}) - .WithContracts(NoThrowGuarantee<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->pop_back(); // - })); -} - -TYPED_TEST(OneSizeTest, Erase) { - using VecT = typename TypeParam::VecT; - constexpr static auto size = TypeParam::GetSizeAt(0); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->erase(it); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->erase(it); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() - 1); - vec->erase(it); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->erase(it, it); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->erase(it, it); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() - 1); - vec->erase(it, it); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin(); - vec->erase(it, it + 1); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() / 2); - vec->erase(it, it + 1); - })); - EXPECT_TRUE(tester.Test([](VecT* vec) { - auto it = vec->begin() + (vec->size() - 1); - vec->erase(it, it + 1); - })); -} - -TYPED_TEST(OneSizeTest, Clear) { - using VecT = typename TypeParam::VecT; - constexpr static auto size = TypeParam::GetSizeAt(0); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{size}) - .WithContracts(NoThrowGuarantee<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->clear(); // - })); -} - -TYPED_TEST(TwoSizeTest, Reserve) { - using VecT = typename TypeParam::VecT; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - constexpr static auto to_capacity = TypeParam::GetSizeAt(1); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { vec->reserve(to_capacity); })); -} - -TYPED_TEST(OneSizeTest, ShrinkToFit) { - using VecT = typename TypeParam::VecT; - constexpr static auto size = TypeParam::GetSizeAt(0); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - vec->shrink_to_fit(); // - })); -} - -TYPED_TEST(TwoSizeTest, Swap) { - using VecT = typename TypeParam::VecT; - constexpr static auto from_size = TypeParam::GetSizeAt(0); - constexpr static auto to_size = TypeParam::GetSizeAt(1); - - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(VecT{from_size}) - .WithContracts(InlinedVectorInvariants<VecT>); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - VecT other_vec{to_size}; - vec->swap(other_vec); - })); - - EXPECT_TRUE(tester.Test([](VecT* vec) { - using std::swap; - VecT other_vec{to_size}; - swap(*vec, other_vec); - })); -} - -} // namespace - -#endif // defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/container/inlined_vector_test.cc b/third_party/abseil_cpp/absl/container/inlined_vector_test.cc deleted file mode 100644 index 98aff33498b2..000000000000 --- a/third_party/abseil_cpp/absl/container/inlined_vector_test.cc +++ /dev/null @@ -1,1815 +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/container/inlined_vector.h" - -#include <algorithm> -#include <forward_list> -#include <list> -#include <memory> -#include <scoped_allocator> -#include <sstream> -#include <stdexcept> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/internal/exception_testing.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/base/options.h" -#include "absl/container/internal/counting_allocator.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/hash/hash_testing.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" - -namespace { - -using absl::container_internal::CountingAllocator; -using absl::test_internal::CopyableMovableInstance; -using absl::test_internal::CopyableOnlyInstance; -using absl::test_internal::InstanceTracker; -using testing::AllOf; -using testing::Each; -using testing::ElementsAre; -using testing::ElementsAreArray; -using testing::Eq; -using testing::Gt; -using testing::PrintToString; - -using IntVec = absl::InlinedVector<int, 8>; - -MATCHER_P(SizeIs, n, "") { - return testing::ExplainMatchResult(n, arg.size(), result_listener); -} - -MATCHER_P(CapacityIs, n, "") { - return testing::ExplainMatchResult(n, arg.capacity(), result_listener); -} - -MATCHER_P(ValueIs, e, "") { - return testing::ExplainMatchResult(e, arg.value(), result_listener); -} - -// TODO(bsamwel): Add support for movable-only types. - -// Test fixture for typed tests on BaseCountedInstance derived classes, see -// test_instance_tracker.h. -template <typename T> -class InstanceTest : public ::testing::Test {}; -TYPED_TEST_SUITE_P(InstanceTest); - -// A simple reference counted class to make sure that the proper elements are -// destroyed in the erase(begin, end) test. -class RefCounted { - public: - RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); } - - RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) { - Ref(); - } - - ~RefCounted() { - Unref(); - count_ = nullptr; - } - - friend void swap(RefCounted& a, RefCounted& b) { - using std::swap; - swap(a.value_, b.value_); - swap(a.count_, b.count_); - } - - RefCounted& operator=(RefCounted v) { - using std::swap; - swap(*this, v); - return *this; - } - - void Ref() const { - ABSL_RAW_CHECK(count_ != nullptr, ""); - ++(*count_); - } - - void Unref() const { - --(*count_); - ABSL_RAW_CHECK(*count_ >= 0, ""); - } - - int value_; - int* count_; -}; - -using RefCountedVec = absl::InlinedVector<RefCounted, 8>; - -// A class with a vtable pointer -class Dynamic { - public: - virtual ~Dynamic() {} -}; - -using DynamicVec = absl::InlinedVector<Dynamic, 8>; - -// Append 0..len-1 to *v -template <typename Container> -static void Fill(Container* v, int len, int offset = 0) { - for (int i = 0; i < len; i++) { - v->push_back(i + offset); - } -} - -static IntVec Fill(int len, int offset = 0) { - IntVec v; - Fill(&v, len, offset); - return v; -} - -TEST(IntVec, SimpleOps) { - for (int len = 0; len < 20; len++) { - IntVec v; - const IntVec& cv = v; // const alias - - Fill(&v, len); - EXPECT_EQ(len, v.size()); - EXPECT_LE(len, v.capacity()); - - for (int i = 0; i < len; i++) { - EXPECT_EQ(i, v[i]); - EXPECT_EQ(i, v.at(i)); - } - EXPECT_EQ(v.begin(), v.data()); - EXPECT_EQ(cv.begin(), cv.data()); - - int counter = 0; - for (IntVec::iterator iter = v.begin(); iter != v.end(); ++iter) { - EXPECT_EQ(counter, *iter); - counter++; - } - EXPECT_EQ(counter, len); - - counter = 0; - for (IntVec::const_iterator iter = v.begin(); iter != v.end(); ++iter) { - EXPECT_EQ(counter, *iter); - counter++; - } - EXPECT_EQ(counter, len); - - counter = 0; - for (IntVec::const_iterator iter = v.cbegin(); iter != v.cend(); ++iter) { - EXPECT_EQ(counter, *iter); - counter++; - } - EXPECT_EQ(counter, len); - - if (len > 0) { - EXPECT_EQ(0, v.front()); - EXPECT_EQ(len - 1, v.back()); - v.pop_back(); - EXPECT_EQ(len - 1, v.size()); - for (int i = 0; i < v.size(); ++i) { - EXPECT_EQ(i, v[i]); - EXPECT_EQ(i, v.at(i)); - } - } - } -} - -TEST(IntVec, PopBackNoOverflow) { - IntVec v = {1}; - v.pop_back(); - EXPECT_EQ(v.size(), 0); -} - -TEST(IntVec, AtThrows) { - IntVec v = {1, 2, 3}; - EXPECT_EQ(v.at(2), 3); - ABSL_BASE_INTERNAL_EXPECT_FAIL(v.at(3), std::out_of_range, - "failed bounds check"); -} - -TEST(IntVec, ReverseIterator) { - for (int len = 0; len < 20; len++) { - IntVec v; - Fill(&v, len); - - int counter = len; - for (IntVec::reverse_iterator iter = v.rbegin(); iter != v.rend(); ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = len; - for (IntVec::const_reverse_iterator iter = v.rbegin(); iter != v.rend(); - ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - - counter = len; - for (IntVec::const_reverse_iterator iter = v.crbegin(); iter != v.crend(); - ++iter) { - counter--; - EXPECT_EQ(counter, *iter); - } - EXPECT_EQ(counter, 0); - } -} - -TEST(IntVec, Erase) { - for (int len = 1; len < 20; len++) { - for (int i = 0; i < len; ++i) { - IntVec v; - Fill(&v, len); - v.erase(v.begin() + i); - EXPECT_EQ(len - 1, v.size()); - for (int j = 0; j < i; ++j) { - EXPECT_EQ(j, v[j]); - } - for (int j = i; j < len - 1; ++j) { - EXPECT_EQ(j + 1, v[j]); - } - } - } -} - -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. -TEST(RefCountedVec, EraseBeginEnd) { - for (int len = 1; len < 20; ++len) { - for (int erase_begin = 0; erase_begin < len; ++erase_begin) { - for (int erase_end = erase_begin; erase_end <= len; ++erase_end) { - std::vector<int> counts(len, 0); - RefCountedVec v; - for (int i = 0; i < len; ++i) { - v.push_back(RefCounted(i, &counts[i])); - } - - int erase_len = erase_end - erase_begin; - - v.erase(v.begin() + erase_begin, v.begin() + erase_end); - - EXPECT_EQ(len - erase_len, v.size()); - - // Check the elements before the first element erased. - for (int i = 0; i < erase_begin; ++i) { - EXPECT_EQ(i, v[i].value_); - } - - // Check the elements after the first element erased. - for (int i = erase_begin; i < v.size(); ++i) { - EXPECT_EQ(i + erase_len, v[i].value_); - } - - // Check that the elements at the beginning are preserved. - for (int i = 0; i < erase_begin; ++i) { - EXPECT_EQ(1, counts[i]); - } - - // Check that the erased elements are destroyed - for (int i = erase_begin; i < erase_end; ++i) { - EXPECT_EQ(0, counts[i]); - } - - // Check that the elements at the end are preserved. - for (int i = erase_end; i < len; ++i) { - EXPECT_EQ(1, counts[i]); - } - } - } - } -} - -struct NoDefaultCtor { - explicit NoDefaultCtor(int) {} -}; -struct NoCopy { - NoCopy() {} - NoCopy(const NoCopy&) = delete; -}; -struct NoAssign { - NoAssign() {} - NoAssign& operator=(const NoAssign&) = delete; -}; -struct MoveOnly { - MoveOnly() {} - MoveOnly(MoveOnly&&) = default; - MoveOnly& operator=(MoveOnly&&) = default; -}; -TEST(InlinedVectorTest, NoDefaultCtor) { - absl::InlinedVector<NoDefaultCtor, 1> v(10, NoDefaultCtor(2)); - (void)v; -} -TEST(InlinedVectorTest, NoCopy) { - absl::InlinedVector<NoCopy, 1> v(10); - (void)v; -} -TEST(InlinedVectorTest, NoAssign) { - absl::InlinedVector<NoAssign, 1> v(10); - (void)v; -} -TEST(InlinedVectorTest, MoveOnly) { - absl::InlinedVector<MoveOnly, 2> v; - v.push_back(MoveOnly{}); - v.push_back(MoveOnly{}); - v.push_back(MoveOnly{}); - v.erase(v.begin()); - v.push_back(MoveOnly{}); - v.erase(v.begin(), v.begin() + 1); - v.insert(v.begin(), MoveOnly{}); - v.emplace(v.begin()); - v.emplace(v.begin(), MoveOnly{}); -} -TEST(InlinedVectorTest, Noexcept) { - EXPECT_TRUE(std::is_nothrow_move_constructible<IntVec>::value); - EXPECT_TRUE((std::is_nothrow_move_constructible< - absl::InlinedVector<MoveOnly, 2>>::value)); - - struct MoveCanThrow { - MoveCanThrow(MoveCanThrow&&) {} - }; - EXPECT_EQ(absl::default_allocator_is_nothrow::value, - (std::is_nothrow_move_constructible< - absl::InlinedVector<MoveCanThrow, 2>>::value)); -} - -TEST(InlinedVectorTest, EmplaceBack) { - absl::InlinedVector<std::pair<std::string, int>, 1> v; - - auto& inlined_element = v.emplace_back("answer", 42); - EXPECT_EQ(&inlined_element, &v[0]); - EXPECT_EQ(inlined_element.first, "answer"); - EXPECT_EQ(inlined_element.second, 42); - - auto& allocated_element = v.emplace_back("taxicab", 1729); - EXPECT_EQ(&allocated_element, &v[1]); - EXPECT_EQ(allocated_element.first, "taxicab"); - EXPECT_EQ(allocated_element.second, 1729); -} - -TEST(InlinedVectorTest, ShrinkToFitGrowingVector) { - absl::InlinedVector<std::pair<std::string, int>, 1> v; - - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 1); - - v.emplace_back("answer", 42); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 1); - - v.emplace_back("taxicab", 1729); - EXPECT_GE(v.capacity(), 2); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 2); - - v.reserve(100); - EXPECT_GE(v.capacity(), 100); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 2); -} - -TEST(InlinedVectorTest, ShrinkToFitEdgeCases) { - { - absl::InlinedVector<std::pair<std::string, int>, 1> v; - v.emplace_back("answer", 42); - v.emplace_back("taxicab", 1729); - EXPECT_GE(v.capacity(), 2); - v.pop_back(); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 1); - EXPECT_EQ(v[0].first, "answer"); - EXPECT_EQ(v[0].second, 42); - } - - { - absl::InlinedVector<std::string, 2> v(100); - v.resize(0); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 2); // inlined capacity - } - - { - absl::InlinedVector<std::string, 2> v(100); - v.resize(1); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 2); // inlined capacity - } - - { - absl::InlinedVector<std::string, 2> v(100); - v.resize(2); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 2); - } - - { - absl::InlinedVector<std::string, 2> v(100); - v.resize(3); - v.shrink_to_fit(); - EXPECT_EQ(v.capacity(), 3); - } -} - -TEST(IntVec, Insert) { - for (int len = 0; len < 20; len++) { - for (int pos = 0; pos <= len; pos++) { - { - // Single element - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - std_v.insert(std_v.begin() + pos, 9999); - IntVec::iterator it = v.insert(v.cbegin() + pos, 9999); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - { - // n elements - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - IntVec::size_type n = 5; - std_v.insert(std_v.begin() + pos, n, 9999); - IntVec::iterator it = v.insert(v.cbegin() + pos, n, 9999); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - { - // Iterator range (random access iterator) - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - const std::vector<int> input = {9999, 8888, 7777}; - std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend()); - IntVec::iterator it = - v.insert(v.cbegin() + pos, input.cbegin(), input.cend()); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - { - // Iterator range (forward iterator) - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - const std::forward_list<int> input = {9999, 8888, 7777}; - std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend()); - IntVec::iterator it = - v.insert(v.cbegin() + pos, input.cbegin(), input.cend()); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - { - // Iterator range (input iterator) - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - std_v.insert(std_v.begin() + pos, {9999, 8888, 7777}); - std::istringstream input("9999 8888 7777"); - IntVec::iterator it = - v.insert(v.cbegin() + pos, std::istream_iterator<int>(input), - std::istream_iterator<int>()); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - { - // Initializer list - std::vector<int> std_v; - Fill(&std_v, len); - IntVec v; - Fill(&v, len); - - std_v.insert(std_v.begin() + pos, {9999, 8888}); - IntVec::iterator it = v.insert(v.cbegin() + pos, {9999, 8888}); - EXPECT_THAT(v, ElementsAreArray(std_v)); - EXPECT_EQ(it, v.cbegin() + pos); - } - } - } -} - -TEST(RefCountedVec, InsertConstructorDestructor) { - // Make sure the proper construction/destruction happen during insert - // operations. - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - for (int pos = 0; pos <= len; pos++) { - SCOPED_TRACE(pos); - std::vector<int> counts(len, 0); - int inserted_count = 0; - RefCountedVec v; - for (int i = 0; i < len; ++i) { - SCOPED_TRACE(i); - v.push_back(RefCounted(i, &counts[i])); - } - - EXPECT_THAT(counts, Each(Eq(1))); - - RefCounted insert_element(9999, &inserted_count); - EXPECT_EQ(1, inserted_count); - v.insert(v.begin() + pos, insert_element); - EXPECT_EQ(2, inserted_count); - // Check that the elements at the end are preserved. - EXPECT_THAT(counts, Each(Eq(1))); - EXPECT_EQ(2, inserted_count); - } - } -} - -TEST(IntVec, Resize) { - for (int len = 0; len < 20; len++) { - IntVec v; - Fill(&v, len); - - // Try resizing up and down by k elements - static const int kResizeElem = 1000000; - for (int k = 0; k < 10; k++) { - // Enlarging resize - v.resize(len + k, kResizeElem); - EXPECT_EQ(len + k, v.size()); - EXPECT_LE(len + k, v.capacity()); - for (int i = 0; i < len + k; i++) { - if (i < len) { - EXPECT_EQ(i, v[i]); - } else { - EXPECT_EQ(kResizeElem, v[i]); - } - } - - // Shrinking resize - v.resize(len, kResizeElem); - EXPECT_EQ(len, v.size()); - EXPECT_LE(len, v.capacity()); - for (int i = 0; i < len; i++) { - EXPECT_EQ(i, v[i]); - } - } - } -} - -TEST(IntVec, InitWithLength) { - for (int len = 0; len < 20; len++) { - IntVec v(len, 7); - EXPECT_EQ(len, v.size()); - EXPECT_LE(len, v.capacity()); - for (int i = 0; i < len; i++) { - EXPECT_EQ(7, v[i]); - } - } -} - -TEST(IntVec, CopyConstructorAndAssignment) { - for (int len = 0; len < 20; len++) { - IntVec v; - Fill(&v, len); - EXPECT_EQ(len, v.size()); - EXPECT_LE(len, v.capacity()); - - IntVec v2(v); - EXPECT_TRUE(v == v2) << PrintToString(v) << PrintToString(v2); - - for (int start_len = 0; start_len < 20; start_len++) { - IntVec v3; - Fill(&v3, start_len, 99); // Add dummy elements that should go away - v3 = v; - EXPECT_TRUE(v == v3) << PrintToString(v) << PrintToString(v3); - } - } -} - -TEST(IntVec, AliasingCopyAssignment) { - for (int len = 0; len < 20; ++len) { - IntVec original; - Fill(&original, len); - IntVec dup = original; - dup = *&dup; - EXPECT_EQ(dup, original); - } -} - -TEST(IntVec, MoveConstructorAndAssignment) { - for (int len = 0; len < 20; len++) { - IntVec v_in; - const int inlined_capacity = v_in.capacity(); - Fill(&v_in, len); - EXPECT_EQ(len, v_in.size()); - EXPECT_LE(len, v_in.capacity()); - - { - IntVec v_temp(v_in); - auto* old_data = v_temp.data(); - IntVec v_out(std::move(v_temp)); - EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out); - if (v_in.size() > inlined_capacity) { - // Allocation is moved as a whole, data stays in place. - EXPECT_TRUE(v_out.data() == old_data); - } else { - EXPECT_FALSE(v_out.data() == old_data); - } - } - for (int start_len = 0; start_len < 20; start_len++) { - IntVec v_out; - Fill(&v_out, start_len, 99); // Add dummy elements that should go away - IntVec v_temp(v_in); - auto* old_data = v_temp.data(); - v_out = std::move(v_temp); - EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out); - if (v_in.size() > inlined_capacity) { - // Allocation is moved as a whole, data stays in place. - EXPECT_TRUE(v_out.data() == old_data); - } else { - EXPECT_FALSE(v_out.data() == old_data); - } - } - } -} - -class NotTriviallyDestructible { - public: - NotTriviallyDestructible() : p_(new int(1)) {} - explicit NotTriviallyDestructible(int i) : p_(new int(i)) {} - - NotTriviallyDestructible(const NotTriviallyDestructible& other) - : p_(new int(*other.p_)) {} - - NotTriviallyDestructible& operator=(const NotTriviallyDestructible& other) { - p_ = absl::make_unique<int>(*other.p_); - return *this; - } - - bool operator==(const NotTriviallyDestructible& other) const { - return *p_ == *other.p_; - } - - private: - std::unique_ptr<int> p_; -}; - -TEST(AliasingTest, Emplace) { - for (int i = 2; i < 20; ++i) { - absl::InlinedVector<NotTriviallyDestructible, 10> vec; - for (int j = 0; j < i; ++j) { - vec.push_back(NotTriviallyDestructible(j)); - } - vec.emplace(vec.begin(), vec[0]); - EXPECT_EQ(vec[0], vec[1]); - vec.emplace(vec.begin() + i / 2, vec[i / 2]); - EXPECT_EQ(vec[i / 2], vec[i / 2 + 1]); - vec.emplace(vec.end() - 1, vec.back()); - EXPECT_EQ(vec[vec.size() - 2], vec.back()); - } -} - -TEST(AliasingTest, InsertWithCount) { - for (int i = 1; i < 20; ++i) { - absl::InlinedVector<NotTriviallyDestructible, 10> vec; - for (int j = 0; j < i; ++j) { - vec.push_back(NotTriviallyDestructible(j)); - } - for (int n = 0; n < 5; ++n) { - // We use back where we can because it's guaranteed to become invalidated - vec.insert(vec.begin(), n, vec.back()); - auto b = vec.begin(); - EXPECT_TRUE( - std::all_of(b, b + n, [&vec](const NotTriviallyDestructible& x) { - return x == vec.back(); - })); - - auto m_idx = vec.size() / 2; - vec.insert(vec.begin() + m_idx, n, vec.back()); - auto m = vec.begin() + m_idx; - EXPECT_TRUE( - std::all_of(m, m + n, [&vec](const NotTriviallyDestructible& x) { - return x == vec.back(); - })); - - // We want distinct values so the equality test is meaningful, - // vec[vec.size() - 1] is also almost always invalidated. - auto old_e = vec.size() - 1; - auto val = vec[old_e]; - vec.insert(vec.end(), n, vec[old_e]); - auto e = vec.begin() + old_e; - EXPECT_TRUE(std::all_of( - e, e + n, - [&val](const NotTriviallyDestructible& x) { return x == val; })); - } - } -} - -TEST(OverheadTest, Storage) { - // Check for size overhead. - // 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])); -} - -TEST(IntVec, Clear) { - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - IntVec v; - Fill(&v, len); - v.clear(); - EXPECT_EQ(0, v.size()); - EXPECT_EQ(v.begin(), v.end()); - } -} - -TEST(IntVec, Reserve) { - for (int len = 0; len < 20; len++) { - IntVec v; - Fill(&v, len); - - for (int newlen = 0; newlen < 100; newlen++) { - const int* start_rep = v.data(); - v.reserve(newlen); - const int* final_rep = v.data(); - if (newlen <= len) { - EXPECT_EQ(start_rep, final_rep); - } - EXPECT_LE(newlen, v.capacity()); - - // Filling up to newlen should not change rep - while (v.size() < newlen) { - v.push_back(0); - } - EXPECT_EQ(final_rep, v.data()); - } - } -} - -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."; - std_v.push_back(s); - v.push_back(s); - for (int i = 0; i < 20; ++i) { - EXPECT_THAT(v, ElementsAreArray(std_v)); - - v.push_back(v.back()); - std_v.push_back(std_v.back()); - } - EXPECT_THAT(v, ElementsAreArray(std_v)); -} - -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."; - std_v.push_back(s); - v.push_back(s); - for (int i = 0; i < 20; ++i) { - EXPECT_EQ(v.back(), std_v.back()); - - v.push_back(std::move(v.back())); - std_v.push_back(std::move(std_v.back())); - } - EXPECT_EQ(v.back(), std_v.back()); -} - -TEST(StringVec, SelfMove) { - const std::string s = "A quite long string to ensure heap."; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - absl::InlinedVector<std::string, 8> v; - for (int i = 0; i < len; ++i) { - SCOPED_TRACE(i); - v.push_back(s); - } - // Indirection necessary to avoid compiler warning. - v = std::move(*(&v)); - // Ensure that the inlined vector is still in a valid state by copying it. - // We don't expect specific contents since a self-move results in an - // unspecified valid state. - std::vector<std::string> copy(v.begin(), v.end()); - } -} - -TEST(IntVec, Swap) { - for (int l1 = 0; l1 < 20; l1++) { - SCOPED_TRACE(l1); - for (int l2 = 0; l2 < 20; l2++) { - SCOPED_TRACE(l2); - IntVec a = Fill(l1, 0); - IntVec b = Fill(l2, 100); - { - using std::swap; - swap(a, b); - } - EXPECT_EQ(l1, b.size()); - EXPECT_EQ(l2, a.size()); - for (int i = 0; i < l1; i++) { - SCOPED_TRACE(i); - EXPECT_EQ(i, b[i]); - } - for (int i = 0; i < l2; i++) { - SCOPED_TRACE(i); - EXPECT_EQ(100 + i, a[i]); - } - } - } -} - -TYPED_TEST_P(InstanceTest, Swap) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - for (int l1 = 0; l1 < 20; l1++) { - SCOPED_TRACE(l1); - for (int l2 = 0; l2 < 20; l2++) { - SCOPED_TRACE(l2); - InstanceTracker tracker; - InstanceVec a, b; - const size_t inlined_capacity = a.capacity(); - auto min_len = std::min(l1, l2); - auto max_len = std::max(l1, l2); - for (int i = 0; i < l1; i++) a.push_back(Instance(i)); - for (int i = 0; i < l2; i++) b.push_back(Instance(100 + i)); - EXPECT_EQ(tracker.instances(), l1 + l2); - tracker.ResetCopiesMovesSwaps(); - { - using std::swap; - swap(a, b); - } - EXPECT_EQ(tracker.instances(), l1 + l2); - if (a.size() > inlined_capacity && b.size() > inlined_capacity) { - EXPECT_EQ(tracker.swaps(), 0); // Allocations are swapped. - EXPECT_EQ(tracker.moves(), 0); - } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) { - EXPECT_EQ(tracker.swaps(), min_len); - EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()), - max_len - min_len); - } else { - // One is allocated and the other isn't. The allocation is transferred - // without copying elements, and the inlined instances are copied/moved. - EXPECT_EQ(tracker.swaps(), 0); - EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()), - min_len); - } - - EXPECT_EQ(l1, b.size()); - EXPECT_EQ(l2, a.size()); - for (int i = 0; i < l1; i++) { - EXPECT_EQ(i, b[i].value()); - } - for (int i = 0; i < l2; i++) { - EXPECT_EQ(100 + i, a[i].value()); - } - } - } -} - -TEST(IntVec, EqualAndNotEqual) { - IntVec a, b; - EXPECT_TRUE(a == b); - EXPECT_FALSE(a != b); - - a.push_back(3); - EXPECT_FALSE(a == b); - EXPECT_TRUE(a != b); - - b.push_back(3); - EXPECT_TRUE(a == b); - EXPECT_FALSE(a != b); - - b.push_back(7); - EXPECT_FALSE(a == b); - EXPECT_TRUE(a != b); - - a.push_back(6); - EXPECT_FALSE(a == b); - EXPECT_TRUE(a != b); - - a.clear(); - b.clear(); - for (int i = 0; i < 100; i++) { - a.push_back(i); - b.push_back(i); - EXPECT_TRUE(a == b); - EXPECT_FALSE(a != b); - - b[i] = b[i] + 1; - EXPECT_FALSE(a == b); - EXPECT_TRUE(a != b); - - b[i] = b[i] - 1; // Back to before - EXPECT_TRUE(a == b); - EXPECT_FALSE(a != b); - } -} - -TEST(IntVec, RelationalOps) { - IntVec a, b; - EXPECT_FALSE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_FALSE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_TRUE(b >= a); - b.push_back(3); - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_TRUE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); - EXPECT_FALSE(a >= b); - EXPECT_TRUE(b >= a); -} - -TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - InstanceTracker tracker; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - tracker.ResetCopiesMovesSwaps(); - - InstanceVec v; - const size_t inlined_capacity = v.capacity(); - for (int i = 0; i < len; i++) { - v.push_back(Instance(i)); - } - EXPECT_EQ(tracker.instances(), len); - EXPECT_GE(tracker.copies() + tracker.moves(), - len); // More due to reallocation. - tracker.ResetCopiesMovesSwaps(); - - // Enlarging resize() must construct some objects - tracker.ResetCopiesMovesSwaps(); - v.resize(len + 10, Instance(100)); - EXPECT_EQ(tracker.instances(), len + 10); - if (len <= inlined_capacity && len + 10 > inlined_capacity) { - EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + len); - } else { - // Only specify a minimum number of copies + moves. We don't want to - // depend on the reallocation policy here. - EXPECT_GE(tracker.copies() + tracker.moves(), - 10); // More due to reallocation. - } - - // Shrinking resize() must destroy some objects - tracker.ResetCopiesMovesSwaps(); - v.resize(len, Instance(100)); - EXPECT_EQ(tracker.instances(), len); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 0); - - // reserve() must not increase the number of initialized objects - SCOPED_TRACE("reserve"); - v.reserve(len + 1000); - EXPECT_EQ(tracker.instances(), len); - EXPECT_EQ(tracker.copies() + tracker.moves(), len); - - // pop_back() and erase() must destroy one object - if (len > 0) { - tracker.ResetCopiesMovesSwaps(); - v.pop_back(); - EXPECT_EQ(tracker.instances(), len - 1); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 0); - - if (!v.empty()) { - tracker.ResetCopiesMovesSwaps(); - v.erase(v.begin()); - EXPECT_EQ(tracker.instances(), len - 2); - EXPECT_EQ(tracker.copies() + tracker.moves(), len - 2); - } - } - - tracker.ResetCopiesMovesSwaps(); - int instances_before_empty_erase = tracker.instances(); - v.erase(v.begin(), v.begin()); - EXPECT_EQ(tracker.instances(), instances_before_empty_erase); - EXPECT_EQ(tracker.copies() + tracker.moves(), 0); - } -} - -TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - InstanceTracker tracker; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - tracker.ResetCopiesMovesSwaps(); - - InstanceVec v; - for (int i = 0; i < len; i++) { - v.push_back(Instance(i)); - } - EXPECT_EQ(tracker.instances(), len); - EXPECT_GE(tracker.copies() + tracker.moves(), - len); // More due to reallocation. - tracker.ResetCopiesMovesSwaps(); - { // Copy constructor should create 'len' more instances. - InstanceVec v_copy(v); - EXPECT_EQ(tracker.instances(), len + len); - EXPECT_EQ(tracker.copies(), len); - EXPECT_EQ(tracker.moves(), 0); - } - EXPECT_EQ(tracker.instances(), len); - } -} - -TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - InstanceTracker tracker; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - tracker.ResetCopiesMovesSwaps(); - - InstanceVec v; - const size_t inlined_capacity = v.capacity(); - for (int i = 0; i < len; i++) { - v.push_back(Instance(i)); - } - EXPECT_EQ(tracker.instances(), len); - EXPECT_GE(tracker.copies() + tracker.moves(), - len); // More due to reallocation. - tracker.ResetCopiesMovesSwaps(); - { - InstanceVec v_copy(std::move(v)); - if (len > inlined_capacity) { - // Allocation is moved as a whole. - EXPECT_EQ(tracker.instances(), len); - EXPECT_EQ(tracker.live_instances(), len); - // Tests an implementation detail, don't rely on this in your code. - EXPECT_EQ(v.size(), 0); // NOLINT misc-use-after-move - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 0); - } else { - EXPECT_EQ(tracker.instances(), len + len); - if (Instance::supports_move()) { - EXPECT_EQ(tracker.live_instances(), len); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), len); - } else { - EXPECT_EQ(tracker.live_instances(), len + len); - EXPECT_EQ(tracker.copies(), len); - EXPECT_EQ(tracker.moves(), 0); - } - } - EXPECT_EQ(tracker.swaps(), 0); - } - } -} - -TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - InstanceTracker tracker; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - for (int longorshort = 0; longorshort <= 1; ++longorshort) { - SCOPED_TRACE(longorshort); - tracker.ResetCopiesMovesSwaps(); - - InstanceVec longer, shorter; - for (int i = 0; i < len; i++) { - longer.push_back(Instance(i)); - shorter.push_back(Instance(i)); - } - longer.push_back(Instance(len)); - EXPECT_EQ(tracker.instances(), len + len + 1); - EXPECT_GE(tracker.copies() + tracker.moves(), - len + len + 1); // More due to reallocation. - - tracker.ResetCopiesMovesSwaps(); - if (longorshort) { - shorter = longer; - EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1)); - EXPECT_GE(tracker.copies() + tracker.moves(), - len + 1); // More due to reallocation. - } else { - longer = shorter; - EXPECT_EQ(tracker.instances(), len + len); - EXPECT_EQ(tracker.copies() + tracker.moves(), len); - } - } - } -} - -TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) { - using Instance = TypeParam; - using InstanceVec = absl::InlinedVector<Instance, 8>; - InstanceTracker tracker; - for (int len = 0; len < 20; len++) { - SCOPED_TRACE(len); - for (int longorshort = 0; longorshort <= 1; ++longorshort) { - SCOPED_TRACE(longorshort); - tracker.ResetCopiesMovesSwaps(); - - InstanceVec longer, shorter; - const int inlined_capacity = longer.capacity(); - for (int i = 0; i < len; i++) { - longer.push_back(Instance(i)); - shorter.push_back(Instance(i)); - } - longer.push_back(Instance(len)); - EXPECT_EQ(tracker.instances(), len + len + 1); - EXPECT_GE(tracker.copies() + tracker.moves(), - len + len + 1); // More due to reallocation. - - tracker.ResetCopiesMovesSwaps(); - int src_len; - if (longorshort) { - src_len = len + 1; - shorter = std::move(longer); - } else { - src_len = len; - longer = std::move(shorter); - } - if (src_len > inlined_capacity) { - // Allocation moved as a whole. - EXPECT_EQ(tracker.instances(), src_len); - EXPECT_EQ(tracker.live_instances(), src_len); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 0); - } else { - // Elements are all copied. - EXPECT_EQ(tracker.instances(), src_len + src_len); - if (Instance::supports_move()) { - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), src_len); - EXPECT_EQ(tracker.live_instances(), src_len); - } else { - EXPECT_EQ(tracker.copies(), src_len); - EXPECT_EQ(tracker.moves(), 0); - EXPECT_EQ(tracker.live_instances(), src_len + src_len); - } - } - EXPECT_EQ(tracker.swaps(), 0); - } - } -} - -TEST(CountElemAssign, SimpleTypeWithInlineBacking) { - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<int> original_contents(original_size, 12345); - - absl::InlinedVector<int, 2> v(original_contents.begin(), - original_contents.end()); - v.assign(2, 123); - EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(123, 123))); - if (original_size <= 2) { - // If the original had inline backing, it should stay inline. - EXPECT_EQ(2, v.capacity()); - } - } -} - -TEST(CountElemAssign, SimpleTypeWithAllocation) { - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<int> original_contents(original_size, 12345); - - absl::InlinedVector<int, 2> v(original_contents.begin(), - original_contents.end()); - v.assign(3, 123); - EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(123, 123, 123))); - EXPECT_LE(v.size(), v.capacity()); - } -} - -TYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) { - using Instance = TypeParam; - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<Instance> original_contents(original_size, Instance(12345)); - - absl::InlinedVector<Instance, 2> v(original_contents.begin(), - original_contents.end()); - v.assign(2, Instance(123)); - EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(ValueIs(123), ValueIs(123)))); - if (original_size <= 2) { - // If the original had inline backing, it should stay inline. - EXPECT_EQ(2, v.capacity()); - } - } -} - -template <typename Instance> -void InstanceCountElemAssignWithAllocationTest() { - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<Instance> original_contents(original_size, Instance(12345)); - - absl::InlinedVector<Instance, 2> v(original_contents.begin(), - original_contents.end()); - v.assign(3, Instance(123)); - EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(ValueIs(123), ValueIs(123), - ValueIs(123)))); - EXPECT_LE(v.size(), v.capacity()); - } -} -TEST(CountElemAssign, WithAllocationCopyableInstance) { - InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>(); -} -TEST(CountElemAssign, WithAllocationCopyableMovableInstance) { - InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>(); -} - -TEST(RangedConstructor, SimpleType) { - std::vector<int> source_v = {4, 5, 6}; - // First try to fit in inline backing - absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end()); - EXPECT_EQ(3, v.size()); - EXPECT_EQ(4, v.capacity()); // Indication that we're still on inlined storage - EXPECT_EQ(4, v[0]); - EXPECT_EQ(5, v[1]); - EXPECT_EQ(6, v[2]); - - // Now, force a re-allocate - absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end()); - EXPECT_EQ(3, realloc_v.size()); - EXPECT_LT(2, realloc_v.capacity()); - EXPECT_EQ(4, realloc_v[0]); - EXPECT_EQ(5, realloc_v[1]); - EXPECT_EQ(6, realloc_v[2]); -} - -// Test for ranged constructors using Instance as the element type and -// SourceContainer as the source container type. -template <typename Instance, typename SourceContainer, int inlined_capacity> -void InstanceRangedConstructorTestForContainer() { - InstanceTracker tracker; - SourceContainer source_v = {Instance(0), Instance(1)}; - tracker.ResetCopiesMovesSwaps(); - absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(), - source_v.end()); - EXPECT_EQ(2, v.size()); - EXPECT_LT(1, v.capacity()); - EXPECT_EQ(0, v[0].value()); - EXPECT_EQ(1, v[1].value()); - EXPECT_EQ(tracker.copies(), 2); - EXPECT_EQ(tracker.moves(), 0); -} - -template <typename Instance, int inlined_capacity> -void InstanceRangedConstructorTestWithCapacity() { - // Test with const and non-const, random access and non-random-access sources. - // TODO(bsamwel): Test with an input iterator source. - { - SCOPED_TRACE("std::list"); - InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>, - inlined_capacity>(); - { - SCOPED_TRACE("const std::list"); - InstanceRangedConstructorTestForContainer< - Instance, const std::list<Instance>, inlined_capacity>(); - } - { - SCOPED_TRACE("std::vector"); - InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>, - inlined_capacity>(); - } - { - SCOPED_TRACE("const std::vector"); - InstanceRangedConstructorTestForContainer< - Instance, const std::vector<Instance>, inlined_capacity>(); - } - } -} - -TYPED_TEST_P(InstanceTest, RangedConstructor) { - using Instance = TypeParam; - SCOPED_TRACE("capacity=1"); - InstanceRangedConstructorTestWithCapacity<Instance, 1>(); - SCOPED_TRACE("capacity=2"); - InstanceRangedConstructorTestWithCapacity<Instance, 2>(); -} - -TEST(RangedConstructor, ElementsAreConstructed) { - std::vector<std::string> source_v = {"cat", "dog"}; - - // Force expansion and re-allocation of v. Ensures that when the vector is - // expanded that new elements are constructed. - absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end()); - EXPECT_EQ("cat", v[0]); - EXPECT_EQ("dog", v[1]); -} - -TEST(RangedAssign, SimpleType) { - // Test for all combinations of original sizes (empty and non-empty inline, - // and out of line) and target sizes. - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<int> original_contents(original_size, 12345); - - for (size_t target_size = 0; target_size <= 5; ++target_size) { - SCOPED_TRACE(target_size); - - // New contents are [3, 4, ...] - std::vector<int> new_contents; - for (size_t i = 0; i < target_size; ++i) { - new_contents.push_back(i + 3); - } - - absl::InlinedVector<int, 3> v(original_contents.begin(), - original_contents.end()); - v.assign(new_contents.begin(), new_contents.end()); - - EXPECT_EQ(new_contents.size(), v.size()); - EXPECT_LE(new_contents.size(), v.capacity()); - if (target_size <= 3 && original_size <= 3) { - // Storage should stay inline when target size is small. - EXPECT_EQ(3, v.capacity()); - } - EXPECT_THAT(v, ElementsAreArray(new_contents)); - } - } -} - -// Returns true if lhs and rhs have the same value. -template <typename Instance> -static bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) { - return lhs.value() == rhs.value(); -} - -// Test for ranged assign() using Instance as the element type and -// SourceContainer as the source container type. -template <typename Instance, typename SourceContainer> -void InstanceRangedAssignTestForContainer() { - // Test for all combinations of original sizes (empty and non-empty inline, - // and out of line) and target sizes. - for (size_t original_size = 0; original_size <= 5; ++original_size) { - SCOPED_TRACE(original_size); - // Original contents are [12345, 12345, ...] - std::vector<Instance> original_contents(original_size, Instance(12345)); - - for (size_t target_size = 0; target_size <= 5; ++target_size) { - SCOPED_TRACE(target_size); - - // New contents are [3, 4, ...] - // Generate data using a non-const container, because SourceContainer - // itself may be const. - // TODO(bsamwel): Test with an input iterator. - std::vector<Instance> new_contents_in; - for (size_t i = 0; i < target_size; ++i) { - new_contents_in.push_back(Instance(i + 3)); - } - SourceContainer new_contents(new_contents_in.begin(), - new_contents_in.end()); - - absl::InlinedVector<Instance, 3> v(original_contents.begin(), - original_contents.end()); - v.assign(new_contents.begin(), new_contents.end()); - - EXPECT_EQ(new_contents.size(), v.size()); - EXPECT_LE(new_contents.size(), v.capacity()); - if (target_size <= 3 && original_size <= 3) { - // Storage should stay inline when target size is small. - EXPECT_EQ(3, v.capacity()); - } - EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(), - InstanceValuesEqual<Instance>)); - } - } -} - -TYPED_TEST_P(InstanceTest, RangedAssign) { - using Instance = TypeParam; - // Test with const and non-const, random access and non-random-access sources. - // TODO(bsamwel): Test with an input iterator source. - SCOPED_TRACE("std::list"); - InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>(); - SCOPED_TRACE("const std::list"); - InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>(); - SCOPED_TRACE("std::vector"); - InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>(); - SCOPED_TRACE("const std::vector"); - InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>(); -} - -TEST(InitializerListConstructor, SimpleTypeWithInlineBacking) { - EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}), - AllOf(SizeIs(3), CapacityIs(4), ElementsAre(4, 5, 6))); -} - -TEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) { - EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}), - AllOf(SizeIs(3), CapacityIs(Gt(2)), ElementsAre(4, 5, 6))); -} - -TEST(InitializerListConstructor, DisparateTypesInList) { - EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8)); - - EXPECT_THAT((absl::InlinedVector<std::string, 2>{"foo", std::string("bar")}), - ElementsAre("foo", "bar")); -} - -TEST(InitializerListConstructor, ComplexTypeWithInlineBacking) { - EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{ - CopyableMovableInstance(0)}), - AllOf(SizeIs(1), CapacityIs(1), ElementsAre(ValueIs(0)))); -} - -TEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) { - EXPECT_THAT( - (absl::InlinedVector<CopyableMovableInstance, 1>{ - CopyableMovableInstance(0), CopyableMovableInstance(1)}), - AllOf(SizeIs(2), CapacityIs(Gt(1)), ElementsAre(ValueIs(0), ValueIs(1)))); -} - -TEST(InitializerListAssign, SimpleTypeFitsInlineBacking) { - for (size_t original_size = 0; original_size <= 4; ++original_size) { - SCOPED_TRACE(original_size); - - absl::InlinedVector<int, 2> v1(original_size, 12345); - const size_t original_capacity_v1 = v1.capacity(); - v1.assign({3}); - EXPECT_THAT( - v1, AllOf(SizeIs(1), CapacityIs(original_capacity_v1), ElementsAre(3))); - - absl::InlinedVector<int, 2> v2(original_size, 12345); - const size_t original_capacity_v2 = v2.capacity(); - v2 = {3}; - EXPECT_THAT( - v2, AllOf(SizeIs(1), CapacityIs(original_capacity_v2), ElementsAre(3))); - } -} - -TEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) { - for (size_t original_size = 0; original_size <= 4; ++original_size) { - SCOPED_TRACE(original_size); - absl::InlinedVector<int, 2> v1(original_size, 12345); - v1.assign({3, 4, 5}); - EXPECT_THAT(v1, AllOf(SizeIs(3), ElementsAre(3, 4, 5))); - EXPECT_LE(3, v1.capacity()); - - absl::InlinedVector<int, 2> v2(original_size, 12345); - v2 = {3, 4, 5}; - EXPECT_THAT(v2, AllOf(SizeIs(3), ElementsAre(3, 4, 5))); - EXPECT_LE(3, v2.capacity()); - } -} - -TEST(InitializerListAssign, DisparateTypesInList) { - absl::InlinedVector<int, 2> v_int1; - v_int1.assign({-7, 8ULL}); - EXPECT_THAT(v_int1, ElementsAre(-7, 8)); - - absl::InlinedVector<int, 2> v_int2; - v_int2 = {-7, 8ULL}; - EXPECT_THAT(v_int2, ElementsAre(-7, 8)); - - absl::InlinedVector<std::string, 2> v_string1; - v_string1.assign({"foo", std::string("bar")}); - EXPECT_THAT(v_string1, ElementsAre("foo", "bar")); - - absl::InlinedVector<std::string, 2> v_string2; - v_string2 = {"foo", std::string("bar")}; - EXPECT_THAT(v_string2, ElementsAre("foo", "bar")); -} - -TYPED_TEST_P(InstanceTest, InitializerListAssign) { - using Instance = TypeParam; - for (size_t original_size = 0; original_size <= 4; ++original_size) { - SCOPED_TRACE(original_size); - absl::InlinedVector<Instance, 2> v(original_size, Instance(12345)); - const size_t original_capacity = v.capacity(); - v.assign({Instance(3)}); - EXPECT_THAT(v, AllOf(SizeIs(1), CapacityIs(original_capacity), - ElementsAre(ValueIs(3)))); - } - for (size_t original_size = 0; original_size <= 4; ++original_size) { - SCOPED_TRACE(original_size); - absl::InlinedVector<Instance, 2> v(original_size, Instance(12345)); - v.assign({Instance(3), Instance(4), Instance(5)}); - EXPECT_THAT( - v, AllOf(SizeIs(3), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5)))); - EXPECT_LE(3, v.capacity()); - } -} - -REGISTER_TYPED_TEST_CASE_P(InstanceTest, Swap, CountConstructorsDestructors, - CountConstructorsDestructorsOnCopyConstruction, - CountConstructorsDestructorsOnMoveConstruction, - CountConstructorsDestructorsOnAssignment, - CountConstructorsDestructorsOnMoveAssignment, - CountElemAssignInlineBacking, RangedConstructor, - RangedAssign, InitializerListAssign); - -using InstanceTypes = - ::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>; -INSTANTIATE_TYPED_TEST_CASE_P(InstanceTestOnTypes, InstanceTest, InstanceTypes); - -TEST(DynamicVec, DynamicVecCompiles) { - DynamicVec v; - (void)v; -} - -TEST(AllocatorSupportTest, Constructors) { - using MyAlloc = CountingAllocator<int>; - using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; - int64_t allocated = 0; - MyAlloc alloc(&allocated); - { AllocVec ABSL_ATTRIBUTE_UNUSED v; } - { AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); } - { AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); } - { AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); } - - AllocVec v2; - { AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); } - { AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); } -} - -TEST(AllocatorSupportTest, CountAllocations) { - using MyAlloc = CountingAllocator<int>; - using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; - const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; - int64_t allocated = 0; - MyAlloc alloc(&allocated); - { - AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc); - EXPECT_THAT(allocated, 0); - } - EXPECT_THAT(allocated, 0); - { - AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); - EXPECT_THAT(allocated, v.size() * sizeof(int)); - } - EXPECT_THAT(allocated, 0); - { - AllocVec v(4, 1, alloc); - EXPECT_THAT(allocated, 0); - - int64_t allocated2 = 0; - MyAlloc alloc2(&allocated2); - AllocVec v2(v, alloc2); - EXPECT_THAT(allocated2, 0); - - int64_t allocated3 = 0; - MyAlloc alloc3(&allocated3); - AllocVec v3(std::move(v), alloc3); - EXPECT_THAT(allocated3, 0); - } - EXPECT_THAT(allocated, 0); - { - AllocVec v(8, 2, alloc); - EXPECT_THAT(allocated, v.size() * sizeof(int)); - - int64_t allocated2 = 0; - MyAlloc alloc2(&allocated2); - AllocVec v2(v, alloc2); - EXPECT_THAT(allocated2, v2.size() * sizeof(int)); - - int64_t allocated3 = 0; - MyAlloc alloc3(&allocated3); - AllocVec v3(std::move(v), alloc3); - EXPECT_THAT(allocated3, v3.size() * sizeof(int)); - } - EXPECT_EQ(allocated, 0); - { - // Test shrink_to_fit deallocations. - AllocVec v(8, 2, alloc); - EXPECT_EQ(allocated, 8 * sizeof(int)); - v.resize(5); - EXPECT_EQ(allocated, 8 * sizeof(int)); - v.shrink_to_fit(); - EXPECT_EQ(allocated, 5 * sizeof(int)); - v.resize(4); - EXPECT_EQ(allocated, 5 * sizeof(int)); - v.shrink_to_fit(); - EXPECT_EQ(allocated, 0); - } -} - -TEST(AllocatorSupportTest, SwapBothAllocated) { - using MyAlloc = CountingAllocator<int>; - using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; - int64_t allocated1 = 0; - int64_t allocated2 = 0; - { - const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7}; - const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - MyAlloc a1(&allocated1); - MyAlloc a2(&allocated2); - AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1); - AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2); - EXPECT_LT(v1.capacity(), v2.capacity()); - EXPECT_THAT(allocated1, v1.capacity() * sizeof(int)); - EXPECT_THAT(allocated2, v2.capacity() * sizeof(int)); - v1.swap(v2); - EXPECT_THAT(v1, ElementsAreArray(ia2)); - EXPECT_THAT(v2, ElementsAreArray(ia1)); - EXPECT_THAT(allocated1, v2.capacity() * sizeof(int)); - EXPECT_THAT(allocated2, v1.capacity() * sizeof(int)); - } - EXPECT_THAT(allocated1, 0); - EXPECT_THAT(allocated2, 0); -} - -TEST(AllocatorSupportTest, SwapOneAllocated) { - using MyAlloc = CountingAllocator<int>; - using AllocVec = absl::InlinedVector<int, 4, MyAlloc>; - int64_t allocated1 = 0; - int64_t allocated2 = 0; - { - const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7}; - const int ia2[] = {0, 1, 2, 3}; - MyAlloc a1(&allocated1); - MyAlloc a2(&allocated2); - AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1); - AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2); - EXPECT_THAT(allocated1, v1.capacity() * sizeof(int)); - EXPECT_THAT(allocated2, 0); - v1.swap(v2); - EXPECT_THAT(v1, ElementsAreArray(ia2)); - EXPECT_THAT(v2, ElementsAreArray(ia1)); - EXPECT_THAT(allocated1, v2.capacity() * sizeof(int)); - EXPECT_THAT(allocated2, 0); - EXPECT_TRUE(v2.get_allocator() == a1); - EXPECT_TRUE(v1.get_allocator() == a2); - } - EXPECT_THAT(allocated1, 0); - EXPECT_THAT(allocated2, 0); -} - -TEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) { - using StdVector = std::vector<int, CountingAllocator<int>>; - using Alloc = CountingAllocator<StdVector>; - using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>; - using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>; - - int64_t total_allocated_byte_count = 0; - - AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count))); - - // Called only once to remain inlined - inlined_case.emplace_back(); - - int64_t absl_responsible_for_count = total_allocated_byte_count; - - // MSVC's allocator preemptively allocates in debug mode -#if !defined(_MSC_VER) - EXPECT_EQ(absl_responsible_for_count, 0); -#endif // !defined(_MSC_VER) - - inlined_case[0].emplace_back(); - EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count); - - inlined_case.clear(); - inlined_case.shrink_to_fit(); - EXPECT_EQ(total_allocated_byte_count, 0); -} - -TEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) { - using StdVector = std::vector<int, CountingAllocator<int>>; - using Alloc = CountingAllocator<StdVector>; - using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>; - using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>; - - int64_t total_allocated_byte_count = 0; - - AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count))); - - // Called twice to force into being allocated - allocated_case.emplace_back(); - allocated_case.emplace_back(); - - int64_t absl_responsible_for_count = total_allocated_byte_count; - EXPECT_GT(absl_responsible_for_count, 0); - - allocated_case[1].emplace_back(); - EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count); - - allocated_case.clear(); - allocated_case.shrink_to_fit(); - EXPECT_EQ(total_allocated_byte_count, 0); -} - -TEST(AllocatorSupportTest, SizeAllocConstructor) { - constexpr int inlined_size = 4; - using Alloc = CountingAllocator<int>; - using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>; - - { - auto len = inlined_size / 2; - int64_t allocated = 0; - auto v = AllocVec(len, Alloc(&allocated)); - - // Inline storage used; allocator should not be invoked - EXPECT_THAT(allocated, 0); - EXPECT_THAT(v, AllOf(SizeIs(len), Each(0))); - } - - { - auto len = inlined_size * 2; - int64_t allocated = 0; - auto v = AllocVec(len, Alloc(&allocated)); - - // Out of line storage used; allocation of 8 elements expected - EXPECT_THAT(allocated, len * sizeof(int)); - EXPECT_THAT(v, AllOf(SizeIs(len), Each(0))); - } -} - -TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) { - using T = int; - using A = std::allocator<T>; - using ATraits = absl::allocator_traits<A>; - - struct MinimumAllocator { - using value_type = T; - - value_type* allocate(size_t n) { - A a; - return ATraits::allocate(a, n); - } - - void deallocate(value_type* p, size_t n) { - A a; - ATraits::deallocate(a, p, n); - } - }; - - absl::InlinedVector<T, 1, MinimumAllocator> vec; - vec.emplace_back(); - vec.resize(0); -} - -TEST(InlinedVectorTest, AbslHashValueWorks) { - using V = absl::InlinedVector<int, 4>; - std::vector<V> cases; - - // Generate a variety of vectors some of these are small enough for the inline - // space but are stored out of line. - for (int i = 0; i < 10; ++i) { - V v; - for (int j = 0; j < i; ++j) { - v.push_back(j); - } - cases.push_back(v); - v.resize(i % 4); - cases.push_back(v); - } - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases)); -} - -} // anonymous namespace diff --git a/third_party/abseil_cpp/absl/container/internal/btree.h b/third_party/abseil_cpp/absl/container/internal/btree.h deleted file mode 100644 index f2fc31df8d41..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/btree.h +++ /dev/null @@ -1,2587 +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. - -// A btree implementation of the STL set and map interfaces. A btree is smaller -// and generally also faster than STL set/map (refer to the benchmarks below). -// The red-black tree implementation of STL set/map has an overhead of 3 -// pointers (left, right and parent) plus the node color information for each -// stored value. So a set<int32_t> consumes 40 bytes for each value stored in -// 64-bit mode. This btree implementation stores multiple values on fixed -// size nodes (usually 256 bytes) and doesn't store child pointers for leaf -// nodes. The result is that a btree_set<int32_t> may use much less memory per -// stored value. For the random insertion benchmark in btree_bench.cc, a -// btree_set<int32_t> with node-size of 256 uses 5.1 bytes per stored value. -// -// The packing of multiple values on to each node of a btree has another effect -// besides better space utilization: better cache locality due to fewer cache -// lines being accessed. Better cache locality translates into faster -// operations. -// -// CAVEATS -// -// Insertions and deletions on a btree can cause splitting, merging or -// rebalancing of btree nodes. And even without these operations, insertions -// and deletions on a btree will move values around within a node. In both -// cases, the result is that insertions and deletions can invalidate iterators -// pointing to values other than the one being inserted/deleted. Therefore, this -// container does not provide pointer stability. This is notably different from -// STL set/map which takes care to not invalidate iterators on insert/erase -// except, of course, for iterators pointing to the value being erased. A -// partial workaround when erasing is available: erase() returns an iterator -// pointing to the item just after the one that was erased (or end() if none -// exists). - -#ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_ -#define ABSL_CONTAINER_INTERNAL_BTREE_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <functional> -#include <iterator> -#include <limits> -#include <new> -#include <string> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/container/internal/common.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/layout.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/cord.h" -#include "absl/strings/string_view.h" -#include "absl/types/compare.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// A helper class that indicates if the Compare parameter is a key-compare-to -// comparator. -template <typename Compare, typename T> -using btree_is_key_compare_to = - std::is_convertible<absl::result_of_t<Compare(const T &, const T &)>, - absl::weak_ordering>; - -struct StringBtreeDefaultLess { - using is_transparent = void; - - StringBtreeDefaultLess() = default; - - // Compatibility constructor. - StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT - StringBtreeDefaultLess(std::less<string_view>) {} // NOLINT - - absl::weak_ordering operator()(absl::string_view lhs, - absl::string_view rhs) const { - return compare_internal::compare_result_as_ordering(lhs.compare(rhs)); - } - StringBtreeDefaultLess(std::less<absl::Cord>) {} // NOLINT - absl::weak_ordering operator()(const absl::Cord &lhs, - const absl::Cord &rhs) const { - return compare_internal::compare_result_as_ordering(lhs.Compare(rhs)); - } - absl::weak_ordering operator()(const absl::Cord &lhs, - absl::string_view rhs) const { - return compare_internal::compare_result_as_ordering(lhs.Compare(rhs)); - } - absl::weak_ordering operator()(absl::string_view lhs, - const absl::Cord &rhs) const { - return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs)); - } -}; - -struct StringBtreeDefaultGreater { - using is_transparent = void; - - StringBtreeDefaultGreater() = default; - - StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT - StringBtreeDefaultGreater(std::greater<string_view>) {} // NOLINT - - absl::weak_ordering operator()(absl::string_view lhs, - absl::string_view rhs) const { - return compare_internal::compare_result_as_ordering(rhs.compare(lhs)); - } - StringBtreeDefaultGreater(std::greater<absl::Cord>) {} // NOLINT - absl::weak_ordering operator()(const absl::Cord &lhs, - const absl::Cord &rhs) const { - return compare_internal::compare_result_as_ordering(rhs.Compare(lhs)); - } - absl::weak_ordering operator()(const absl::Cord &lhs, - absl::string_view rhs) const { - return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs)); - } - absl::weak_ordering operator()(absl::string_view lhs, - const absl::Cord &rhs) const { - return compare_internal::compare_result_as_ordering(rhs.Compare(lhs)); - } -}; - -// A helper class to convert a boolean comparison into a three-way "compare-to" -// comparison that returns an `absl::weak_ordering`. This helper -// class is specialized for less<std::string>, greater<std::string>, -// less<string_view>, greater<string_view>, less<absl::Cord>, and -// greater<absl::Cord>. -// -// key_compare_to_adapter is provided so that btree users -// automatically get the more efficient compare-to code when using common -// Abseil string types with common comparison functors. -// These string-like specializations also turn on heterogeneous lookup by -// default. -template <typename Compare> -struct key_compare_to_adapter { - using type = Compare; -}; - -template <> -struct key_compare_to_adapter<std::less<std::string>> { - using type = StringBtreeDefaultLess; -}; - -template <> -struct key_compare_to_adapter<std::greater<std::string>> { - using type = StringBtreeDefaultGreater; -}; - -template <> -struct key_compare_to_adapter<std::less<absl::string_view>> { - using type = StringBtreeDefaultLess; -}; - -template <> -struct key_compare_to_adapter<std::greater<absl::string_view>> { - using type = StringBtreeDefaultGreater; -}; - -template <> -struct key_compare_to_adapter<std::less<absl::Cord>> { - using type = StringBtreeDefaultLess; -}; - -template <> -struct key_compare_to_adapter<std::greater<absl::Cord>> { - using type = StringBtreeDefaultGreater; -}; - -// Detects an 'absl_btree_prefer_linear_node_search' member. This is -// a protocol used as an opt-in or opt-out of linear search. -// -// For example, this would be useful for key types that wrap an integer -// and define their own cheap operator<(). For example: -// -// class K { -// public: -// using absl_btree_prefer_linear_node_search = std::true_type; -// ... -// private: -// friend bool operator<(K a, K b) { return a.k_ < b.k_; } -// int k_; -// }; -// -// btree_map<K, V> m; // Uses linear search -// -// If T has the preference tag, then it has a preference. -// Btree will use the tag's truth value. -template <typename T, typename = void> -struct has_linear_node_search_preference : std::false_type {}; -template <typename T, typename = void> -struct prefers_linear_node_search : std::false_type {}; -template <typename T> -struct has_linear_node_search_preference< - T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>> - : std::true_type {}; -template <typename T> -struct prefers_linear_node_search< - T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>> - : T::absl_btree_prefer_linear_node_search {}; - -template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, - bool Multi, typename SlotPolicy> -struct common_params { - // If Compare is a common comparator for a string-like type, then we adapt it - // to use heterogeneous lookup and to be a key-compare-to comparator. - using key_compare = typename key_compare_to_adapter<Compare>::type; - // True when key_compare has been adapted to StringBtreeDefault{Less,Greater}. - using is_key_compare_adapted = - absl::negation<std::is_same<key_compare, Compare>>; - // A type which indicates if we have a key-compare-to functor or a plain old - // key-compare functor. - using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>; - - using allocator_type = Alloc; - using key_type = Key; - using size_type = std::make_signed<size_t>::type; - using difference_type = ptrdiff_t; - - // 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; - using init_type = typename slot_policy::mutable_value_type; - using pointer = value_type *; - using const_pointer = const value_type *; - using reference = value_type &; - using const_reference = const value_type &; - - enum { - kTargetNodeSize = TargetNodeSize, - - // Upper bound for the available space for values. This is largest for leaf - // nodes, which have overhead of at least a pointer + 4 bytes (for storing - // 3 field_types and an enum). - kNodeValueSpace = - TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4), - }; - - // This is an integral type large enough to hold as many - // ValueSize-values as will fit a node of TargetNodeSize bytes. - using node_count_type = - absl::conditional_t<(kNodeValueSpace / sizeof(value_type) > - (std::numeric_limits<uint8_t>::max)()), - uint16_t, uint8_t>; // NOLINT - - // The following methods are necessary for passing this struct as PolicyTraits - // for node_handle and/or are used within btree. - static value_type &element(slot_type *slot) { - return slot_policy::element(slot); - } - static const value_type &element(const slot_type *slot) { - return slot_policy::element(slot); - } - template <class... Args> - static void construct(Alloc *alloc, slot_type *slot, Args &&... args) { - slot_policy::construct(alloc, slot, std::forward<Args>(args)...); - } - static void construct(Alloc *alloc, slot_type *slot, slot_type *other) { - slot_policy::construct(alloc, slot, other); - } - static void destroy(Alloc *alloc, slot_type *slot) { - slot_policy::destroy(alloc, slot); - } - static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) { - construct(alloc, new_slot, old_slot); - destroy(alloc, old_slot); - } - static void swap(Alloc *alloc, slot_type *a, slot_type *b) { - slot_policy::swap(alloc, a, b); - } - static void move(Alloc *alloc, slot_type *src, slot_type *dest) { - slot_policy::move(alloc, src, dest); - } -}; - -// A parameters structure for holding the type parameters for a btree_map. -// Compare and Alloc should be nothrow copy-constructible. -template <typename Key, typename Data, typename Compare, typename Alloc, - int TargetNodeSize, bool Multi> -struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi, - map_slot_policy<Key, Data>> { - using super_type = typename map_params::common_params; - using mapped_type = Data; - // This type allows us to move keys when it is safe to do so. It is safe - // for maps in which value_type and mutable_value_type are layout compatible. - using slot_policy = typename super_type::slot_policy; - using slot_type = typename super_type::slot_type; - using value_type = typename super_type::value_type; - using init_type = typename super_type::init_type; - - using key_compare = typename super_type::key_compare; - // Inherit from key_compare for empty base class optimization. - struct value_compare : private key_compare { - value_compare() = default; - explicit value_compare(const key_compare &cmp) : key_compare(cmp) {} - - template <typename T, typename U> - auto operator()(const T &left, const U &right) const - -> decltype(std::declval<key_compare>()(left.first, right.first)) { - return key_compare::operator()(left.first, right.first); - } - }; - using is_map_container = std::true_type; - - template <typename V> - static auto key(const V &value) -> decltype(value.first) { - return value.first; - } - static const Key &key(const slot_type *s) { return slot_policy::key(s); } - static const Key &key(slot_type *s) { return slot_policy::key(s); } - // For use in node handle. - static auto mutable_key(slot_type *s) - -> decltype(slot_policy::mutable_key(s)) { - return slot_policy::mutable_key(s); - } - static mapped_type &value(value_type *value) { return value->second; } -}; - -// This type implements the necessary functions from the -// absl::container_internal::slot_type interface. -template <typename Key> -struct set_slot_policy { - using slot_type = Key; - using value_type = Key; - using mutable_value_type = Key; - - static value_type &element(slot_type *slot) { return *slot; } - static const value_type &element(const slot_type *slot) { return *slot; } - - template <typename Alloc, class... Args> - static void construct(Alloc *alloc, slot_type *slot, Args &&... args) { - absl::allocator_traits<Alloc>::construct(*alloc, slot, - std::forward<Args>(args)...); - } - - template <typename Alloc> - static void construct(Alloc *alloc, slot_type *slot, slot_type *other) { - absl::allocator_traits<Alloc>::construct(*alloc, slot, std::move(*other)); - } - - template <typename Alloc> - static void destroy(Alloc *alloc, slot_type *slot) { - absl::allocator_traits<Alloc>::destroy(*alloc, slot); - } - - template <typename Alloc> - static void swap(Alloc * /*alloc*/, slot_type *a, slot_type *b) { - using std::swap; - swap(*a, *b); - } - - template <typename Alloc> - static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) { - *dest = std::move(*src); - } -}; - -// A parameters structure for holding the type parameters for a btree_set. -// Compare and Alloc should be nothrow copy-constructible. -template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, - bool Multi> -struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi, - set_slot_policy<Key>> { - using value_type = Key; - using slot_type = typename set_params::common_params::slot_type; - using value_compare = typename set_params::common_params::key_compare; - using is_map_container = std::false_type; - - template <typename V> - static const V &key(const V &value) { return value; } - static const Key &key(const slot_type *slot) { return *slot; } - static const Key &key(slot_type *slot) { return *slot; } -}; - -// An adapter class that converts a lower-bound compare into an upper-bound -// compare. Note: there is no need to make a version of this adapter specialized -// for key-compare-to functors because the upper-bound (the first value greater -// than the input) is never an exact match. -template <typename Compare> -struct upper_bound_adapter { - explicit upper_bound_adapter(const Compare &c) : comp(c) {} - template <typename K1, typename K2> - bool operator()(const K1 &a, const K2 &b) const { - // Returns true when a is not greater than b. - return !compare_internal::compare_result_as_less_than(comp(b, a)); - } - - private: - Compare comp; -}; - -enum class MatchKind : uint8_t { kEq, kNe }; - -template <typename V, bool IsCompareTo> -struct SearchResult { - V value; - MatchKind match; - - static constexpr bool HasMatch() { return true; } - bool IsEq() const { return match == MatchKind::kEq; } -}; - -// When we don't use CompareTo, `match` is not present. -// This ensures that callers can't use it accidentally when it provides no -// useful information. -template <typename V> -struct SearchResult<V, false> { - SearchResult() {} - explicit SearchResult(V value) : value(value) {} - SearchResult(V value, MatchKind /*match*/) : value(value) {} - - V value; - - static constexpr bool HasMatch() { return false; } - static constexpr bool IsEq() { return false; } -}; - -// A node in the btree holding. The same node type is used for both internal -// and leaf nodes in the btree, though the nodes are allocated in such a way -// that the children array is only valid in internal nodes. -template <typename Params> -class btree_node { - using is_key_compare_to = typename Params::is_key_compare_to; - using 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; - - public: - using params_type = Params; - using key_type = typename Params::key_type; - using value_type = typename Params::value_type; - using pointer = typename Params::pointer; - using const_pointer = typename Params::const_pointer; - using reference = typename Params::reference; - using const_reference = typename Params::const_reference; - using key_compare = typename Params::key_compare; - using size_type = typename Params::size_type; - using difference_type = typename Params::difference_type; - - // Btree decides whether to use linear node search as follows: - // - If the comparator expresses a preference, use that. - // - If the key expresses a preference, use that. - // - If the key is arithmetic and the comparator is std::less or - // std::greater, choose linear. - // - Otherwise, choose binary. - // TODO(ezb): Might make sense to add condition(s) based on node-size. - using use_linear_search = std::integral_constant< - bool, - has_linear_node_search_preference<key_compare>::value - ? prefers_linear_node_search<key_compare>::value - : has_linear_node_search_preference<key_type>::value - ? prefers_linear_node_search<key_type>::value - : std::is_arithmetic<key_type>::value && - (std::is_same<std::less<key_type>, key_compare>::value || - std::is_same<std::greater<key_type>, - key_compare>::value)>; - - // This class is organized by gtl::Layout as if it had the following - // structure: - // // A pointer to the node's parent. - // btree_node *parent; - // - // // The position of the node in the node's parent. - // field_type position; - // // The index of the first populated value in `values`. - // // TODO(ezb): right now, `start` is always 0. Update insertion/merge - // // logic to allow for floating storage within nodes. - // field_type start; - // // The index after the last populated value in `values`. Currently, this - // // is the same as the count of values. - // field_type finish; - // // The maximum number of values the node can hold. This is an integer in - // // [1, 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 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 - // // 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 kNodeValues + 1 children for - // // internal nodes. - // 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 - // the btree implementation. - ~btree_node() = default; - btree_node(btree_node const &) = delete; - btree_node &operator=(btree_node const &) = delete; - - // Public for EmptyNodeType. - constexpr static size_type Alignment() { - static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(), - "Alignment of all nodes must be equal."); - return InternalLayout().Alignment(); - } - - protected: - btree_node() = default; - - private: - using layout_type = absl::container_internal::Layout<btree_node *, field_type, - slot_type, btree_node *>; - constexpr static size_type SizeWithNValues(size_type n) { - return layout_type(/*parent*/ 1, - /*position, start, finish, max_count*/ 4, - /*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 SizeWithNValues(1) - sizeof(value_type); - } - - // Compute how many values we can fit onto a leaf node taking into account - // padding. - constexpr static size_type NodeTargetValues(const int begin, const int end) { - return begin == end ? begin - : SizeWithNValues((begin + end) / 2 + 1) > - params_type::kTargetNodeSize - ? NodeTargetValues(begin, (begin + end) / 2) - : NodeTargetValues((begin + end) / 2 + 1, end); - } - - enum { - kTargetNodeSize = params_type::kTargetNodeSize, - kNodeTargetValues = NodeTargetValues(0, params_type::kTargetNodeSize), - - // 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). - 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 kNodeValues values. - constexpr static layout_type LeafLayout(const int max_values = kNodeValues) { - return layout_type(/*parent*/ 1, - /*position, start, finish, max_count*/ 4, - /*values*/ max_values, - /*children*/ 0); - } - constexpr static layout_type InternalLayout() { - return layout_type(/*parent*/ 1, - /*position, start, finish, max_count*/ 4, - /*values*/ kNodeValues, - /*children*/ kNodeValues + 1); - } - constexpr static size_type LeafSize(const int max_values = kNodeValues) { - return LeafLayout(max_values).AllocSize(); - } - constexpr static size_type InternalSize() { - return InternalLayout().AllocSize(); - } - - // N is the index of the type in the Layout definition. - // ElementType<N> is the Nth type in the Layout definition. - template <size_type N> - inline typename layout_type::template ElementType<N> *GetField() { - // We assert that we don't read from values that aren't there. - assert(N < 3 || !leaf()); - return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this)); - } - template <size_type N> - inline const typename layout_type::template ElementType<N> *GetField() const { - assert(N < 3 || !leaf()); - return InternalLayout().template Pointer<N>( - reinterpret_cast<const char *>(this)); - } - void set_parent(btree_node *p) { *GetField<0>() = p; } - field_type &mutable_finish() { return GetField<1>()[2]; } - slot_type *slot(int i) { return &GetField<2>()[i]; } - slot_type *start_slot() { return slot(start()); } - slot_type *finish_slot() { return slot(finish()); } - const slot_type *slot(int i) const { return &GetField<2>()[i]; } - void set_position(field_type v) { GetField<1>()[0] = v; } - void set_start(field_type v) { GetField<1>()[1] = v; } - void set_finish(field_type v) { GetField<1>()[2] = v; } - // This method is only called by the node init methods. - void set_max_count(field_type v) { GetField<1>()[3] = v; } - - public: - // Whether this is a leaf node or not. This value doesn't change after the - // node is created. - bool leaf() const { return GetField<1>()[3] != kInternalNodeMaxCount; } - - // Getter for the position of this node in its parent. - field_type position() const { return GetField<1>()[0]; } - - // Getter for the offset of the first value in the `values` array. - field_type start() const { - // TODO(ezb): when floating storage is implemented, return GetField<1>()[1]; - assert(GetField<1>()[1] == 0); - return 0; - } - - // Getter for the offset after the last value in the `values` array. - field_type finish() const { return GetField<1>()[2]; } - - // Getters for the number of values stored in this node. - field_type count() const { - assert(finish() >= start()); - return finish() - start(); - } - field_type max_count() const { - // Internal nodes have max_count==kInternalNodeMaxCount. - // Leaf nodes have max_count in [1, kNodeValues]. - const field_type max_count = GetField<1>()[3]; - return max_count == field_type{kInternalNodeMaxCount} - ? field_type{kNodeValues} - : max_count; - } - - // Getter for the parent of this node. - btree_node *parent() const { return *GetField<0>(); } - // Getter for whether the node is the root of the tree. The parent of the - // root of the tree is the leftmost node in the tree which is guaranteed to - // be a leaf. - bool is_root() const { return parent()->leaf(); } - void make_root() { - assert(parent()->is_root()); - set_parent(parent()->parent()); - } - - // Getters for the key/value at position i in the node. - const key_type &key(int i) const { return params_type::key(slot(i)); } - reference value(int i) { return params_type::element(slot(i)); } - const_reference value(int i) const { return params_type::element(slot(i)); } - - // Getters/setter for the child at position i in the node. - btree_node *child(int i) const { return GetField<3>()[i]; } - btree_node *start_child() const { return child(start()); } - btree_node *&mutable_child(int i) { return GetField<3>()[i]; } - void clear_child(int i) { - absl::container_internal::SanitizerPoisonObject(&mutable_child(i)); - } - void set_child(int i, btree_node *c) { - absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i)); - mutable_child(i) = c; - c->set_position(i); - } - void init_child(int i, btree_node *c) { - set_child(i, c); - c->set_parent(this); - } - - // Returns the position of the first value whose key is not less than k. - template <typename K> - SearchResult<int, is_key_compare_to::value> lower_bound( - const K &k, const key_compare &comp) const { - return use_linear_search::value ? linear_search(k, comp) - : binary_search(k, comp); - } - // Returns the position of the first value whose key is greater than k. - template <typename K> - int upper_bound(const K &k, const key_compare &comp) const { - auto upper_compare = upper_bound_adapter<key_compare>(comp); - return use_linear_search::value ? linear_search(k, upper_compare).value - : binary_search(k, upper_compare).value; - } - - template <typename K, typename Compare> - SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value> - linear_search(const K &k, const Compare &comp) const { - return linear_search_impl(k, start(), finish(), comp, - btree_is_key_compare_to<Compare, key_type>()); - } - - template <typename K, typename Compare> - SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value> - binary_search(const K &k, const Compare &comp) const { - return binary_search_impl(k, start(), finish(), comp, - btree_is_key_compare_to<Compare, key_type>()); - } - - // Returns the position of the first value whose key is not less than k using - // linear search performed using plain compare. - template <typename K, typename Compare> - SearchResult<int, false> linear_search_impl( - const K &k, int s, const int e, const Compare &comp, - std::false_type /* IsCompareTo */) const { - while (s < e) { - if (!comp(key(s), k)) { - break; - } - ++s; - } - return SearchResult<int, false>{s}; - } - - // Returns the position of the first value whose key is not less than k using - // linear search performed using compare-to. - template <typename K, typename Compare> - SearchResult<int, true> linear_search_impl( - const K &k, int s, const int e, const Compare &comp, - std::true_type /* IsCompareTo */) const { - while (s < e) { - const absl::weak_ordering c = comp(key(s), k); - if (c == 0) { - return {s, MatchKind::kEq}; - } else if (c > 0) { - break; - } - ++s; - } - return {s, MatchKind::kNe}; - } - - // Returns the position of the first value whose key is not less than k using - // binary search performed using plain compare. - template <typename K, typename Compare> - SearchResult<int, false> binary_search_impl( - const K &k, int s, int e, const Compare &comp, - std::false_type /* IsCompareTo */) const { - while (s != e) { - const int mid = (s + e) >> 1; - if (comp(key(mid), k)) { - s = mid + 1; - } else { - e = mid; - } - } - return SearchResult<int, false>{s}; - } - - // Returns the position of the first value whose key is not less than k using - // binary search performed using compare-to. - template <typename K, typename CompareTo> - SearchResult<int, true> binary_search_impl( - const K &k, int s, int e, const CompareTo &comp, - std::true_type /* IsCompareTo */) const { - if (is_multi_container::value) { - MatchKind exact_match = MatchKind::kNe; - while (s != e) { - const int mid = (s + e) >> 1; - const absl::weak_ordering c = comp(key(mid), k); - if (c < 0) { - s = mid + 1; - } else { - e = mid; - if (c == 0) { - // Need to return the first value whose key is not less than k, - // which requires continuing the binary search if this is a - // multi-container. - exact_match = MatchKind::kEq; - } - } - } - return {s, exact_match}; - } else { // Not a multi-container. - while (s != e) { - const int mid = (s + e) >> 1; - const absl::weak_ordering c = comp(key(mid), k); - if (c < 0) { - s = mid + 1; - } else if (c > 0) { - e = mid; - } else { - return {mid, MatchKind::kEq}; - } - } - return {s, MatchKind::kNe}; - } - } - - // Emplaces a value at position i, shifting all existing values and - // children at positions >= i to the right by 1. - template <typename... Args> - void emplace_value(size_type i, allocator_type *alloc, Args &&... args); - - // Removes the values at positions [i, i + to_erase), shifting all existing - // values and children after that range to the left by to_erase. Clears all - // children between [i, i + to_erase). - void remove_values(field_type i, field_type to_erase, allocator_type *alloc); - - // Rebalances a node with its right sibling. - void rebalance_right_to_left(int to_move, btree_node *right, - allocator_type *alloc); - void rebalance_left_to_right(int to_move, btree_node *right, - allocator_type *alloc); - - // Splits a node, moving a portion of the node's values to its right sibling. - void split(int insert_position, btree_node *dest, allocator_type *alloc); - - // Merges a node with its right sibling, moving all of the values and the - // delimiting key in the parent node onto itself, and deleting the src node. - void merge(btree_node *src, allocator_type *alloc); - - // Node allocation/deletion routines. - void init_leaf(btree_node *parent, int max_count) { - set_parent(parent); - set_position(0); - set_start(0); - set_finish(0); - set_max_count(max_count); - absl::container_internal::SanitizerPoisonMemoryRegion( - start_slot(), max_count * sizeof(slot_type)); - } - void init_internal(btree_node *parent) { - init_leaf(parent, kNodeValues); - // Set `max_count` to a sentinel value to indicate that this node is - // internal. - set_max_count(kInternalNodeMaxCount); - absl::container_internal::SanitizerPoisonMemoryRegion( - &mutable_child(start()), (kNodeValues + 1) * sizeof(btree_node *)); - } - - static void deallocate(const size_type size, btree_node *node, - allocator_type *alloc) { - absl::container_internal::Deallocate<Alignment()>(alloc, node, size); - } - - // Deletes a node and all of its children. - static void clear_and_delete(btree_node *node, allocator_type *alloc); - - private: - template <typename... Args> - void value_init(const field_type i, allocator_type *alloc, Args &&... args) { - absl::container_internal::SanitizerUnpoisonObject(slot(i)); - params_type::construct(alloc, slot(i), std::forward<Args>(args)...); - } - void value_destroy(const field_type i, allocator_type *alloc) { - params_type::destroy(alloc, slot(i)); - absl::container_internal::SanitizerPoisonObject(slot(i)); - } - void value_destroy_n(const field_type i, const field_type n, - allocator_type *alloc) { - for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) { - params_type::destroy(alloc, s); - absl::container_internal::SanitizerPoisonObject(s); - } - } - - static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) { - absl::container_internal::SanitizerUnpoisonObject(dest); - params_type::transfer(alloc, dest, src); - absl::container_internal::SanitizerPoisonObject(src); - } - - // Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`. - void transfer(const size_type dest_i, const size_type src_i, - btree_node *src_node, allocator_type *alloc) { - transfer(slot(dest_i), src_node->slot(src_i), alloc); - } - - // Transfers `n` values starting at value `src_i` in `src_node` into the - // values starting at value `dest_i` in `this`. - void transfer_n(const size_type n, const size_type dest_i, - const size_type src_i, btree_node *src_node, - allocator_type *alloc) { - for (slot_type *src = src_node->slot(src_i), *end = src + n, - *dest = slot(dest_i); - src != end; ++src, ++dest) { - transfer(dest, src, alloc); - } - } - - // Same as above, except that we start at the end and work our way to the - // beginning. - void transfer_n_backward(const size_type n, const size_type dest_i, - const size_type src_i, btree_node *src_node, - allocator_type *alloc) { - for (slot_type *src = src_node->slot(src_i + n - 1), *end = src - n, - *dest = slot(dest_i + n - 1); - src != end; --src, --dest) { - transfer(dest, src, alloc); - } - } - - template <typename P> - friend class btree; - template <typename N, typename R, typename P> - friend struct btree_iterator; - friend class BtreeNodePeer; -}; - -template <typename Node, typename Reference, typename Pointer> -struct btree_iterator { - private: - using key_type = typename Node::key_type; - using size_type = typename Node::size_type; - using params_type = typename Node::params_type; - - using node_type = Node; - using normal_node = typename std::remove_const<Node>::type; - using const_node = const Node; - using normal_pointer = typename params_type::pointer; - using normal_reference = typename params_type::reference; - using const_pointer = typename params_type::const_pointer; - using const_reference = typename params_type::const_reference; - using slot_type = typename params_type::slot_type; - - using iterator = - btree_iterator<normal_node, normal_reference, normal_pointer>; - using const_iterator = - btree_iterator<const_node, const_reference, const_pointer>; - - public: - // These aliases are public for std::iterator_traits. - using difference_type = typename Node::difference_type; - using value_type = typename params_type::value_type; - using pointer = Pointer; - using reference = Reference; - using iterator_category = std::bidirectional_iterator_tag; - - btree_iterator() : node(nullptr), position(-1) {} - explicit btree_iterator(Node *n) : node(n), position(n->start()) {} - btree_iterator(Node *n, int p) : node(n), position(p) {} - - // NOTE: this SFINAE allows for implicit conversions from iterator to - // const_iterator, but it specifically avoids 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) {} - - private: - // This SFINAE allows explicit conversions from const_iterator to - // 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, - absl::enable_if_t< - std::is_same<btree_iterator<N, R, P>, const_iterator>::value && - std::is_same<btree_iterator, iterator>::value, - int> = 0> - explicit btree_iterator(const btree_iterator<N, R, P> &other) - : node(const_cast<node_type *>(other.node)), position(other.position) {} - - // Increment/decrement the iterator. - void increment() { - if (node->leaf() && ++position < node->finish()) { - return; - } - increment_slow(); - } - void increment_slow(); - - void decrement() { - if (node->leaf() && --position >= node->start()) { - return; - } - decrement_slow(); - } - void decrement_slow(); - - public: - bool operator==(const iterator &other) const { - return node == other.node && position == other.position; - } - bool operator==(const const_iterator &other) const { - return node == other.node && position == other.position; - } - bool operator!=(const iterator &other) const { - return node != other.node || position != other.position; - } - bool operator!=(const const_iterator &other) const { - return node != other.node || position != other.position; - } - - // Accessors for the key/value the iterator is pointing at. - reference operator*() const { - ABSL_HARDENING_ASSERT(node != nullptr); - ABSL_HARDENING_ASSERT(node->start() <= position); - ABSL_HARDENING_ASSERT(node->finish() > position); - return node->value(position); - } - pointer operator->() const { return &operator*(); } - - btree_iterator &operator++() { - increment(); - return *this; - } - btree_iterator &operator--() { - decrement(); - return *this; - } - btree_iterator operator++(int) { - btree_iterator tmp = *this; - ++*this; - return tmp; - } - btree_iterator operator--(int) { - btree_iterator tmp = *this; - --*this; - return tmp; - } - - private: - template <typename Params> - friend class btree; - template <typename Tree> - friend class btree_container; - template <typename Tree> - friend class btree_set_container; - template <typename Tree> - friend class btree_map_container; - template <typename Tree> - friend class btree_multiset_container; - template <typename N, typename R, typename P> - friend struct btree_iterator; - template <typename TreeType, typename CheckerType> - friend class base_checker; - - const key_type &key() const { return node->key(position); } - slot_type *slot() { return node->slot(position); } - - // The node in the tree the iterator is pointing at. - Node *node; - // The position within the node of the tree the iterator is pointing at. - // NOTE: this is an int rather than a field_type because iterators can point - // to invalid positions (such as -1) in certain circumstances. - int position; -}; - -template <typename Params> -class btree { - using node_type = btree_node<Params>; - using is_key_compare_to = typename Params::is_key_compare_to; - using init_type = typename Params::init_type; - using field_type = typename node_type::field_type; - using is_multi_container = typename Params::is_multi_container; - using is_key_compare_adapted = typename Params::is_key_compare_adapted; - - // We use a static empty node for the root/leftmost/rightmost of empty btrees - // in order to avoid branching in begin()/end(). - struct alignas(node_type::Alignment()) EmptyNodeType : node_type { - using field_type = typename node_type::field_type; - node_type *parent; - field_type position = 0; - field_type start = 0; - field_type finish = 0; - // max_count must be != kInternalNodeMaxCount (so that this node is regarded - // as a leaf node). max_count() is never called when the tree is empty. - field_type max_count = node_type::kInternalNodeMaxCount + 1; - -#ifdef _MSC_VER - // MSVC has constexpr code generations bugs here. - EmptyNodeType() : parent(this) {} -#else - constexpr EmptyNodeType(node_type *p) : parent(p) {} -#endif - }; - - static node_type *EmptyNode() { -#ifdef _MSC_VER - static EmptyNodeType *empty_node = new EmptyNodeType; - // This assert fails on some other construction methods. - assert(empty_node->parent == empty_node); - return empty_node; -#else - static constexpr EmptyNodeType empty_node( - const_cast<EmptyNodeType *>(&empty_node)); - return const_cast<EmptyNodeType *>(&empty_node); -#endif - } - - enum : uint32_t { - kNodeValues = node_type::kNodeValues, - kMinNodeValues = kNodeValues / 2, - }; - - struct node_stats { - using size_type = typename Params::size_type; - - node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {} - - node_stats &operator+=(const node_stats &other) { - leaf_nodes += other.leaf_nodes; - internal_nodes += other.internal_nodes; - return *this; - } - - size_type leaf_nodes; - size_type internal_nodes; - }; - - public: - using key_type = typename Params::key_type; - using value_type = typename Params::value_type; - using size_type = typename Params::size_type; - using difference_type = typename Params::difference_type; - using key_compare = typename Params::key_compare; - using value_compare = typename Params::value_compare; - using allocator_type = typename Params::allocator_type; - using reference = typename Params::reference; - using const_reference = typename Params::const_reference; - using pointer = typename Params::pointer; - using const_pointer = typename Params::const_pointer; - using iterator = 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>; - using node_handle_type = node_handle<Params, Params, allocator_type>; - - // Internal types made public for use by btree_container types. - using params_type = Params; - using slot_type = typename Params::slot_type; - - private: - // For use in copy_or_move_values_in_order. - const value_type &maybe_move_from_iterator(const_iterator it) { return *it; } - value_type &&maybe_move_from_iterator(iterator it) { return std::move(*it); } - - // Copies or moves (depending on the template parameter) the values in - // other into this btree in their order in other. This btree must be empty - // before this method is called. This method is used in copy construction, - // copy assignment, and move assignment. - template <typename Btree> - void copy_or_move_values_in_order(Btree &other); - - // Validates that various assumptions/requirements are true at compile time. - constexpr static bool static_assert_validation(); - - public: - btree(const key_compare &comp, const allocator_type &alloc) - : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {} - - btree(const btree &other) : btree(other, other.allocator()) {} - btree(const btree &other, const allocator_type &alloc) - : btree(other.key_comp(), alloc) { - copy_or_move_values_in_order(other); - } - btree(btree &&other) noexcept - : root_(std::move(other.root_)), - rightmost_(absl::exchange(other.rightmost_, EmptyNode())), - size_(absl::exchange(other.size_, 0)) { - other.mutable_root() = EmptyNode(); - } - btree(btree &&other, const allocator_type &alloc) - : btree(other.key_comp(), alloc) { - if (alloc == other.allocator()) { - swap(other); - } else { - // Move values from `other` one at a time when allocators are different. - copy_or_move_values_in_order(other); - } - } - - ~btree() { - // Put static_asserts in destructor to avoid triggering them before the type - // is complete. - static_assert(static_assert_validation(), "This call must be elided."); - clear(); - } - - // Assign the contents of other to *this. - btree &operator=(const btree &other); - btree &operator=(btree &&other) noexcept; - - iterator begin() { return iterator(leftmost()); } - const_iterator begin() const { return const_iterator(leftmost()); } - iterator end() { return iterator(rightmost_, rightmost_->finish()); } - const_iterator end() const { - return const_iterator(rightmost_, rightmost_->finish()); - } - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - // Finds the first element whose key is not less than key. - template <typename K> - iterator lower_bound(const K &key) { - return internal_end(internal_lower_bound(key).value); - } - template <typename K> - const_iterator lower_bound(const K &key) const { - return internal_end(internal_lower_bound(key).value); - } - - // Finds the first element whose key is greater than key. - template <typename K> - iterator upper_bound(const K &key) { - return internal_end(internal_upper_bound(key)); - } - template <typename K> - const_iterator upper_bound(const K &key) const { - return internal_end(internal_upper_bound(key)); - } - - // Finds the range of values which compare equal to key. The first member of - // the returned pair is equal to lower_bound(key). The second member of the - // pair is equal to upper_bound(key). - template <typename K> - std::pair<iterator, iterator> equal_range(const K &key); - template <typename K> - std::pair<const_iterator, const_iterator> equal_range(const K &key) const { - return const_cast<btree *>(this)->equal_range(key); - } - - // Inserts a value into the btree only if it does not already exist. The - // boolean return value indicates whether insertion succeeded or failed. - // Requirement: if `key` already exists in the btree, does not consume `args`. - // Requirement: `key` is never referenced after consuming `args`. - template <typename K, typename... Args> - std::pair<iterator, bool> insert_unique(const K &key, Args &&... args); - - // Inserts with hint. Checks to see if the value should be placed immediately - // before `position` in the tree. If so, then the insertion will take - // amortized constant time. If not, the insertion will take amortized - // logarithmic time as if a call to insert_unique() were made. - // Requirement: if `key` already exists in the btree, does not consume `args`. - // Requirement: `key` is never referenced after consuming `args`. - template <typename K, typename... Args> - std::pair<iterator, bool> insert_hint_unique(iterator position, - const K &key, - Args &&... args); - - // Insert a range of values into the btree. - // Note: the first overload avoids constructing a value_type if the key - // already exists in the btree. - template <typename InputIterator, - typename = decltype(std::declval<const key_compare &>()( - params_type::key(*std::declval<InputIterator>()), - std::declval<const key_type &>()))> - void insert_iterator_unique(InputIterator b, InputIterator e, int); - // We need the second overload for cases in which we need to construct a - // value_type in order to compare it with the keys already in the btree. - template <typename InputIterator> - void insert_iterator_unique(InputIterator b, InputIterator e, char); - - // Inserts a value into the btree. - template <typename ValueType> - iterator insert_multi(const key_type &key, ValueType &&v); - - // Inserts a value into the btree. - template <typename ValueType> - iterator insert_multi(ValueType &&v) { - return insert_multi(params_type::key(v), std::forward<ValueType>(v)); - } - - // Insert with hint. Check to see if the value should be placed immediately - // before position in the tree. If it does, then the insertion will take - // amortized constant time. If not, the insertion will take amortized - // logarithmic time as if a call to insert_multi(v) were made. - template <typename ValueType> - iterator insert_hint_multi(iterator position, ValueType &&v); - - // Insert a range of values into the btree. - template <typename InputIterator> - void insert_iterator_multi(InputIterator b, InputIterator e); - - // Erase the specified iterator from the btree. The iterator must be valid - // (i.e. not equal to end()). Return an iterator pointing to the node after - // the one that was erased (or end() if none exists). - // Requirement: does not read the value at `*iter`. - iterator erase(iterator iter); - - // Erases range. Returns the number of keys erased and an iterator pointing - // to the element after the last erased element. - std::pair<size_type, iterator> erase_range(iterator begin, iterator end); - - // Finds 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)); - } - template <typename K> - const_iterator find(const K &key) const { - return internal_end(internal_find(key)); - } - - // Clear the btree, deleting all of the values it contains. - void clear(); - - // Swaps the contents of `this` and `other`. - void swap(btree &other); - - const key_compare &key_comp() const noexcept { - return root_.template get<0>(); - } - template <typename K1, typename K2> - bool compare_keys(const K1 &a, const K2 &b) const { - return compare_internal::compare_result_as_less_than(key_comp()(a, b)); - } - - value_compare value_comp() const { return value_compare(key_comp()); } - - // Verifies the structure of the btree. - void verify() const; - - // Size routines. - size_type size() const { return size_; } - size_type max_size() const { return (std::numeric_limits<size_type>::max)(); } - bool empty() const { return size_ == 0; } - - // The height of the btree. An empty tree will have height 0. - size_type height() const { - size_type h = 0; - if (!empty()) { - // Count the length of the chain from the leftmost node up to the - // root. We actually count from the root back around to the level below - // the root, but the calculation is the same because of the circularity - // of that traversal. - const node_type *n = root(); - do { - ++h; - n = n->parent(); - } while (n != root()); - } - return h; - } - - // The number of internal, leaf and total nodes used by the btree. - size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; } - size_type internal_nodes() const { - return internal_stats(root()).internal_nodes; - } - size_type nodes() const { - node_stats stats = internal_stats(root()); - return stats.leaf_nodes + stats.internal_nodes; - } - - // The total number of bytes used by the btree. - size_type bytes_used() const { - node_stats stats = internal_stats(root()); - if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) { - return sizeof(*this) + node_type::LeafSize(root()->max_count()); - } else { - return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() + - stats.internal_nodes * node_type::InternalSize(); - } - } - - // The average number of bytes used per value stored in the btree. - static double average_bytes_per_value() { - // 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 - // divided by the maximum number of elements a tree with the current number - // of nodes could hold. A value of 1 indicates perfect space - // utilization. Smaller values indicate space wastage. - // Returns 0 for empty trees. - double fullness() const { - if (empty()) return 0.0; - return static_cast<double>(size()) / (nodes() * 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 - // storing elements divided by the number of elements. - // Returns 0 for empty trees. - double overhead() const { - if (empty()) return 0.0; - return (bytes_used() - size() * sizeof(value_type)) / - static_cast<double>(size()); - } - - // The allocator used by the btree. - allocator_type get_allocator() const { return allocator(); } - - private: - // Internal accessor routines. - node_type *root() { return root_.template get<2>(); } - const node_type *root() const { return root_.template get<2>(); } - node_type *&mutable_root() noexcept { return root_.template get<2>(); } - key_compare *mutable_key_comp() noexcept { return &root_.template get<0>(); } - - // The leftmost node is stored as the parent of the root node. - node_type *leftmost() { return root()->parent(); } - const node_type *leftmost() const { return root()->parent(); } - - // Allocator routines. - allocator_type *mutable_allocator() noexcept { - return &root_.template get<1>(); - } - const allocator_type &allocator() const noexcept { - return root_.template get<1>(); - } - - // Allocates a correctly aligned node of at least size bytes using the - // allocator. - node_type *allocate(const size_type size) { - return reinterpret_cast<node_type *>( - absl::container_internal::Allocate<node_type::Alignment()>( - mutable_allocator(), size)); - } - - // Node creation/deletion routines. - node_type *new_internal_node(node_type *parent) { - node_type *n = allocate(node_type::InternalSize()); - n->init_internal(parent); - return n; - } - node_type *new_leaf_node(node_type *parent) { - node_type *n = allocate(node_type::LeafSize()); - n->init_leaf(parent, kNodeValues); - return n; - } - node_type *new_leaf_root_node(const int max_count) { - node_type *n = allocate(node_type::LeafSize(max_count)); - n->init_leaf(/*parent=*/n, max_count); - return n; - } - - // Deletion helper routines. - iterator rebalance_after_delete(iterator iter); - - // Rebalances or splits the node iter points to. - void rebalance_or_split(iterator *iter); - - // Merges the values of left, right and the delimiting key on their parent - // onto left, removing the delimiting key and deleting right. - void merge_nodes(node_type *left, node_type *right); - - // Tries to merge node with its left or right sibling, and failing that, - // rebalance with its left or right sibling. Returns true if a merge - // occurred, at which point it is no longer valid to access node. Returns - // false if no merging took place. - bool try_merge_or_rebalance(iterator *iter); - - // Tries to shrink the height of the tree by 1. - void try_shrink(); - - iterator internal_end(iterator iter) { - return iter.node != nullptr ? iter : end(); - } - const_iterator internal_end(const_iterator iter) const { - return iter.node != nullptr ? iter : end(); - } - - // Emplaces a value into the btree immediately before iter. Requires that - // key(v) <= iter.key() and (--iter).key() <= key(v). - template <typename... Args> - iterator internal_emplace(iterator iter, Args &&... args); - - // Returns an iterator pointing to the first value >= the value "iter" is - // pointing at. Note that "iter" might be pointing to an invalid location such - // as iter.position == iter.node->finish(). This routine simply moves iter up - // in the tree to a valid location. - // Requires: iter.node is non-null. - template <typename IterType> - static IterType internal_last(IterType iter); - - // Returns an iterator pointing to the leaf position at which key would - // reside in the tree, unless there is an exact match - in which case, the - // result may not be on a leaf. When there's a three-way comparator, we can - // return whether there was an exact match. This allows the caller to avoid a - // subsequent comparison to determine if an exact match was made, which is - // important for keys with expensive comparison, such as strings. - template <typename K> - SearchResult<iterator, is_key_compare_to::value> internal_locate( - const K &key) const; - - // Internal routine which implements lower_bound(). - template <typename K> - SearchResult<iterator, is_key_compare_to::value> internal_lower_bound( - const K &key) const; - - // Internal routine which implements upper_bound(). - template <typename K> - iterator internal_upper_bound(const K &key) const; - - // Internal routine which implements find(). - template <typename K> - iterator internal_find(const K &key) const; - - // Verifies the tree structure of node. - int internal_verify(const node_type *node, const key_type *lo, - const key_type *hi) const; - - node_stats internal_stats(const node_type *node) const { - // The root can be a static empty node. - if (node == nullptr || (node == root() && empty())) { - return node_stats(0, 0); - } - if (node->leaf()) { - return node_stats(1, 0); - } - node_stats res(0, 1); - for (int i = node->start(); i <= node->finish(); ++i) { - res += internal_stats(node->child(i)); - } - return res; - } - - // We use compressed tuple in order to save space because key_compare and - // allocator_type are usually empty. - absl::container_internal::CompressedTuple<key_compare, allocator_type, - node_type *> - root_; - - // A pointer to the rightmost node. Note that the leftmost node is stored as - // the root's parent. - node_type *rightmost_; - - // Number of values. - size_type size_; -}; - -//// -// btree_node methods -template <typename P> -template <typename... Args> -inline void btree_node<P>::emplace_value(const size_type i, - allocator_type *alloc, - Args &&... args) { - assert(i >= start()); - assert(i <= finish()); - // Shift old values to create space for new value and then construct it in - // place. - if (i < finish()) { - transfer_n_backward(finish() - i, /*dest_i=*/i + 1, /*src_i=*/i, this, - alloc); - } - value_init(i, alloc, std::forward<Args>(args)...); - set_finish(finish() + 1); - - if (!leaf() && finish() > i + 1) { - for (int j = finish(); j > i + 1; --j) { - set_child(j, child(j - 1)); - } - clear_child(i + 1); - } -} - -template <typename P> -inline void btree_node<P>::remove_values(const field_type i, - const field_type to_erase, - allocator_type *alloc) { - // Transfer values after the removed range into their new places. - value_destroy_n(i, to_erase, alloc); - const field_type orig_finish = finish(); - const field_type src_i = i + to_erase; - transfer_n(orig_finish - src_i, i, src_i, this, alloc); - - if (!leaf()) { - // Delete all children between begin and end. - for (int j = 0; j < to_erase; ++j) { - clear_and_delete(child(i + j + 1), alloc); - } - // Rotate children after end into new positions. - for (int j = i + to_erase + 1; j <= orig_finish; ++j) { - set_child(j - to_erase, child(j)); - clear_child(j); - } - } - set_finish(orig_finish - to_erase); -} - -template <typename P> -void btree_node<P>::rebalance_right_to_left(const int to_move, - btree_node *right, - allocator_type *alloc) { - assert(parent() == right->parent()); - assert(position() + 1 == right->position()); - assert(right->count() >= count()); - assert(to_move >= 1); - assert(to_move <= right->count()); - - // 1) Move the delimiting value in the parent to the left node. - transfer(finish(), position(), parent(), alloc); - - // 2) Move the (to_move - 1) values from the right node to the left node. - transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc); - - // 3) Move the new delimiting value to the parent from the right node. - parent()->transfer(position(), right->start() + to_move - 1, right, alloc); - - // 4) Shift the values in the right node to their correct positions. - right->transfer_n(right->count() - to_move, right->start(), - right->start() + to_move, right, alloc); - - if (!leaf()) { - // Move the child pointers from the right to the left node. - for (int i = 0; i < to_move; ++i) { - init_child(finish() + i + 1, right->child(i)); - } - for (int i = right->start(); i <= right->finish() - to_move; ++i) { - assert(i + to_move <= right->max_count()); - right->init_child(i, right->child(i + to_move)); - right->clear_child(i + to_move); - } - } - - // Fixup `finish` on the left and right nodes. - set_finish(finish() + to_move); - right->set_finish(right->finish() - to_move); -} - -template <typename P> -void btree_node<P>::rebalance_left_to_right(const int to_move, - btree_node *right, - allocator_type *alloc) { - assert(parent() == right->parent()); - assert(position() + 1 == right->position()); - assert(count() >= right->count()); - assert(to_move >= 1); - assert(to_move <= count()); - - // Values in the right node are shifted to the right to make room for the - // new to_move values. Then, the delimiting value in the parent and the - // other (to_move - 1) values in the left node are moved into the right node. - // Lastly, a new delimiting value is moved from the left node into the - // parent, and the remaining empty left node entries are destroyed. - - // 1) Shift existing values in the right node to their correct positions. - right->transfer_n_backward(right->count(), right->start() + to_move, - right->start(), right, alloc); - - // 2) Move the delimiting value in the parent to the right node. - right->transfer(right->start() + to_move - 1, position(), parent(), alloc); - - // 3) Move the (to_move - 1) values from the left node to the right node. - right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this, - alloc); - - // 4) Move the new delimiting value to the parent from the left node. - parent()->transfer(position(), finish() - to_move, this, alloc); - - if (!leaf()) { - // Move the child pointers from the left to the right node. - for (int i = right->finish(); i >= right->start(); --i) { - right->init_child(i + to_move, right->child(i)); - right->clear_child(i); - } - for (int i = 1; i <= to_move; ++i) { - right->init_child(i - 1, child(finish() - to_move + i)); - clear_child(finish() - to_move + i); - } - } - - // Fixup the counts on the left and right nodes. - set_finish(finish() - to_move); - right->set_finish(right->finish() + to_move); -} - -template <typename P> -void btree_node<P>::split(const int insert_position, btree_node *dest, - allocator_type *alloc) { - assert(dest->count() == 0); - assert(max_count() == 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 - // more values on the right node. If we're inserting at the end of the - // right node then bias the split to put more values on the left node. - if (insert_position == start()) { - dest->set_finish(dest->start() + finish() - 1); - } else if (insert_position == kNodeValues) { - dest->set_finish(dest->start()); - } else { - dest->set_finish(dest->start() + count() / 2); - } - set_finish(finish() - dest->count()); - assert(count() >= 1); - - // Move values from the left sibling to the right sibling. - dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc); - - // The split key is the largest value in the left sibling. - --mutable_finish(); - parent()->emplace_value(position(), alloc, finish_slot()); - value_destroy(finish(), alloc); - parent()->init_child(position() + 1, dest); - - if (!leaf()) { - for (int i = dest->start(), j = finish() + 1; i <= dest->finish(); - ++i, ++j) { - assert(child(j) != nullptr); - dest->init_child(i, child(j)); - clear_child(j); - } - } -} - -template <typename P> -void btree_node<P>::merge(btree_node *src, allocator_type *alloc) { - assert(parent() == src->parent()); - assert(position() + 1 == src->position()); - - // Move the delimiting value to the left node. - value_init(finish(), alloc, parent()->slot(position())); - - // Move the values from the right to the left node. - transfer_n(src->count(), finish() + 1, src->start(), src, alloc); - - if (!leaf()) { - // Move the child pointers from the right to the left node. - for (int i = src->start(), j = finish() + 1; i <= src->finish(); ++i, ++j) { - init_child(j, src->child(i)); - src->clear_child(i); - } - } - - // Fixup `finish` on the src and dest nodes. - set_finish(start() + 1 + count() + src->count()); - src->set_finish(src->start()); - - // Remove the value on the parent node and delete the src node. - parent()->remove_values(position(), /*to_erase=*/1, alloc); -} - -template <typename P> -void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) { - if (node->leaf()) { - node->value_destroy_n(node->start(), node->count(), alloc); - deallocate(LeafSize(node->max_count()), node, alloc); - return; - } - if (node->count() == 0) { - deallocate(InternalSize(), node, alloc); - return; - } - - // The parent of the root of the subtree we are deleting. - btree_node *delete_root_parent = node->parent(); - - // Navigate to the leftmost leaf under node, and then delete upwards. - while (!node->leaf()) node = node->start_child(); - // Use `int` because `pos` needs to be able to hold `kNodeValues+1`, which - // isn't guaranteed to be a valid `field_type`. - int pos = node->position(); - btree_node *parent = node->parent(); - for (;;) { - // In each iteration of the next loop, we delete one leaf node and go right. - assert(pos <= parent->finish()); - do { - node = parent->child(pos); - if (!node->leaf()) { - // Navigate to the leftmost leaf under node. - while (!node->leaf()) node = node->start_child(); - pos = node->position(); - parent = node->parent(); - } - node->value_destroy_n(node->start(), node->count(), alloc); - deallocate(LeafSize(node->max_count()), node, alloc); - ++pos; - } while (pos <= parent->finish()); - - // Once we've deleted all children of parent, delete parent and go up/right. - assert(pos > parent->finish()); - do { - node = parent; - pos = node->position(); - parent = node->parent(); - node->value_destroy_n(node->start(), node->count(), alloc); - deallocate(InternalSize(), node, alloc); - if (parent == delete_root_parent) return; - ++pos; - } while (pos > parent->finish()); - } -} - -//// -// btree_iterator methods -template <typename N, typename R, typename P> -void btree_iterator<N, R, P>::increment_slow() { - if (node->leaf()) { - assert(position >= node->finish()); - btree_iterator save(*this); - while (position == node->finish() && !node->is_root()) { - assert(node->parent()->child(node->position()) == node); - position = node->position(); - node = node->parent(); - } - // TODO(ezb): assert we aren't incrementing end() instead of handling. - if (position == node->finish()) { - *this = save; - } - } else { - assert(position < node->finish()); - node = node->child(position + 1); - while (!node->leaf()) { - node = node->start_child(); - } - position = node->start(); - } -} - -template <typename N, typename R, typename P> -void btree_iterator<N, R, P>::decrement_slow() { - if (node->leaf()) { - assert(position <= -1); - btree_iterator save(*this); - while (position < node->start() && !node->is_root()) { - assert(node->parent()->child(node->position()) == node); - position = node->position() - 1; - node = node->parent(); - } - // TODO(ezb): assert we aren't decrementing begin() instead of handling. - if (position < node->start()) { - *this = save; - } - } else { - assert(position >= node->start()); - node = node->child(position); - while (!node->leaf()) { - node = node->child(node->finish()); - } - position = node->finish() - 1; - } -} - -//// -// btree methods -template <typename P> -template <typename Btree> -void btree<P>::copy_or_move_values_in_order(Btree &other) { - static_assert(std::is_same<btree, Btree>::value || - std::is_same<const btree, Btree>::value, - "Btree type must be same or const."); - assert(empty()); - - // We can avoid key comparisons because we know the order of the - // values is the same order we'll store them in. - auto iter = other.begin(); - if (iter == other.end()) return; - insert_multi(maybe_move_from_iterator(iter)); - ++iter; - for (; iter != other.end(); ++iter) { - // If the btree is not empty, we can just insert the new value at the end - // of the tree. - internal_emplace(end(), maybe_move_from_iterator(iter)); - } -} - -template <typename P> -constexpr bool btree<P>::static_assert_validation() { - static_assert(std::is_nothrow_copy_constructible<key_compare>::value, - "Key comparison must be nothrow copy constructible"); - static_assert(std::is_nothrow_copy_constructible<allocator_type>::value, - "Allocator must be nothrow copy constructible"); - static_assert(type_traits_internal::is_trivially_copyable<iterator>::value, - "iterator not trivially copyable."); - - // Note: We assert that kTargetValues, which is computed from - // Params::kTargetNodeSize, must fit the node_type::field_type. - static_assert( - 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. - using compare_result_type = - absl::result_of_t<key_compare(key_type, key_type)>; - static_assert( - std::is_same<compare_result_type, bool>::value || - std::is_convertible<compare_result_type, absl::weak_ordering>::value, - "key comparison function must return absl::{weak,strong}_ordering or " - "bool."); - - // Test the assumption made in setting kNodeValueSpace. - static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4, - "node space assumption incorrect"); - - return true; -} - -template <typename P> -template <typename K> -auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> { - const SearchResult<iterator, is_key_compare_to::value> res = - internal_lower_bound(key); - const iterator lower = internal_end(res.value); - if (res.HasMatch() ? !res.IsEq() - : lower == end() || compare_keys(key, lower.key())) { - return {lower, lower}; - } - - const iterator next = std::next(lower); - // When the comparator is heterogeneous, we can't assume that comparison with - // non-`key_type` will be equivalent to `key_type` comparisons so there - // could be multiple equivalent keys even in a unique-container. But for - // heterogeneous comparisons from the default string adapted comparators, we - // don't need to worry about this. - if (!is_multi_container::value && - (std::is_same<K, key_type>::value || is_key_compare_adapted::value)) { - // The next iterator after lower must point to a key greater than `key`. - // Note: if this assert fails, then it may indicate that the comparator does - // not meet the equivalence requirements for Compare - // (see https://en.cppreference.com/w/cpp/named_req/Compare). - assert(next == end() || compare_keys(key, next.key())); - return {lower, next}; - } - // Try once more to avoid the call to upper_bound() if there's only one - // equivalent key. This should prevent all calls to upper_bound() in cases of - // unique-containers with heterogeneous comparators in which all comparison - // operators have the same equivalence classes. - if (next == end() || compare_keys(key, next.key())) return {lower, next}; - - // In this case, we need to call upper_bound() to avoid worst case O(N) - // behavior if we were to iterate over equal keys. - return {lower, upper_bound(key)}; -} - -template <typename P> -template <typename K, typename... Args> -auto btree<P>::insert_unique(const K &key, Args &&... args) - -> std::pair<iterator, bool> { - if (empty()) { - mutable_root() = rightmost_ = new_leaf_root_node(1); - } - - SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key); - iterator iter = res.value; - - if (res.HasMatch()) { - if (res.IsEq()) { - // The key already exists in the tree, do nothing. - return {iter, false}; - } - } else { - iterator last = internal_last(iter); - if (last.node && !compare_keys(key, last.key())) { - // The key already exists in the tree, do nothing. - return {last, false}; - } - } - return {internal_emplace(iter, std::forward<Args>(args)...), true}; -} - -template <typename P> -template <typename K, typename... Args> -inline auto btree<P>::insert_hint_unique(iterator position, const K &key, - Args &&... args) - -> std::pair<iterator, bool> { - if (!empty()) { - if (position == end() || compare_keys(key, position.key())) { - if (position == begin() || compare_keys(std::prev(position).key(), key)) { - // prev.key() < key < position.key() - return {internal_emplace(position, std::forward<Args>(args)...), true}; - } - } else if (compare_keys(position.key(), key)) { - ++position; - if (position == end() || compare_keys(key, position.key())) { - // {original `position`}.key() < key < {current `position`}.key() - return {internal_emplace(position, std::forward<Args>(args)...), true}; - } - } else { - // position.key() == key - return {position, false}; - } - } - return insert_unique(key, std::forward<Args>(args)...); -} - -template <typename P> -template <typename InputIterator, typename> -void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) { - for (; b != e; ++b) { - insert_hint_unique(end(), params_type::key(*b), *b); - } -} - -template <typename P> -template <typename InputIterator> -void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) { - for (; b != e; ++b) { - init_type value(*b); - insert_hint_unique(end(), params_type::key(value), std::move(value)); - } -} - -template <typename P> -template <typename ValueType> -auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator { - if (empty()) { - mutable_root() = rightmost_ = new_leaf_root_node(1); - } - - iterator iter = internal_upper_bound(key); - if (iter.node == nullptr) { - iter = end(); - } - return internal_emplace(iter, std::forward<ValueType>(v)); -} - -template <typename P> -template <typename ValueType> -auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator { - if (!empty()) { - const key_type &key = params_type::key(v); - if (position == end() || !compare_keys(position.key(), key)) { - if (position == begin() || - !compare_keys(key, std::prev(position).key())) { - // prev.key() <= key <= position.key() - return internal_emplace(position, std::forward<ValueType>(v)); - } - } else { - ++position; - if (position == end() || !compare_keys(position.key(), key)) { - // {original `position`}.key() < key < {current `position`}.key() - return internal_emplace(position, std::forward<ValueType>(v)); - } - } - } - return insert_multi(std::forward<ValueType>(v)); -} - -template <typename P> -template <typename InputIterator> -void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) { - for (; b != e; ++b) { - insert_hint_multi(end(), *b); - } -} - -template <typename P> -auto btree<P>::operator=(const btree &other) -> btree & { - if (this != &other) { - clear(); - - *mutable_key_comp() = other.key_comp(); - if (absl::allocator_traits< - allocator_type>::propagate_on_container_copy_assignment::value) { - *mutable_allocator() = other.allocator(); - } - - copy_or_move_values_in_order(other); - } - return *this; -} - -template <typename P> -auto btree<P>::operator=(btree &&other) noexcept -> btree & { - if (this != &other) { - clear(); - - using std::swap; - if (absl::allocator_traits< - allocator_type>::propagate_on_container_copy_assignment::value) { - // Note: `root_` also contains the allocator and the key comparator. - swap(root_, other.root_); - swap(rightmost_, other.rightmost_); - swap(size_, other.size_); - } else { - if (allocator() == other.allocator()) { - swap(mutable_root(), other.mutable_root()); - swap(*mutable_key_comp(), *other.mutable_key_comp()); - swap(rightmost_, other.rightmost_); - swap(size_, other.size_); - } else { - // We aren't allowed to propagate the allocator and the allocator is - // different so we can't take over its memory. We must move each element - // individually. We need both `other` and `this` to have `other`s key - // comparator while moving the values so we can't swap the key - // comparators. - *mutable_key_comp() = other.key_comp(); - copy_or_move_values_in_order(other); - } - } - } - return *this; -} - -template <typename P> -auto btree<P>::erase(iterator iter) -> iterator { - bool internal_delete = false; - if (!iter.node->leaf()) { - // Deletion of a value on an internal node. First, move the largest value - // from our left child here, then delete that position (in remove_values() - // below). We can get to the largest value from our left child by - // decrementing iter. - iterator internal_iter(iter); - --iter; - assert(iter.node->leaf()); - params_type::move(mutable_allocator(), iter.node->slot(iter.position), - internal_iter.node->slot(internal_iter.position)); - internal_delete = true; - } - - // Delete the key from the leaf. - iter.node->remove_values(iter.position, /*to_erase=*/1, mutable_allocator()); - --size_; - - // We want to return the next value after the one we just erased. If we - // erased from an internal node (internal_delete == true), then the next - // value is ++(++iter). If we erased from a leaf node (internal_delete == - // false) then the next value is ++iter. Note that ++iter may point to an - // internal node and the value in the internal node may move to a leaf node - // (iter.node) when rebalancing is performed at the leaf level. - - iterator res = rebalance_after_delete(iter); - - // If we erased from an internal node, advance the iterator. - if (internal_delete) { - ++res; - } - return res; -} - -template <typename P> -auto btree<P>::rebalance_after_delete(iterator iter) -> iterator { - // Merge/rebalance as we walk back up the tree. - iterator res(iter); - bool first_iteration = true; - for (;;) { - if (iter.node == root()) { - try_shrink(); - if (empty()) { - return end(); - } - break; - } - if (iter.node->count() >= kMinNodeValues) { - break; - } - bool merged = try_merge_or_rebalance(&iter); - // On the first iteration, we should update `res` with `iter` because `res` - // may have been invalidated. - if (first_iteration) { - res = iter; - first_iteration = false; - } - if (!merged) { - break; - } - iter.position = iter.node->position(); - iter.node = iter.node->parent(); - } - - // Adjust our return value. If we're pointing at the end of a node, advance - // the iterator. - if (res.position == res.node->finish()) { - res.position = res.node->finish() - 1; - ++res; - } - - return res; -} - -template <typename P> -auto btree<P>::erase_range(iterator begin, iterator end) - -> std::pair<size_type, iterator> { - difference_type count = std::distance(begin, end); - assert(count >= 0); - - if (count == 0) { - return {0, begin}; - } - - if (count == size_) { - clear(); - return {count, this->end()}; - } - - if (begin.node == end.node) { - assert(end.position > begin.position); - begin.node->remove_values(begin.position, end.position - begin.position, - mutable_allocator()); - size_ -= count; - return {count, rebalance_after_delete(begin)}; - } - - const size_type target_size = size_ - count; - while (size_ > target_size) { - if (begin.node->leaf()) { - const size_type remaining_to_erase = size_ - target_size; - const size_type remaining_in_node = begin.node->finish() - begin.position; - const size_type to_erase = - (std::min)(remaining_to_erase, remaining_in_node); - begin.node->remove_values(begin.position, to_erase, mutable_allocator()); - size_ -= to_erase; - begin = rebalance_after_delete(begin); - } else { - begin = erase(begin); - } - } - return {count, begin}; -} - -template <typename P> -void btree<P>::clear() { - if (!empty()) { - node_type::clear_and_delete(root(), mutable_allocator()); - } - mutable_root() = EmptyNode(); - rightmost_ = EmptyNode(); - size_ = 0; -} - -template <typename P> -void btree<P>::swap(btree &other) { - using std::swap; - if (absl::allocator_traits< - allocator_type>::propagate_on_container_swap::value) { - // Note: `root_` also contains the allocator and the key comparator. - swap(root_, other.root_); - } else { - // It's undefined behavior if the allocators are unequal here. - assert(allocator() == other.allocator()); - swap(mutable_root(), other.mutable_root()); - swap(*mutable_key_comp(), *other.mutable_key_comp()); - } - swap(rightmost_, other.rightmost_); - swap(size_, other.size_); -} - -template <typename P> -void btree<P>::verify() const { - assert(root() != nullptr); - assert(leftmost() != nullptr); - assert(rightmost_ != nullptr); - assert(empty() || size() == internal_verify(root(), nullptr, nullptr)); - assert(leftmost() == (++const_iterator(root(), -1)).node); - assert(rightmost_ == (--const_iterator(root(), root()->finish())).node); - assert(leftmost()->leaf()); - assert(rightmost_->leaf()); -} - -template <typename P> -void btree<P>::rebalance_or_split(iterator *iter) { - node_type *&node = iter->node; - int &insert_position = iter->position; - assert(node->count() == node->max_count()); - assert(kNodeValues == node->max_count()); - - // First try to make room on the node by rebalancing. - node_type *parent = node->parent(); - if (node != root()) { - if (node->position() > parent->start()) { - // Try rebalancing with our left sibling. - node_type *left = parent->child(node->position() - 1); - assert(left->max_count() == 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 = (kNodeValues - left->count()) / - (1 + (insert_position < static_cast<int>(kNodeValues))); - to_move = (std::max)(1, to_move); - - if (insert_position - to_move >= node->start() || - left->count() + to_move < static_cast<int>(kNodeValues)) { - left->rebalance_right_to_left(to_move, node, mutable_allocator()); - - assert(node->max_count() - node->count() == to_move); - insert_position = insert_position - to_move; - if (insert_position < node->start()) { - insert_position = insert_position + left->count() + 1; - node = left; - } - - assert(node->count() < node->max_count()); - return; - } - } - } - - if (node->position() < parent->finish()) { - // Try rebalancing with our right sibling. - node_type *right = parent->child(node->position() + 1); - assert(right->max_count() == 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>(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>(kNodeValues)) { - node->rebalance_left_to_right(to_move, right, mutable_allocator()); - - if (insert_position > node->finish()) { - insert_position = insert_position - node->count() - 1; - node = right; - } - - assert(node->count() < node->max_count()); - return; - } - } - } - - // Rebalancing failed, make sure there is room on the parent node for a new - // value. - assert(parent->max_count() == kNodeValues); - if (parent->count() == kNodeValues) { - iterator parent_iter(node->parent(), node->position()); - rebalance_or_split(&parent_iter); - } - } else { - // Rebalancing not possible because this is the root node. - // Create a new root node and set the current root node as the child of the - // new root. - parent = new_internal_node(parent); - parent->init_child(parent->start(), root()); - mutable_root() = parent; - // If the former root was a leaf node, then it's now the rightmost node. - assert(!parent->start_child()->leaf() || - parent->start_child() == rightmost_); - } - - // Split the node. - node_type *split_node; - if (node->leaf()) { - split_node = new_leaf_node(parent); - node->split(insert_position, split_node, mutable_allocator()); - if (rightmost_ == node) rightmost_ = split_node; - } else { - split_node = new_internal_node(parent); - node->split(insert_position, split_node, mutable_allocator()); - } - - if (insert_position > node->finish()) { - insert_position = insert_position - node->count() - 1; - node = split_node; - } -} - -template <typename P> -void btree<P>::merge_nodes(node_type *left, node_type *right) { - left->merge(right, mutable_allocator()); - if (rightmost_ == right) rightmost_ = left; -} - -template <typename P> -bool btree<P>::try_merge_or_rebalance(iterator *iter) { - node_type *parent = iter->node->parent(); - if (iter->node->position() > parent->start()) { - // Try merging with our left sibling. - node_type *left = parent->child(iter->node->position() - 1); - assert(left->max_count() == kNodeValues); - if (1U + left->count() + iter->node->count() <= kNodeValues) { - iter->position += 1 + left->count(); - merge_nodes(left, iter->node); - iter->node = left; - return true; - } - } - if (iter->node->position() < parent->finish()) { - // Try merging with our right sibling. - node_type *right = parent->child(iter->node->position() + 1); - assert(right->max_count() == kNodeValues); - if (1U + iter->node->count() + right->count() <= kNodeValues) { - merge_nodes(iter->node, right); - return true; - } - // Try rebalancing with our right sibling. We don't perform rebalancing if - // we deleted the first element from iter->node and the node is not - // empty. This is a small optimization for the common pattern of deleting - // from the front of the tree. - if (right->count() > kMinNodeValues && - (iter->node->count() == 0 || iter->position > iter->node->start())) { - int to_move = (right->count() - iter->node->count()) / 2; - to_move = (std::min)(to_move, right->count() - 1); - iter->node->rebalance_right_to_left(to_move, right, mutable_allocator()); - return false; - } - } - if (iter->node->position() > parent->start()) { - // Try rebalancing with our left sibling. We don't perform rebalancing if - // we deleted the last element from iter->node and the node is not - // empty. This is a small optimization for the common pattern of deleting - // from the back of the tree. - node_type *left = parent->child(iter->node->position() - 1); - if (left->count() > kMinNodeValues && - (iter->node->count() == 0 || iter->position < iter->node->finish())) { - int to_move = (left->count() - iter->node->count()) / 2; - to_move = (std::min)(to_move, left->count() - 1); - left->rebalance_left_to_right(to_move, iter->node, mutable_allocator()); - iter->position += to_move; - return false; - } - } - return false; -} - -template <typename P> -void btree<P>::try_shrink() { - node_type *orig_root = root(); - if (orig_root->count() > 0) { - return; - } - // Deleted the last item on the root node, shrink the height of the tree. - if (orig_root->leaf()) { - assert(size() == 0); - mutable_root() = rightmost_ = EmptyNode(); - } else { - node_type *child = orig_root->start_child(); - child->make_root(); - mutable_root() = child; - } - node_type::clear_and_delete(orig_root, mutable_allocator()); -} - -template <typename P> -template <typename IterType> -inline IterType btree<P>::internal_last(IterType iter) { - assert(iter.node != nullptr); - while (iter.position == iter.node->finish()) { - iter.position = iter.node->position(); - iter.node = iter.node->parent(); - if (iter.node->leaf()) { - iter.node = nullptr; - break; - } - } - return iter; -} - -template <typename P> -template <typename... Args> -inline auto btree<P>::internal_emplace(iterator iter, Args &&... args) - -> iterator { - if (!iter.node->leaf()) { - // We can't insert on an internal node. Instead, we'll insert after the - // previous value which is guaranteed to be on a leaf node. - --iter; - ++iter.position; - } - const field_type max_count = iter.node->max_count(); - allocator_type *alloc = mutable_allocator(); - if (iter.node->count() == max_count) { - // Make room in the leaf for the new item. - if (max_count < 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>)(kNodeValues, 2 * max_count)); - // Transfer the values from the old root to the new root. - node_type *old_root = root(); - node_type *new_root = iter.node; - new_root->transfer_n(old_root->count(), new_root->start(), - old_root->start(), old_root, alloc); - new_root->set_finish(old_root->finish()); - old_root->set_finish(old_root->start()); - node_type::clear_and_delete(old_root, alloc); - mutable_root() = rightmost_ = new_root; - } else { - rebalance_or_split(&iter); - } - } - iter.node->emplace_value(iter.position, alloc, std::forward<Args>(args)...); - ++size_; - return iter; -} - -template <typename P> -template <typename K> -inline auto btree<P>::internal_locate(const K &key) const - -> SearchResult<iterator, is_key_compare_to::value> { - iterator iter(const_cast<node_type *>(root())); - for (;;) { - SearchResult<int, is_key_compare_to::value> res = - iter.node->lower_bound(key, key_comp()); - iter.position = res.value; - if (res.IsEq()) { - return {iter, MatchKind::kEq}; - } - // Note: in the non-key-compare-to case, we don't need to walk all the way - // down the tree if the keys are equal, but determining equality would - // require doing an extra comparison on each node on the way down, and we - // will need to go all the way to the leaf node in the expected case. - if (iter.node->leaf()) { - break; - } - iter.node = iter.node->child(iter.position); - } - // Note: in the non-key-compare-to case, the key may actually be equivalent - // here (and the MatchKind::kNe is ignored). - return {iter, MatchKind::kNe}; -} - -template <typename P> -template <typename K> -auto btree<P>::internal_lower_bound(const K &key) const - -> SearchResult<iterator, is_key_compare_to::value> { - 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; - // TODO(ezb): we should be able to terminate early on IsEq() if there can't - // be multiple equivalent keys in container for this lookup type. - if (iter.node->leaf()) { - break; - } - seen_eq = seen_eq || res.IsEq(); - iter.node = iter.node->child(iter.position); - } - if (res.IsEq()) return {iter, MatchKind::kEq}; - return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe}; -} - -template <typename P> -template <typename K> -auto btree<P>::internal_upper_bound(const K &key) const -> iterator { - iterator iter(const_cast<node_type *>(root())); - for (;;) { - iter.position = iter.node->upper_bound(key, key_comp()); - if (iter.node->leaf()) { - break; - } - iter.node = iter.node->child(iter.position); - } - return internal_last(iter); -} - -template <typename P> -template <typename K> -auto btree<P>::internal_find(const K &key) const -> iterator { - SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key); - if (res.HasMatch()) { - if (res.IsEq()) { - return res.value; - } - } else { - const iterator iter = internal_last(res.value); - if (iter.node != nullptr && !compare_keys(key, iter.key())) { - return iter; - } - } - return {nullptr, 0}; -} - -template <typename P> -int btree<P>::internal_verify(const node_type *node, const key_type *lo, - const key_type *hi) const { - assert(node->count() > 0); - assert(node->count() <= node->max_count()); - if (lo) { - assert(!compare_keys(node->key(node->start()), *lo)); - } - if (hi) { - assert(!compare_keys(*hi, node->key(node->finish() - 1))); - } - for (int i = node->start() + 1; i < node->finish(); ++i) { - assert(!compare_keys(node->key(i), node->key(i - 1))); - } - int count = node->count(); - if (!node->leaf()) { - for (int i = node->start(); i <= node->finish(); ++i) { - assert(node->child(i) != nullptr); - assert(node->child(i)->parent() == node); - assert(node->child(i)->position() == i); - count += internal_verify(node->child(i), - i == node->start() ? lo : &node->key(i - 1), - i == node->finish() ? hi : &node->key(i)); - } - } - return count; -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_BTREE_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/btree_container.h b/third_party/abseil_cpp/absl/container/internal/btree_container.h deleted file mode 100644 index 887eda4122f8..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/btree_container.h +++ /dev/null @@ -1,683 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_ -#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_ - -#include <algorithm> -#include <initializer_list> -#include <iterator> -#include <utility> - -#include "absl/base/internal/throw_delegate.h" -#include "absl/container/internal/btree.h" // IWYU pragma: export -#include "absl/container/internal/common.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// A common base class for btree_set, btree_map, btree_multiset, and -// btree_multimap. -template <typename Tree> -class btree_container { - using params_type = typename Tree::params_type; - - protected: - // Alias used for heterogeneous lookup functions. - // `key_arg<K>` evaluates to `K` when the functors are transparent and to - // `key_type` otherwise. It permits template argument deduction on `K` for the - // transparent case. - template <class K> - using key_arg = - typename KeyArg<IsTransparent<typename Tree::key_compare>::value>:: - template type<K, typename Tree::key_type>; - - public: - using key_type = typename Tree::key_type; - using value_type = typename Tree::value_type; - using size_type = typename Tree::size_type; - using difference_type = typename Tree::difference_type; - using key_compare = typename Tree::key_compare; - using value_compare = typename Tree::value_compare; - using allocator_type = typename Tree::allocator_type; - using reference = typename Tree::reference; - using const_reference = typename Tree::const_reference; - using pointer = typename Tree::pointer; - using const_pointer = typename Tree::const_pointer; - using iterator = typename Tree::iterator; - using const_iterator = typename Tree::const_iterator; - using reverse_iterator = typename Tree::reverse_iterator; - using const_reverse_iterator = typename Tree::const_reverse_iterator; - using node_type = typename Tree::node_handle_type; - - // Constructors/assignments. - btree_container() : tree_(key_compare(), allocator_type()) {} - explicit btree_container(const key_compare &comp, - const allocator_type &alloc = allocator_type()) - : tree_(comp, alloc) {} - explicit btree_container(const allocator_type &alloc) - : tree_(key_compare(), alloc) {} - - btree_container(const btree_container &other) - : btree_container(other, absl::allocator_traits<allocator_type>:: - select_on_container_copy_construction( - other.get_allocator())) {} - btree_container(const btree_container &other, const allocator_type &alloc) - : tree_(other.tree_, alloc) {} - - btree_container(btree_container &&other) noexcept( - std::is_nothrow_move_constructible<Tree>::value) = default; - btree_container(btree_container &&other, const allocator_type &alloc) - : tree_(std::move(other.tree_), alloc) {} - - btree_container &operator=(const btree_container &other) = default; - btree_container &operator=(btree_container &&other) noexcept( - std::is_nothrow_move_assignable<Tree>::value) = default; - - // Iterator routines. - iterator begin() { return tree_.begin(); } - const_iterator begin() const { return tree_.begin(); } - const_iterator cbegin() const { return tree_.begin(); } - iterator end() { return tree_.end(); } - const_iterator end() const { return tree_.end(); } - const_iterator cend() const { return tree_.end(); } - reverse_iterator rbegin() { return tree_.rbegin(); } - const_reverse_iterator rbegin() const { return tree_.rbegin(); } - const_reverse_iterator crbegin() const { return tree_.rbegin(); } - reverse_iterator rend() { return tree_.rend(); } - const_reverse_iterator rend() const { return tree_.rend(); } - const_reverse_iterator crend() const { return tree_.rend(); } - - // Lookup routines. - template <typename K = key_type> - size_type count(const key_arg<K> &key) const { - auto equal_range = this->equal_range(key); - return std::distance(equal_range.first, equal_range.second); - } - template <typename K = key_type> - iterator find(const key_arg<K> &key) { - return tree_.find(key); - } - template <typename K = key_type> - const_iterator find(const key_arg<K> &key) const { - return tree_.find(key); - } - template <typename K = key_type> - bool contains(const key_arg<K> &key) const { - return find(key) != end(); - } - template <typename K = key_type> - iterator lower_bound(const key_arg<K> &key) { - return tree_.lower_bound(key); - } - template <typename K = key_type> - const_iterator lower_bound(const key_arg<K> &key) const { - return tree_.lower_bound(key); - } - template <typename K = key_type> - iterator upper_bound(const key_arg<K> &key) { - return tree_.upper_bound(key); - } - template <typename K = key_type> - const_iterator upper_bound(const key_arg<K> &key) const { - return tree_.upper_bound(key); - } - template <typename K = key_type> - std::pair<iterator, iterator> equal_range(const key_arg<K> &key) { - return tree_.equal_range(key); - } - template <typename K = key_type> - std::pair<const_iterator, const_iterator> equal_range( - const key_arg<K> &key) const { - return tree_.equal_range(key); - } - - // Deletion routines. Note that there is also a deletion routine that is - // specific to btree_set_container/btree_multiset_container. - - // Erase the specified iterator from the btree. The iterator must be valid - // (i.e. not equal to end()). Return an iterator pointing to the node after - // the one that was erased (or end() if none exists). - iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); } - iterator erase(iterator iter) { return tree_.erase(iter); } - iterator erase(const_iterator first, const_iterator last) { - return tree_.erase_range(iterator(first), iterator(last)).second; - } - template <typename K = key_type> - size_type erase(const key_arg<K> &key) { - auto equal_range = this->equal_range(key); - return tree_.erase_range(equal_range.first, equal_range.second).first; - } - - // Extract routines. - node_type extract(iterator position) { - // Use Move instead of Transfer, because the rebalancing code expects to - // have a valid object to scribble metadata bits on top of. - auto node = CommonAccess::Move<node_type>(get_allocator(), position.slot()); - erase(position); - return node; - } - node_type extract(const_iterator position) { - return extract(iterator(position)); - } - - // Utility routines. - void clear() { tree_.clear(); } - void swap(btree_container &other) { tree_.swap(other.tree_); } - void verify() const { tree_.verify(); } - - // Size routines. - size_type size() const { return tree_.size(); } - size_type max_size() const { return tree_.max_size(); } - bool empty() const { return tree_.empty(); } - - friend bool operator==(const btree_container &x, const btree_container &y) { - if (x.size() != y.size()) return false; - return std::equal(x.begin(), x.end(), y.begin()); - } - - friend bool operator!=(const btree_container &x, const btree_container &y) { - return !(x == y); - } - - friend bool operator<(const btree_container &x, const btree_container &y) { - return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); - } - - friend bool operator>(const btree_container &x, const btree_container &y) { - return y < x; - } - - friend bool operator<=(const btree_container &x, const btree_container &y) { - return !(y < x); - } - - friend bool operator>=(const btree_container &x, const btree_container &y) { - return !(x < y); - } - - // The allocator used by the btree. - allocator_type get_allocator() const { return tree_.get_allocator(); } - - // The key comparator used by the btree. - key_compare key_comp() const { return tree_.key_comp(); } - value_compare value_comp() const { return tree_.value_comp(); } - - // Support absl::Hash. - template <typename State> - friend State AbslHashValue(State h, const btree_container &b) { - for (const auto &v : b) { - h = State::combine(std::move(h), v); - } - return State::combine(std::move(h), b.size()); - } - - protected: - Tree tree_; -}; - -// A common base class for btree_set and btree_map. -template <typename Tree> -class btree_set_container : public btree_container<Tree> { - using super_type = btree_container<Tree>; - using params_type = typename Tree::params_type; - using init_type = typename params_type::init_type; - using is_key_compare_to = typename params_type::is_key_compare_to; - friend class BtreeNodePeer; - - protected: - template <class K> - using key_arg = typename super_type::template key_arg<K>; - - public: - using key_type = typename Tree::key_type; - using value_type = typename Tree::value_type; - using size_type = typename Tree::size_type; - using key_compare = typename Tree::key_compare; - using allocator_type = typename Tree::allocator_type; - using iterator = typename Tree::iterator; - using const_iterator = typename Tree::const_iterator; - using node_type = typename super_type::node_type; - using insert_return_type = InsertReturnType<iterator, node_type>; - - // Inherit constructors. - using super_type::super_type; - btree_set_container() {} - - // Range constructors. - template <class InputIterator> - btree_set_container(InputIterator b, InputIterator e, - const key_compare &comp = key_compare(), - const allocator_type &alloc = allocator_type()) - : super_type(comp, alloc) { - insert(b, e); - } - template <class InputIterator> - btree_set_container(InputIterator b, InputIterator e, - const allocator_type &alloc) - : btree_set_container(b, e, key_compare(), alloc) {} - - // Initializer list constructors. - btree_set_container(std::initializer_list<init_type> init, - const key_compare &comp = key_compare(), - const allocator_type &alloc = allocator_type()) - : btree_set_container(init.begin(), init.end(), comp, alloc) {} - btree_set_container(std::initializer_list<init_type> init, - const allocator_type &alloc) - : btree_set_container(init.begin(), init.end(), alloc) {} - - // Insertion routines. - std::pair<iterator, bool> insert(const value_type &v) { - return this->tree_.insert_unique(params_type::key(v), v); - } - std::pair<iterator, bool> insert(value_type &&v) { - return this->tree_.insert_unique(params_type::key(v), std::move(v)); - } - template <typename... Args> - std::pair<iterator, bool> emplace(Args &&... args) { - init_type v(std::forward<Args>(args)...); - return this->tree_.insert_unique(params_type::key(v), std::move(v)); - } - iterator insert(const_iterator hint, const value_type &v) { - return this->tree_ - .insert_hint_unique(iterator(hint), params_type::key(v), v) - .first; - } - iterator insert(const_iterator hint, value_type &&v) { - return this->tree_ - .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v)) - .first; - } - template <typename... Args> - iterator emplace_hint(const_iterator hint, Args &&... args) { - init_type v(std::forward<Args>(args)...); - return this->tree_ - .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v)) - .first; - } - template <typename InputIterator> - void insert(InputIterator b, InputIterator e) { - this->tree_.insert_iterator_unique(b, e, 0); - } - void insert(std::initializer_list<init_type> init) { - this->tree_.insert_iterator_unique(init.begin(), init.end(), 0); - } - insert_return_type insert(node_type &&node) { - if (!node) return {this->end(), false, node_type()}; - std::pair<iterator, bool> res = - this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)), - CommonAccess::GetSlot(node)); - if (res.second) { - CommonAccess::Destroy(&node); - return {res.first, true, node_type()}; - } else { - return {res.first, false, std::move(node)}; - } - } - iterator insert(const_iterator hint, node_type &&node) { - if (!node) return this->end(); - std::pair<iterator, bool> res = this->tree_.insert_hint_unique( - iterator(hint), params_type::key(CommonAccess::GetSlot(node)), - CommonAccess::GetSlot(node)); - if (res.second) CommonAccess::Destroy(&node); - return res.first; - } - - // Node extraction routines. - // TODO(ezb): when the comparator is heterogeneous and has different - // equivalence classes for different lookup types, we should extract the first - // equivalent value if there are multiple. - template <typename K = key_type> - node_type extract(const key_arg<K> &key) { - auto it = this->find(key); - return it == this->end() ? node_type() : extract(it); - } - using super_type::extract; - - // Merge routines. - // Moves elements from `src` into `this`. If the element already exists in - // `this`, it is left unmodified in `src`. - template < - typename T, - typename absl::enable_if_t< - absl::conjunction< - std::is_same<value_type, typename T::value_type>, - std::is_same<allocator_type, typename T::allocator_type>, - std::is_same<typename params_type::is_map_container, - typename T::params_type::is_map_container>>::value, - int> = 0> - void merge(btree_container<T> &src) { // NOLINT - for (auto src_it = src.begin(); src_it != src.end();) { - if (insert(std::move(params_type::element(src_it.slot()))).second) { - src_it = src.erase(src_it); - } else { - ++src_it; - } - } - } - - template < - typename T, - typename absl::enable_if_t< - absl::conjunction< - std::is_same<value_type, typename T::value_type>, - std::is_same<allocator_type, typename T::allocator_type>, - std::is_same<typename params_type::is_map_container, - typename T::params_type::is_map_container>>::value, - int> = 0> - void merge(btree_container<T> &&src) { - merge(src); - } -}; - -// Base class for btree_map. -template <typename Tree> -class btree_map_container : public btree_set_container<Tree> { - using super_type = btree_set_container<Tree>; - using params_type = typename Tree::params_type; - friend class BtreeNodePeer; - - private: - template <class K> - using key_arg = typename super_type::template key_arg<K>; - - public: - using key_type = typename Tree::key_type; - using mapped_type = typename params_type::mapped_type; - using value_type = typename Tree::value_type; - using key_compare = typename Tree::key_compare; - using allocator_type = typename Tree::allocator_type; - using iterator = typename Tree::iterator; - using const_iterator = typename Tree::const_iterator; - - // Inherit constructors. - using super_type::super_type; - btree_map_container() {} - - // Insertion routines. - // Note: the nullptr template arguments and extra `const M&` overloads allow - // for supporting bitfield arguments. - template <typename K = key_type, class M> - std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, - const M &obj) { - return insert_or_assign_impl(k, obj); - } - template <typename K = key_type, class M, K * = nullptr> - std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj) { - return insert_or_assign_impl(std::forward<K>(k), obj); - } - template <typename K = key_type, class M, M * = nullptr> - std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj) { - return insert_or_assign_impl(k, std::forward<M>(obj)); - } - template <typename K = key_type, class M, K * = nullptr, M * = nullptr> - std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj) { - return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj)); - } - template <typename K = key_type, class M> - iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, - const M &obj) { - return insert_or_assign_hint_impl(hint, k, obj); - } - template <typename K = key_type, class M, K * = nullptr> - iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, const M &obj) { - return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj); - } - template <typename K = key_type, class M, M * = nullptr> - iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, M &&obj) { - return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj)); - } - template <typename K = key_type, class M, K * = nullptr, M * = nullptr> - iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, M &&obj) { - return insert_or_assign_hint_impl(hint, std::forward<K>(k), - std::forward<M>(obj)); - } - - template <typename K = key_type, typename... Args, - typename absl::enable_if_t< - !std::is_convertible<K, const_iterator>::value, int> = 0> - std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&... args) { - return try_emplace_impl(k, std::forward<Args>(args)...); - } - template <typename K = key_type, typename... Args, - typename absl::enable_if_t< - !std::is_convertible<K, const_iterator>::value, int> = 0> - std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&... args) { - return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...); - } - template <typename K = key_type, typename... Args> - iterator try_emplace(const_iterator hint, const key_arg<K> &k, - Args &&... args) { - return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...); - } - template <typename K = key_type, typename... Args> - iterator try_emplace(const_iterator hint, key_arg<K> &&k, Args &&... args) { - return try_emplace_hint_impl(hint, std::forward<K>(k), - std::forward<Args>(args)...); - } - - template <typename K = key_type> - mapped_type &operator[](const key_arg<K> &k) { - return try_emplace(k).first->second; - } - template <typename K = key_type> - mapped_type &operator[](key_arg<K> &&k) { - return try_emplace(std::forward<K>(k)).first->second; - } - - template <typename K = key_type> - mapped_type &at(const key_arg<K> &key) { - auto it = this->find(key); - if (it == this->end()) - base_internal::ThrowStdOutOfRange("absl::btree_map::at"); - return it->second; - } - template <typename K = key_type> - const mapped_type &at(const key_arg<K> &key) const { - auto it = this->find(key); - if (it == this->end()) - base_internal::ThrowStdOutOfRange("absl::btree_map::at"); - return it->second; - } - - private: - // Note: when we call `std::forward<M>(obj)` twice, it's safe because - // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when - // `ret.second` is false. - template <class K, class M> - std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) { - const std::pair<iterator, bool> ret = - this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj)); - if (!ret.second) ret.first->second = std::forward<M>(obj); - return ret; - } - template <class K, class M> - iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) { - const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique( - iterator(hint), k, std::forward<K>(k), std::forward<M>(obj)); - if (!ret.second) ret.first->second = std::forward<M>(obj); - return ret.first; - } - - template <class K, class... Args> - std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) { - return this->tree_.insert_unique( - k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)), - std::forward_as_tuple(std::forward<Args>(args)...)); - } - template <class K, class... Args> - iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) { - return this->tree_ - .insert_hint_unique(iterator(hint), k, std::piecewise_construct, - std::forward_as_tuple(std::forward<K>(k)), - std::forward_as_tuple(std::forward<Args>(args)...)) - .first; - } -}; - -// A common base class for btree_multiset and btree_multimap. -template <typename Tree> -class btree_multiset_container : public btree_container<Tree> { - using super_type = btree_container<Tree>; - using params_type = typename Tree::params_type; - using init_type = typename params_type::init_type; - using is_key_compare_to = typename params_type::is_key_compare_to; - - template <class K> - using key_arg = typename super_type::template key_arg<K>; - - public: - using key_type = typename Tree::key_type; - using value_type = typename Tree::value_type; - using size_type = typename Tree::size_type; - using key_compare = typename Tree::key_compare; - using allocator_type = typename Tree::allocator_type; - using iterator = typename Tree::iterator; - using const_iterator = typename Tree::const_iterator; - using node_type = typename super_type::node_type; - - // Inherit constructors. - using super_type::super_type; - btree_multiset_container() {} - - // Range constructors. - template <class InputIterator> - btree_multiset_container(InputIterator b, InputIterator e, - const key_compare &comp = key_compare(), - const allocator_type &alloc = allocator_type()) - : super_type(comp, alloc) { - insert(b, e); - } - template <class InputIterator> - btree_multiset_container(InputIterator b, InputIterator e, - const allocator_type &alloc) - : btree_multiset_container(b, e, key_compare(), alloc) {} - - // Initializer list constructors. - btree_multiset_container(std::initializer_list<init_type> init, - const key_compare &comp = key_compare(), - const allocator_type &alloc = allocator_type()) - : btree_multiset_container(init.begin(), init.end(), comp, alloc) {} - btree_multiset_container(std::initializer_list<init_type> init, - const allocator_type &alloc) - : btree_multiset_container(init.begin(), init.end(), alloc) {} - - // Insertion routines. - iterator insert(const value_type &v) { return this->tree_.insert_multi(v); } - iterator insert(value_type &&v) { - return this->tree_.insert_multi(std::move(v)); - } - iterator insert(const_iterator hint, const value_type &v) { - return this->tree_.insert_hint_multi(iterator(hint), v); - } - iterator insert(const_iterator hint, value_type &&v) { - return this->tree_.insert_hint_multi(iterator(hint), std::move(v)); - } - template <typename InputIterator> - void insert(InputIterator b, InputIterator e) { - this->tree_.insert_iterator_multi(b, e); - } - void insert(std::initializer_list<init_type> init) { - this->tree_.insert_iterator_multi(init.begin(), init.end()); - } - template <typename... Args> - iterator emplace(Args &&... args) { - return this->tree_.insert_multi(init_type(std::forward<Args>(args)...)); - } - template <typename... Args> - iterator emplace_hint(const_iterator hint, Args &&... args) { - return this->tree_.insert_hint_multi( - iterator(hint), init_type(std::forward<Args>(args)...)); - } - iterator insert(node_type &&node) { - if (!node) return this->end(); - iterator res = - this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)), - CommonAccess::GetSlot(node)); - CommonAccess::Destroy(&node); - return res; - } - iterator insert(const_iterator hint, node_type &&node) { - if (!node) return this->end(); - iterator res = this->tree_.insert_hint_multi( - iterator(hint), - std::move(params_type::element(CommonAccess::GetSlot(node)))); - CommonAccess::Destroy(&node); - return res; - } - - // Node extraction routines. - // TODO(ezb): we are supposed to extract the first equivalent key if there are - // multiple, but this isn't guaranteed to extract the first one. - template <typename K = key_type> - node_type extract(const key_arg<K> &key) { - auto it = this->find(key); - return it == this->end() ? node_type() : extract(it); - } - using super_type::extract; - - // Merge routines. - // Moves all elements from `src` into `this`. - template < - typename T, - typename absl::enable_if_t< - absl::conjunction< - std::is_same<value_type, typename T::value_type>, - std::is_same<allocator_type, typename T::allocator_type>, - std::is_same<typename params_type::is_map_container, - typename T::params_type::is_map_container>>::value, - int> = 0> - void merge(btree_container<T> &src) { // NOLINT - for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) { - insert(std::move(params_type::element(src_it.slot()))); - } - src.clear(); - } - - template < - typename T, - typename absl::enable_if_t< - absl::conjunction< - std::is_same<value_type, typename T::value_type>, - std::is_same<allocator_type, typename T::allocator_type>, - std::is_same<typename params_type::is_map_container, - typename T::params_type::is_map_container>>::value, - int> = 0> - void merge(btree_container<T> &&src) { - merge(src); - } -}; - -// A base class for btree_multimap. -template <typename Tree> -class btree_multimap_container : public btree_multiset_container<Tree> { - using super_type = btree_multiset_container<Tree>; - using params_type = typename Tree::params_type; - - public: - using mapped_type = typename params_type::mapped_type; - - // Inherit constructors. - using super_type::super_type; - btree_multimap_container() {} -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/common.h b/third_party/abseil_cpp/absl/container/internal/common.h deleted file mode 100644 index 030e9d4ab07d..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/common.h +++ /dev/null @@ -1,206 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_ -#define ABSL_CONTAINER_INTERNAL_CONTAINER_H_ - -#include <cassert> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class, class = void> -struct IsTransparent : std::false_type {}; -template <class T> -struct IsTransparent<T, absl::void_t<typename T::is_transparent>> - : std::true_type {}; - -template <bool is_transparent> -struct KeyArg { - // Transparent. Forward `K`. - template <typename K, typename key_type> - using type = K; -}; - -template <> -struct KeyArg<false> { - // Not transparent. Always use `key_type`. - template <typename K, typename key_type> - using type = key_type; -}; - -// The node_handle concept from C++17. -// We specialize node_handle for sets and maps. node_handle_base holds the -// common API of both. -template <typename PolicyTraits, typename Alloc> -class node_handle_base { - protected: - using slot_type = typename PolicyTraits::slot_type; - - public: - using allocator_type = Alloc; - - constexpr node_handle_base() = default; - node_handle_base(node_handle_base&& other) noexcept { - *this = std::move(other); - } - ~node_handle_base() { destroy(); } - node_handle_base& operator=(node_handle_base&& other) noexcept { - destroy(); - if (!other.empty()) { - alloc_ = other.alloc_; - PolicyTraits::transfer(alloc(), slot(), other.slot()); - other.reset(); - } - return *this; - } - - bool empty() const noexcept { return !alloc_; } - explicit operator bool() const noexcept { return !empty(); } - allocator_type get_allocator() const { return *alloc_; } - - protected: - friend struct CommonAccess; - - struct transfer_tag_t {}; - node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s) - : alloc_(a) { - PolicyTraits::transfer(alloc(), slot(), s); - } - - struct move_tag_t {}; - node_handle_base(move_tag_t, const allocator_type& a, slot_type* s) - : alloc_(a) { - PolicyTraits::construct(alloc(), slot(), s); - } - - void destroy() { - if (!empty()) { - PolicyTraits::destroy(alloc(), slot()); - reset(); - } - } - - void reset() { - assert(alloc_.has_value()); - alloc_ = absl::nullopt; - } - - slot_type* slot() const { - assert(!empty()); - return reinterpret_cast<slot_type*>(std::addressof(slot_space_)); - } - allocator_type* alloc() { return std::addressof(*alloc_); } - - private: - absl::optional<allocator_type> alloc_ = {}; - alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {}; -}; - -// For sets. -template <typename Policy, typename PolicyTraits, typename Alloc, - typename = void> -class node_handle : public node_handle_base<PolicyTraits, Alloc> { - using Base = node_handle_base<PolicyTraits, Alloc>; - - public: - using value_type = typename PolicyTraits::value_type; - - constexpr node_handle() {} - - value_type& value() const { return PolicyTraits::element(this->slot()); } - - private: - friend struct CommonAccess; - - using Base::Base; -}; - -// For maps. -template <typename Policy, typename PolicyTraits, typename Alloc> -class node_handle<Policy, PolicyTraits, Alloc, - absl::void_t<typename Policy::mapped_type>> - : public node_handle_base<PolicyTraits, Alloc> { - using Base = node_handle_base<PolicyTraits, Alloc>; - using slot_type = typename PolicyTraits::slot_type; - - public: - using key_type = typename Policy::key_type; - using mapped_type = typename Policy::mapped_type; - - constexpr node_handle() {} - - // When C++17 is available, we can use std::launder to provide mutable - // access to the key. Otherwise, we provide const access. - auto key() const - -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) { - return PolicyTraits::mutable_key(this->slot()); - } - - mapped_type& mapped() const { - return PolicyTraits::value(&PolicyTraits::element(this->slot())); - } - - private: - friend struct CommonAccess; - - using Base::Base; -}; - -// Provide access to non-public node-handle functions. -struct CommonAccess { - template <typename Node> - static auto GetSlot(const Node& node) -> decltype(node.slot()) { - return node.slot(); - } - - template <typename Node> - static void Destroy(Node* node) { - node->destroy(); - } - - template <typename Node> - static void Reset(Node* node) { - node->reset(); - } - - template <typename T, typename... Args> - static T Transfer(Args&&... args) { - return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...); - } - - template <typename T, typename... Args> - static T Move(Args&&... args) { - return T(typename T::move_tag_t{}, std::forward<Args>(args)...); - } -}; - -// Implement the insert_return_type<> concept of C++17. -template <class Iterator, class NodeType> -struct InsertReturnType { - Iterator position; - bool inserted; - NodeType node; -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/compressed_tuple.h b/third_party/abseil_cpp/absl/container/internal/compressed_tuple.h deleted file mode 100644 index 5ebe16494249..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/compressed_tuple.h +++ /dev/null @@ -1,290 +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. -// -// Helper class to perform the Empty Base Optimization. -// Ts can contain classes and non-classes, empty or not. For the ones that -// are empty classes, we perform the optimization. If all types in Ts are empty -// classes, then CompressedTuple<Ts...> is itself an empty class. -// -// To access the members, use member get<N>() function. -// -// Eg: -// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2, -// t3); -// assert(value.get<0>() == 7); -// T1& t1 = value.get<1>(); -// const T2& t2 = value.get<2>(); -// ... -// -// https://en.cppreference.com/w/cpp/language/ebo - -#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ -#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ - -#include <initializer_list> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/utility/utility.h" - -#if defined(_MSC_VER) && !defined(__NVCC__) -// We need to mark these classes with this declspec to ensure that -// CompressedTuple happens. -#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases) -#else -#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <typename... Ts> -class CompressedTuple; - -namespace internal_compressed_tuple { - -template <typename D, size_t I> -struct Elem; -template <typename... B, size_t I> -struct Elem<CompressedTuple<B...>, I> - : std::tuple_element<I, std::tuple<B...>> {}; -template <typename D, size_t I> -using ElemT = typename Elem<D, I>::type; - -// Use the __is_final intrinsic if available. Where it's not available, classes -// declared with the 'final' specifier cannot be used as CompressedTuple -// elements. -// TODO(sbenza): Replace this with std::is_final in C++14. -template <typename T> -constexpr bool IsFinal() { -#if defined(__clang__) || defined(__GNUC__) - return __is_final(T); -#else - return false; -#endif -} - -// We can't use EBCO on other CompressedTuples because that would mean that we -// derive from multiple Storage<> instantiations with the same I parameter, -// and potentially from multiple identical Storage<> instantiations. So anytime -// we use type inheritance rather than encapsulation, we mark -// CompressedTupleImpl, to make this easy to detect. -struct uses_inheritance {}; - -template <typename T> -constexpr bool ShouldUseBase() { - return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>() && - !std::is_base_of<uses_inheritance, T>::value; -} - -// The storage class provides two specializations: -// - For empty classes, it stores T as a base class. -// - For everything else, it stores T as a member. -template <typename T, size_t I, -#if defined(_MSC_VER) - bool UseBase = - ShouldUseBase<typename std::enable_if<true, T>::type>()> -#else - bool UseBase = ShouldUseBase<T>()> -#endif -struct Storage { - T value; - constexpr Storage() = default; - template <typename V> - explicit constexpr Storage(absl::in_place_t, V&& v) - : value(absl::forward<V>(v)) {} - constexpr const T& get() const& { return value; } - T& get() & { return value; } - constexpr const T&& get() const&& { return absl::move(*this).value; } - T&& get() && { return std::move(*this).value; } -}; - -template <typename T, size_t I> -struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T { - constexpr Storage() = default; - - template <typename V> - explicit constexpr Storage(absl::in_place_t, V&& v) - : T(absl::forward<V>(v)) {} - - constexpr const T& get() const& { return *this; } - T& get() & { return *this; } - constexpr const T&& get() const&& { return absl::move(*this); } - T&& get() && { return std::move(*this); } -}; - -template <typename D, typename I, bool ShouldAnyUseBase> -struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl; - -template <typename... Ts, size_t... I, bool ShouldAnyUseBase> -struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl< - CompressedTuple<Ts...>, absl::index_sequence<I...>, ShouldAnyUseBase> - // We use the dummy identity function through std::integral_constant to - // convince MSVC of accepting and expanding I in that context. Without it - // you would get: - // error C3548: 'I': parameter pack cannot be used in this context - : uses_inheritance, - Storage<Ts, std::integral_constant<size_t, I>::value>... { - constexpr CompressedTupleImpl() = default; - template <typename... Vs> - explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args) - : Storage<Ts, I>(absl::in_place, absl::forward<Vs>(args))... {} - friend CompressedTuple<Ts...>; -}; - -template <typename... Ts, size_t... I> -struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl< - CompressedTuple<Ts...>, absl::index_sequence<I...>, false> - // We use the dummy identity function as above... - : Storage<Ts, std::integral_constant<size_t, I>::value, false>... { - constexpr CompressedTupleImpl() = default; - template <typename... Vs> - explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args) - : Storage<Ts, I, false>(absl::in_place, absl::forward<Vs>(args))... {} - friend CompressedTuple<Ts...>; -}; - -std::false_type Or(std::initializer_list<std::false_type>); -std::true_type Or(std::initializer_list<bool>); - -// MSVC requires this to be done separately rather than within the declaration -// of CompressedTuple below. -template <typename... Ts> -constexpr bool ShouldAnyUseBase() { - return decltype( - Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){}; -} - -template <typename T, typename V> -using TupleElementMoveConstructible = - typename std::conditional<std::is_reference<T>::value, - std::is_convertible<V, T>, - std::is_constructible<T, V&&>>::type; - -template <bool SizeMatches, class T, class... Vs> -struct TupleMoveConstructible : std::false_type {}; - -template <class... Ts, class... Vs> -struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...> - : std::integral_constant< - bool, absl::conjunction< - TupleElementMoveConstructible<Ts, Vs&&>...>::value> {}; - -template <typename T> -struct compressed_tuple_size; - -template <typename... Es> -struct compressed_tuple_size<CompressedTuple<Es...>> - : public std::integral_constant<std::size_t, sizeof...(Es)> {}; - -template <class T, class... Vs> -struct TupleItemsMoveConstructible - : std::integral_constant< - bool, TupleMoveConstructible<compressed_tuple_size<T>::value == - sizeof...(Vs), - T, Vs...>::value> {}; - -} // namespace internal_compressed_tuple - -// Helper class to perform the Empty Base Class Optimization. -// Ts can contain classes and non-classes, empty or not. For the ones that -// are empty classes, we perform the CompressedTuple. If all types in Ts are -// empty classes, then CompressedTuple<Ts...> is itself an empty class. (This -// does not apply when one or more of those empty classes is itself an empty -// CompressedTuple.) -// -// To access the members, use member .get<N>() function. -// -// Eg: -// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2, -// t3); -// assert(value.get<0>() == 7); -// T1& t1 = value.get<1>(); -// const T2& t2 = value.get<2>(); -// ... -// -// https://en.cppreference.com/w/cpp/language/ebo -template <typename... Ts> -class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple - : private internal_compressed_tuple::CompressedTupleImpl< - CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>, - internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> { - private: - template <int I> - using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>; - - template <int I> - using StorageT = internal_compressed_tuple::Storage<ElemT<I>, I>; - - public: - // There seems to be a bug in MSVC dealing in which using '=default' here will - // cause the compiler to ignore the body of other constructors. The work- - // around is to explicitly implement the default constructor. -#if defined(_MSC_VER) - constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {} -#else - constexpr CompressedTuple() = default; -#endif - explicit constexpr CompressedTuple(const Ts&... base) - : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {} - - template <typename First, typename... Vs, - absl::enable_if_t< - absl::conjunction< - // Ensure we are not hiding default copy/move constructors. - absl::negation<std::is_same<void(CompressedTuple), - void(absl::decay_t<First>)>>, - internal_compressed_tuple::TupleItemsMoveConstructible< - CompressedTuple<Ts...>, First, Vs...>>::value, - bool> = true> - explicit constexpr CompressedTuple(First&& first, Vs&&... base) - : CompressedTuple::CompressedTupleImpl(absl::in_place, - absl::forward<First>(first), - absl::forward<Vs>(base)...) {} - - template <int I> - ElemT<I>& get() & { - return StorageT<I>::get(); - } - - template <int I> - constexpr const ElemT<I>& get() const& { - return StorageT<I>::get(); - } - - template <int I> - ElemT<I>&& get() && { - return std::move(*this).StorageT<I>::get(); - } - - template <int I> - constexpr const ElemT<I>&& get() const&& { - return absl::move(*this).StorageT<I>::get(); - } -}; - -// Explicit specialization for a zero-element tuple -// (needed to avoid ambiguous overloads for the default constructor). -template <> -class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC - -#endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ 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 deleted file mode 100644 index 62a7483ee311..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/compressed_tuple_test.cc +++ /dev/null @@ -1,409 +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/compressed_tuple.h" - -#include <memory> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/memory/memory.h" -#include "absl/types/any.h" -#include "absl/types/optional.h" -#include "absl/utility/utility.h" - -// These are declared at global scope purely so that error messages -// are smaller and easier to understand. -enum class CallType { kConstRef, kConstMove }; - -template <int> -struct Empty { - constexpr CallType value() const& { return CallType::kConstRef; } - constexpr CallType value() const&& { return CallType::kConstMove; } -}; - -template <typename T> -struct NotEmpty { - T value; -}; - -template <typename T, typename U> -struct TwoValues { - T value1; - U value2; -}; - - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using absl::test_internal::CopyableMovableInstance; -using absl::test_internal::InstanceTracker; - -TEST(CompressedTupleTest, Sizeof) { - EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>)); - EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>)); - EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>)); - EXPECT_EQ(sizeof(int), - sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>)); - - EXPECT_EQ(sizeof(TwoValues<int, double>), - sizeof(CompressedTuple<int, NotEmpty<double>>)); - EXPECT_EQ(sizeof(TwoValues<int, double>), - sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>)); - EXPECT_EQ(sizeof(TwoValues<int, double>), - sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>)); -} - -TEST(CompressedTupleTest, OneMoveOnRValueConstructionTemp) { - InstanceTracker tracker; - CompressedTuple<CopyableMovableInstance> x1(CopyableMovableInstance(1)); - EXPECT_EQ(tracker.instances(), 1); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_LE(tracker.moves(), 1); - EXPECT_EQ(x1.get<0>().value(), 1); -} - -TEST(CompressedTupleTest, OneMoveOnRValueConstructionMove) { - InstanceTracker tracker; - - CopyableMovableInstance i1(1); - CompressedTuple<CopyableMovableInstance> x1(std::move(i1)); - EXPECT_EQ(tracker.instances(), 2); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_LE(tracker.moves(), 1); - EXPECT_EQ(x1.get<0>().value(), 1); -} - -TEST(CompressedTupleTest, OneMoveOnRValueConstructionMixedTypes) { - InstanceTracker tracker; - CopyableMovableInstance i1(1); - CopyableMovableInstance i2(2); - Empty<0> empty; - CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>> - x1(std::move(i1), i2, empty); - EXPECT_EQ(x1.get<0>().value(), 1); - EXPECT_EQ(x1.get<1>().value(), 2); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); -} - -struct IncompleteType; -CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>> -MakeWithIncomplete(CopyableMovableInstance i1, - IncompleteType& t, // NOLINT - Empty<0> empty) { - return CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>>{ - std::move(i1), t, empty}; -} - -struct IncompleteType {}; -TEST(CompressedTupleTest, OneMoveOnRValueConstructionWithIncompleteType) { - InstanceTracker tracker; - CopyableMovableInstance i1(1); - Empty<0> empty; - struct DerivedType : IncompleteType {int value = 0;}; - DerivedType fd; - fd.value = 7; - - CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>> x1 = - MakeWithIncomplete(std::move(i1), fd, empty); - - EXPECT_EQ(x1.get<0>().value(), 1); - EXPECT_EQ(static_cast<DerivedType&>(x1.get<1>()).value, 7); - - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 2); -} - -TEST(CompressedTupleTest, - OneMoveOnRValueConstructionMixedTypes_BraceInitPoisonPillExpected) { - InstanceTracker tracker; - CopyableMovableInstance i1(1); - CopyableMovableInstance i2(2); - CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>> - x1(std::move(i1), i2, {}); // NOLINT - EXPECT_EQ(x1.get<0>().value(), 1); - EXPECT_EQ(x1.get<1>().value(), 2); - EXPECT_EQ(tracker.instances(), 3); - // We are forced into the `const Ts&...` constructor (invoking copies) - // because we need it to deduce the type of `{}`. - // std::tuple also has this behavior. - // Note, this test is proof that this is expected behavior, but it is not - // _desired_ behavior. - EXPECT_EQ(tracker.copies(), 1); - EXPECT_EQ(tracker.moves(), 0); -} - -TEST(CompressedTupleTest, OneCopyOnLValueConstruction) { - InstanceTracker tracker; - CopyableMovableInstance i1(1); - - CompressedTuple<CopyableMovableInstance> x1(i1); - EXPECT_EQ(tracker.copies(), 1); - EXPECT_EQ(tracker.moves(), 0); - - tracker.ResetCopiesMovesSwaps(); - - CopyableMovableInstance i2(2); - const CopyableMovableInstance& i2_ref = i2; - CompressedTuple<CopyableMovableInstance> x2(i2_ref); - EXPECT_EQ(tracker.copies(), 1); - EXPECT_EQ(tracker.moves(), 0); -} - -TEST(CompressedTupleTest, OneMoveOnRValueAccess) { - InstanceTracker tracker; - CopyableMovableInstance i1(1); - CompressedTuple<CopyableMovableInstance> x(std::move(i1)); - tracker.ResetCopiesMovesSwaps(); - - CopyableMovableInstance i2 = std::move(x).get<0>(); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); -} - -TEST(CompressedTupleTest, OneCopyOnLValueAccess) { - InstanceTracker tracker; - - CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0)); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); - - CopyableMovableInstance t = x.get<0>(); - EXPECT_EQ(tracker.copies(), 1); - EXPECT_EQ(tracker.moves(), 1); -} - -TEST(CompressedTupleTest, ZeroCopyOnRefAccess) { - InstanceTracker tracker; - - CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0)); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); - - CopyableMovableInstance& t1 = x.get<0>(); - const CopyableMovableInstance& t2 = x.get<0>(); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); - EXPECT_EQ(t1.value(), 0); - EXPECT_EQ(t2.value(), 0); -} - -TEST(CompressedTupleTest, Access) { - struct S { - std::string x; - }; - CompressedTuple<int, Empty<0>, S> x(7, {}, S{"ABC"}); - EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>)); - EXPECT_EQ(7, x.get<0>()); - EXPECT_EQ("ABC", x.get<2>().x); -} - -TEST(CompressedTupleTest, NonClasses) { - CompressedTuple<int, const char*> x(7, "ABC"); - EXPECT_EQ(7, x.get<0>()); - EXPECT_STREQ("ABC", x.get<1>()); -} - -TEST(CompressedTupleTest, MixClassAndNonClass) { - CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, "ABC", {}, - {1.25}); - struct Mock { - int v; - const char* p; - double d; - }; - EXPECT_EQ(sizeof(x), sizeof(Mock)); - EXPECT_EQ(7, x.get<0>()); - EXPECT_STREQ("ABC", x.get<1>()); - EXPECT_EQ(1.25, x.get<3>().value); -} - -TEST(CompressedTupleTest, Nested) { - CompressedTuple<int, CompressedTuple<int>, - CompressedTuple<int, CompressedTuple<int>>> - x(1, CompressedTuple<int>(2), - CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4))); - EXPECT_EQ(1, x.get<0>()); - EXPECT_EQ(2, x.get<1>().get<0>()); - EXPECT_EQ(3, x.get<2>().get<0>()); - EXPECT_EQ(4, x.get<2>().get<1>().get<0>()); - - CompressedTuple<Empty<0>, Empty<0>, - CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>> - y; - std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(), - &y.get<2>().get<1>().get<0>()}; -#ifdef _MSC_VER - // MSVC has a bug where many instances of the same base class are layed out in - // the same address when using __declspec(empty_bases). - // This will be fixed in a future version of MSVC. - int expected = 1; -#else - int expected = 4; -#endif - EXPECT_EQ(expected, sizeof(y)); - EXPECT_EQ(expected, empties.size()); - EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size()); - - EXPECT_EQ(4 * sizeof(char), - sizeof(CompressedTuple<CompressedTuple<char, char>, - CompressedTuple<char, char>>)); - EXPECT_TRUE((std::is_empty<CompressedTuple<Empty<0>, Empty<1>>>::value)); - - // Make sure everything still works when things are nested. - struct CT_Empty : CompressedTuple<Empty<0>> {}; - CompressedTuple<Empty<0>, CT_Empty> nested_empty; - auto contained = nested_empty.get<0>(); - auto nested = nested_empty.get<1>().get<0>(); - EXPECT_TRUE((std::is_same<decltype(contained), decltype(nested)>::value)); -} - -TEST(CompressedTupleTest, Reference) { - int i = 7; - std::string s = "Very long 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(x.get<0>(), x.get<1>()); - EXPECT_NE(&x.get<0>(), &x.get<1>()); - EXPECT_EQ(&x.get<1>(), &i); - - EXPECT_EQ(x.get<2>(), x.get<3>()); - EXPECT_NE(&x.get<2>(), &x.get<3>()); - EXPECT_EQ(&x.get<3>(), &s); -} - -TEST(CompressedTupleTest, NoElements) { - CompressedTuple<> x; - static_cast<void>(x); // Silence -Wunused-variable. - EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value); -} - -TEST(CompressedTupleTest, MoveOnlyElements) { - CompressedTuple<std::unique_ptr<std::string>> str_tup( - absl::make_unique<std::string>("str")); - - CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>, - std::unique_ptr<int>> - x(std::move(str_tup), absl::make_unique<int>(5)); - - EXPECT_EQ(*x.get<0>().get<0>(), "str"); - EXPECT_EQ(*x.get<1>(), 5); - - std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>(); - std::unique_ptr<int> x1 = std::move(x).get<1>(); - - EXPECT_EQ(*x0, "str"); - EXPECT_EQ(*x1, 5); -} - -TEST(CompressedTupleTest, MoveConstructionMoveOnlyElements) { - CompressedTuple<std::unique_ptr<std::string>> base( - absl::make_unique<std::string>("str")); - EXPECT_EQ(*base.get<0>(), "str"); - - CompressedTuple<std::unique_ptr<std::string>> copy(std::move(base)); - EXPECT_EQ(*copy.get<0>(), "str"); -} - -TEST(CompressedTupleTest, AnyElements) { - any a(std::string("str")); - CompressedTuple<any, any&> x(any(5), a); - EXPECT_EQ(absl::any_cast<int>(x.get<0>()), 5); - EXPECT_EQ(absl::any_cast<std::string>(x.get<1>()), "str"); - - a = 0.5f; - EXPECT_EQ(absl::any_cast<float>(x.get<1>()), 0.5); -} - -TEST(CompressedTupleTest, Constexpr) { - struct NonTrivialStruct { - constexpr NonTrivialStruct() = default; - constexpr int value() const { return v; } - int v = 5; - }; - struct TrivialStruct { - TrivialStruct() = default; - constexpr int value() const { return v; } - int v; - }; - constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x( - 7, 1.25, CompressedTuple<int>(5), {}); - constexpr int x0 = x.get<0>(); - constexpr double x1 = x.get<1>(); - constexpr int x2 = x.get<2>().get<0>(); - constexpr CallType x3 = x.get<3>().value(); - - EXPECT_EQ(x0, 7); - EXPECT_EQ(x1, 1.25); - EXPECT_EQ(x2, 5); - EXPECT_EQ(x3, CallType::kConstRef); - -#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 - constexpr CompressedTuple<Empty<0>, TrivialStruct, int> trivial = {}; - constexpr CallType trivial0 = trivial.get<0>().value(); - constexpr int trivial1 = trivial.get<1>().value(); - constexpr int trivial2 = trivial.get<2>(); - - EXPECT_EQ(trivial0, CallType::kConstRef); - EXPECT_EQ(trivial1, 0); - EXPECT_EQ(trivial2, 0); -#endif - - constexpr CompressedTuple<Empty<0>, NonTrivialStruct, absl::optional<int>> - non_trivial = {}; - constexpr CallType non_trivial0 = non_trivial.get<0>().value(); - constexpr int non_trivial1 = non_trivial.get<1>().value(); - constexpr absl::optional<int> non_trivial2 = non_trivial.get<2>(); - - EXPECT_EQ(non_trivial0, CallType::kConstRef); - EXPECT_EQ(non_trivial1, 5); - EXPECT_EQ(non_trivial2, absl::nullopt); - - static constexpr char data[] = "DEF"; - constexpr CompressedTuple<const char*> z(data); - constexpr const char* z1 = z.get<0>(); - EXPECT_EQ(std::string(z1), std::string(data)); - -#if defined(__clang__) - // An apparent bug in earlier versions of gcc claims these are ambiguous. - constexpr int x2m = absl::move(x.get<2>()).get<0>(); - constexpr CallType x3m = absl::move(x).get<3>().value(); - EXPECT_EQ(x2m, 5); - EXPECT_EQ(x3m, CallType::kConstMove); -#endif -} - -#if defined(__clang__) || defined(__GNUC__) -TEST(CompressedTupleTest, EmptyFinalClass) { - struct S final { - int f() const { return 5; } - }; - CompressedTuple<S> x; - EXPECT_EQ(x.get<0>().f(), 5); -} -#endif - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/container_memory.h b/third_party/abseil_cpp/absl/container/internal/container_memory.h deleted file mode 100644 index e67529ecb6e6..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/container_memory.h +++ /dev/null @@ -1,460 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ -#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ - -#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. -// -// Note that many allocators don't honor alignment requirements above certain -// threshold (usually either alignof(std::max_align_t) or alignof(void*)). -// Allocate() doesn't apply alignment corrections. If the underlying allocator -// returns insufficiently alignment pointer, that's what you are going to get. -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>; - 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)); - assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 && - "allocator does not respect alignment"); - return p; -} - -// The pointer must have been previously obtained by calling -// Allocate<Alignment>(alloc, n). -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>; - 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), - (n + sizeof(M) - 1) / sizeof(M)); -} - -namespace memory_internal { - -// Constructs T into uninitialized storage pointed by `ptr` using the args -// specified in the tuple. -template <class Alloc, class T, class Tuple, size_t... I> -void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t, - absl::index_sequence<I...>) { - absl::allocator_traits<Alloc>::construct( - *alloc, ptr, std::get<I>(std::forward<Tuple>(t))...); -} - -template <class T, class F> -struct WithConstructedImplF { - template <class... Args> - decltype(std::declval<F>()(std::declval<T>())) operator()( - Args&&... args) const { - return std::forward<F>(f)(T(std::forward<Args>(args)...)); - } - F&& f; -}; - -template <class T, class Tuple, size_t... Is, class F> -decltype(std::declval<F>()(std::declval<T>())) WithConstructedImpl( - Tuple&& t, absl::index_sequence<Is...>, F&& f) { - return WithConstructedImplF<T, F>{std::forward<F>(f)}( - std::get<Is>(std::forward<Tuple>(t))...); -} - -template <class T, size_t... Is> -auto TupleRefImpl(T&& t, absl::index_sequence<Is...>) - -> decltype(std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...)) { - return std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...); -} - -// Returns a tuple of references to the elements of the input tuple. T must be a -// tuple. -template <class T> -auto TupleRef(T&& t) -> decltype( - TupleRefImpl(std::forward<T>(t), - absl::make_index_sequence< - std::tuple_size<typename std::decay<T>::type>::value>())) { - return TupleRefImpl( - std::forward<T>(t), - absl::make_index_sequence< - std::tuple_size<typename std::decay<T>::type>::value>()); -} - -template <class F, class K, class V> -decltype(std::declval<F>()(std::declval<const K&>(), std::piecewise_construct, - std::declval<std::tuple<K>>(), std::declval<V>())) -DecomposePairImpl(F&& f, std::pair<std::tuple<K>, V> p) { - const auto& key = std::get<0>(p.first); - return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first), - std::move(p.second)); -} - -} // namespace memory_internal - -// Constructs T into uninitialized storage pointed by `ptr` using the args -// specified in the tuple. -template <class Alloc, class T, class Tuple> -void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) { - memory_internal::ConstructFromTupleImpl( - alloc, ptr, std::forward<Tuple>(t), - absl::make_index_sequence< - std::tuple_size<typename std::decay<Tuple>::type>::value>()); -} - -// Constructs T using the args specified in the tuple and calls F with the -// constructed value. -template <class T, class Tuple, class F> -decltype(std::declval<F>()(std::declval<T>())) WithConstructed( - Tuple&& t, F&& f) { - return memory_internal::WithConstructedImpl<T>( - std::forward<Tuple>(t), - absl::make_index_sequence< - std::tuple_size<typename std::decay<Tuple>::type>::value>(), - std::forward<F>(f)); -} - -// Given arguments of an std::pair's consructor, PairArgs() returns a pair of -// tuples with references to the passed arguments. The tuples contain -// constructor arguments for the first and the second elements of the pair. -// -// The following two snippets are equivalent. -// -// 1. std::pair<F, S> p(args...); -// -// 2. auto a = PairArgs(args...); -// std::pair<F, S> p(std::piecewise_construct, -// std::move(p.first), std::move(p.second)); -inline std::pair<std::tuple<>, std::tuple<>> PairArgs() { return {}; } -template <class F, class S> -std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(F&& f, S&& s) { - return {std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)), - std::forward_as_tuple(std::forward<S>(s))}; -} -template <class F, class S> -std::pair<std::tuple<const F&>, std::tuple<const S&>> PairArgs( - const std::pair<F, S>& p) { - return PairArgs(p.first, p.second); -} -template <class F, class S> -std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(std::pair<F, S>&& p) { - return PairArgs(std::forward<F>(p.first), std::forward<S>(p.second)); -} -template <class F, class S> -auto PairArgs(std::piecewise_construct_t, F&& f, S&& s) - -> decltype(std::make_pair(memory_internal::TupleRef(std::forward<F>(f)), - memory_internal::TupleRef(std::forward<S>(s)))) { - return std::make_pair(memory_internal::TupleRef(std::forward<F>(f)), - memory_internal::TupleRef(std::forward<S>(s))); -} - -// A helper function for implementing apply() in map policies. -template <class F, class... Args> -auto DecomposePair(F&& f, Args&&... args) - -> decltype(memory_internal::DecomposePairImpl( - std::forward<F>(f), PairArgs(std::forward<Args>(args)...))) { - return memory_internal::DecomposePairImpl( - std::forward<F>(f), PairArgs(std::forward<Args>(args)...)); -} - -// A helper function for implementing apply() in set policies. -template <class F, class Arg> -decltype(std::declval<F>()(std::declval<const Arg&>(), std::declval<Arg>())) -DecomposeValue(F&& f, Arg&& arg) { - const auto& key = arg; - return std::forward<F>(f)(key, std::forward<Arg>(arg)); -} - -// Helper functions for asan and msan. -inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - ASAN_POISON_MEMORY_REGION(m, s); -#endif -#ifdef ABSL_HAVE_MEMORY_SANITIZER - __msan_poison(m, s); -#endif - (void)m; - (void)s; -} - -inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) { -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(m, s); -#endif -#ifdef ABSL_HAVE_MEMORY_SANITIZER - __msan_unpoison(m, s); -#endif - (void)m; - (void)s; -} - -template <typename T> -inline void SanitizerPoisonObject(const T* object) { - SanitizerPoisonMemoryRegion(object, sizeof(T)); -} - -template <typename T> -inline void SanitizerUnpoisonObject(const T* object) { - SanitizerUnpoisonMemoryRegion(object, sizeof(T)); -} - -namespace memory_internal { - -// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and -// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and -// offsetof(Pair, second) respectively. Otherwise they are -1. -// -// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout -// 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); -}; - -template <class Pair> -struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type> { - static constexpr size_t kFirst = offsetof(Pair, first); - static constexpr size_t kSecond = offsetof(Pair, second); -}; - -template <class K, class V> -struct IsLayoutCompatible { - private: - struct Pair { - K first; - V second; - }; - - // Is P layout-compatible with Pair? - template <class P> - static constexpr bool LayoutCompatible() { - return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) && - alignof(P) == alignof(Pair) && - memory_internal::OffsetOf<P>::kFirst == - memory_internal::OffsetOf<Pair>::kFirst && - memory_internal::OffsetOf<P>::kSecond == - memory_internal::OffsetOf<Pair>::kSecond; - } - - public: - // Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are, - // then it is safe to store them in a union and read from either. - static constexpr bool value = std::is_standard_layout<K>() && - std::is_standard_layout<Pair>() && - memory_internal::OffsetOf<Pair>::kFirst == 0 && - LayoutCompatible<std::pair<K, V>>() && - LayoutCompatible<std::pair<const K, V>>(); -}; - -} // namespace memory_internal - -// The internal storage type for key-value containers like flat_hash_map. -// -// It is convenient for the value_type of a flat_hash_map<K, V> to be -// pair<const K, V>; the "const K" prevents accidental modification of the key -// when dealing with the reference returned from find() and similar methods. -// However, this creates other problems; we want to be able to emplace(K, V) -// efficiently with move operations, and similarly be able to move a -// pair<K, V> in insert(). -// -// The solution is this union, which aliases the const and non-const versions -// of the pair. This also allows flat_hash_map<const K, V> to work, even though -// that has the same efficiency issues with move in emplace() and insert() - -// but people do it anyway. -// -// If kMutableKeys is false, only the value member can be accessed. -// -// If kMutableKeys is true, key can be accessed through all slots while value -// and mutable_value must be accessed only via INITIALIZED slots. Slots are -// created and destroyed via mutable_value so that the key can be moved later. -// -// Accessing one of the union fields while the other is active is safe as -// long as they are layout-compatible, which is guaranteed by the definition of -// kMutableKeys. For C++11, the relevant section of the standard is -// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19) -template <class K, class V> -union map_slot_type { - map_slot_type() {} - ~map_slot_type() = delete; - using value_type = std::pair<const K, V>; - using mutable_value_type = - std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>; - - value_type value; - mutable_value_type mutable_value; - absl::remove_const_t<K> key; -}; - -template <class K, class V> -struct map_slot_policy { - using slot_type = map_slot_type<K, V>; - using value_type = std::pair<const K, V>; - using mutable_value_type = std::pair<K, V>; - - private: - static void emplace(slot_type* slot) { - // The construction of union doesn't do anything at runtime but it allows us - // to access its members without violating aliasing rules. - new (slot) slot_type; - } - // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one - // or the other via slot_type. We are also free to access the key via - // slot_type::key in this case. - using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>; - - public: - static value_type& element(slot_type* slot) { return slot->value; } - static const value_type& element(const slot_type* slot) { - 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; - } - - template <class Allocator, class... Args> - static void construct(Allocator* alloc, slot_type* slot, Args&&... args) { - emplace(slot); - if (kMutableKeys::value) { - absl::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value, - std::forward<Args>(args)...); - } else { - absl::allocator_traits<Allocator>::construct(*alloc, &slot->value, - std::forward<Args>(args)...); - } - } - - // Construct this slot by moving from another slot. - template <class Allocator> - static void construct(Allocator* alloc, slot_type* slot, slot_type* other) { - emplace(slot); - if (kMutableKeys::value) { - absl::allocator_traits<Allocator>::construct( - *alloc, &slot->mutable_value, std::move(other->mutable_value)); - } else { - absl::allocator_traits<Allocator>::construct(*alloc, &slot->value, - std::move(other->value)); - } - } - - template <class Allocator> - static void destroy(Allocator* alloc, slot_type* slot) { - if (kMutableKeys::value) { - absl::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value); - } else { - absl::allocator_traits<Allocator>::destroy(*alloc, &slot->value); - } - } - - template <class Allocator> - static void transfer(Allocator* alloc, slot_type* new_slot, - slot_type* old_slot) { - emplace(new_slot); - if (kMutableKeys::value) { - absl::allocator_traits<Allocator>::construct( - *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value)); - } else { - absl::allocator_traits<Allocator>::construct(*alloc, &new_slot->value, - std::move(old_slot->value)); - } - destroy(alloc, old_slot); - } - - template <class Allocator> - static void swap(Allocator* alloc, slot_type* a, slot_type* b) { - if (kMutableKeys::value) { - using std::swap; - swap(a->mutable_value, b->mutable_value); - } else { - value_type tmp = std::move(a->value); - absl::allocator_traits<Allocator>::destroy(*alloc, &a->value); - absl::allocator_traits<Allocator>::construct(*alloc, &a->value, - std::move(b->value)); - absl::allocator_traits<Allocator>::destroy(*alloc, &b->value); - absl::allocator_traits<Allocator>::construct(*alloc, &b->value, - std::move(tmp)); - } - } - - template <class Allocator> - static void move(Allocator* alloc, slot_type* src, slot_type* dest) { - if (kMutableKeys::value) { - dest->mutable_value = std::move(src->mutable_value); - } else { - absl::allocator_traits<Allocator>::destroy(*alloc, &dest->value); - absl::allocator_traits<Allocator>::construct(*alloc, &dest->value, - std::move(src->value)); - } - } -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ 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 deleted file mode 100644 index 6a7fcd29ba90..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/container_memory_test.cc +++ /dev/null @@ -1,256 +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/container_memory.h" - -#include <cstdint> -#include <tuple> -#include <typeindex> -#include <typeinfo> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::absl::test_internal::CopyableMovableInstance; -using ::absl::test_internal::InstanceTracker; -using ::testing::_; -using ::testing::ElementsAre; -using ::testing::Gt; -using ::testing::Pair; - -TEST(Memory, AlignmentLargerThanBase) { - std::allocator<int8_t> alloc; - void* mem = Allocate<2>(&alloc, 3); - EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2); - memcpy(mem, "abc", 3); - Deallocate<2>(&alloc, mem, 3); -} - -TEST(Memory, AlignmentSmallerThanBase) { - std::allocator<int64_t> alloc; - void* mem = Allocate<2>(&alloc, 3); - EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2); - memcpy(mem, "abc", 3); - 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>; - - public: - Fixture() { ptr_ = std::allocator_traits<Alloc>::allocate(*alloc(), 1); } - ~Fixture() override { - std::allocator_traits<Alloc>::destroy(*alloc(), ptr_); - std::allocator_traits<Alloc>::deallocate(*alloc(), ptr_, 1); - } - std::string* ptr() { return ptr_; } - Alloc* alloc() { return &alloc_; } - - private: - Alloc alloc_; - std::string* ptr_; -}; - -TEST_F(Fixture, ConstructNoArgs) { - ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple()); - EXPECT_EQ(*ptr(), ""); -} - -TEST_F(Fixture, ConstructOneArg) { - ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple("abcde")); - EXPECT_EQ(*ptr(), "abcde"); -} - -TEST_F(Fixture, ConstructTwoArg) { - ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple(5, 'a')); - EXPECT_EQ(*ptr(), "aaaaa"); -} - -TEST(PairArgs, NoArgs) { - EXPECT_THAT(PairArgs(), - Pair(std::forward_as_tuple(), std::forward_as_tuple())); -} - -TEST(PairArgs, TwoArgs) { - EXPECT_EQ( - std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), - PairArgs(1, 'A')); -} - -TEST(PairArgs, Pair) { - EXPECT_EQ( - std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), - PairArgs(std::make_pair(1, 'A'))); -} - -TEST(PairArgs, Piecewise) { - EXPECT_EQ( - std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), - PairArgs(std::piecewise_construct, std::forward_as_tuple(1), - std::forward_as_tuple('A'))); -} - -TEST(WithConstructed, Simple) { - EXPECT_EQ(1, WithConstructed<absl::string_view>( - std::make_tuple(std::string("a")), - [](absl::string_view str) { return str.size(); })); -} - -template <class F, class Arg> -decltype(DecomposeValue(std::declval<F>(), std::declval<Arg>())) -DecomposeValueImpl(int, F&& f, Arg&& arg) { - return DecomposeValue(std::forward<F>(f), std::forward<Arg>(arg)); -} - -template <class F, class Arg> -const char* DecomposeValueImpl(char, F&& f, Arg&& arg) { - return "not decomposable"; -} - -template <class F, class Arg> -decltype(DecomposeValueImpl(0, std::declval<F>(), std::declval<Arg>())) -TryDecomposeValue(F&& f, Arg&& arg) { - return DecomposeValueImpl(0, std::forward<F>(f), std::forward<Arg>(arg)); -} - -TEST(DecomposeValue, Decomposable) { - auto f = [](const int& x, int&& y) { - EXPECT_EQ(&x, &y); - EXPECT_EQ(42, x); - return 'A'; - }; - EXPECT_EQ('A', TryDecomposeValue(f, 42)); -} - -TEST(DecomposeValue, NotDecomposable) { - auto f = [](void*) { - ADD_FAILURE() << "Must not be called"; - return 'A'; - }; - EXPECT_STREQ("not decomposable", TryDecomposeValue(f, 42)); -} - -template <class F, class... Args> -decltype(DecomposePair(std::declval<F>(), std::declval<Args>()...)) -DecomposePairImpl(int, F&& f, Args&&... args) { - return DecomposePair(std::forward<F>(f), std::forward<Args>(args)...); -} - -template <class F, class... Args> -const char* DecomposePairImpl(char, F&& f, Args&&... args) { - return "not decomposable"; -} - -template <class F, class... Args> -decltype(DecomposePairImpl(0, std::declval<F>(), std::declval<Args>()...)) -TryDecomposePair(F&& f, Args&&... args) { - return DecomposePairImpl(0, std::forward<F>(f), std::forward<Args>(args)...); -} - -TEST(DecomposePair, Decomposable) { - 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); - EXPECT_EQ(0.5, std::get<0>(v)); - return 'A'; - }; - EXPECT_EQ('A', TryDecomposePair(f, 42, 0.5)); - EXPECT_EQ('A', TryDecomposePair(f, std::make_pair(42, 0.5))); - EXPECT_EQ('A', TryDecomposePair(f, std::piecewise_construct, - std::make_tuple(42), std::make_tuple(0.5))); -} - -TEST(DecomposePair, NotDecomposable) { - auto f = [](...) { - ADD_FAILURE() << "Must not be called"; - return 'A'; - }; - EXPECT_STREQ("not decomposable", - TryDecomposePair(f)); - EXPECT_STREQ("not decomposable", - TryDecomposePair(f, std::piecewise_construct, std::make_tuple(), - std::make_tuple(0.5))); -} - -TEST(MapSlotPolicy, ConstKeyAndValue) { - using slot_policy = map_slot_policy<const CopyableMovableInstance, - const CopyableMovableInstance>; - using slot_type = typename slot_policy::slot_type; - - union Slots { - Slots() {} - ~Slots() {} - slot_type slots[100]; - } slots; - - std::allocator< - std::pair<const CopyableMovableInstance, const CopyableMovableInstance>> - alloc; - InstanceTracker tracker; - slot_policy::construct(&alloc, &slots.slots[0], CopyableMovableInstance(1), - CopyableMovableInstance(1)); - for (int i = 0; i < 99; ++i) { - slot_policy::transfer(&alloc, &slots.slots[i + 1], &slots.slots[i]); - } - slot_policy::destroy(&alloc, &slots.slots[99]); - - EXPECT_EQ(tracker.copies(), 0); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/counting_allocator.h b/third_party/abseil_cpp/absl/container/internal/counting_allocator.h deleted file mode 100644 index 927cf0825579..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/counting_allocator.h +++ /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. - -#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ -#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ - -#include <cstdint> -#include <memory> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// This is a stateful allocator, but the state lives outside of the -// allocator (in whatever test is using the allocator). This is odd -// but helps in tests where the allocator is propagated into nested -// containers - that chain of allocators uses the same state and is -// thus easier to query for aggregate allocation information. -template <typename T> -class CountingAllocator { - public: - using Allocator = std::allocator<T>; - using AllocatorTraits = std::allocator_traits<Allocator>; - using value_type = typename AllocatorTraits::value_type; - using pointer = typename AllocatorTraits::pointer; - using const_pointer = typename AllocatorTraits::const_pointer; - using size_type = typename AllocatorTraits::size_type; - using difference_type = typename AllocatorTraits::difference_type; - - CountingAllocator() = default; - explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {} - CountingAllocator(int64_t* bytes_used, int64_t* instance_count) - : bytes_used_(bytes_used), instance_count_(instance_count) {} - - template <typename U> - CountingAllocator(const CountingAllocator<U>& x) - : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {} - - pointer allocate( - size_type n, - typename AllocatorTraits::const_void_pointer hint = nullptr) { - Allocator allocator; - pointer ptr = AllocatorTraits::allocate(allocator, n, hint); - if (bytes_used_ != nullptr) { - *bytes_used_ += n * sizeof(T); - } - return ptr; - } - - void deallocate(pointer p, size_type n) { - Allocator allocator; - AllocatorTraits::deallocate(allocator, p, n); - if (bytes_used_ != nullptr) { - *bytes_used_ -= n * sizeof(T); - } - } - - template <typename U, typename... Args> - void construct(U* p, Args&&... args) { - Allocator allocator; - AllocatorTraits::construct(allocator, p, std::forward<Args>(args)...); - if (instance_count_ != nullptr) { - *instance_count_ += 1; - } - } - - template <typename U> - void destroy(U* p) { - Allocator allocator; - AllocatorTraits::destroy(allocator, p); - if (instance_count_ != nullptr) { - *instance_count_ -= 1; - } - } - - template <typename U> - class rebind { - public: - using other = CountingAllocator<U>; - }; - - friend bool operator==(const CountingAllocator& a, - const CountingAllocator& b) { - return a.bytes_used_ == b.bytes_used_ && - a.instance_count_ == b.instance_count_; - } - - friend bool operator!=(const CountingAllocator& a, - const CountingAllocator& b) { - return !(a == b); - } - - int64_t* bytes_used_ = nullptr; - int64_t* instance_count_ = nullptr; -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hash_function_defaults.h b/third_party/abseil_cpp/absl/container/internal/hash_function_defaults.h deleted file mode 100644 index 0683422ad89b..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_function_defaults.h +++ /dev/null @@ -1,161 +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. -// -// Define the default Hash and Eq functions for SwissTable containers. -// -// std::hash<T> and std::equal_to<T> are not appropriate hash and equal -// functions for SwissTable containers. There are two reasons for this. -// -// SwissTable containers are power of 2 sized containers: -// -// This means they use the lower bits of the hash value to find the slot for -// each entry. The typical hash function for integral types is the identity. -// This is a very weak hash function for SwissTable and any power of 2 sized -// hashtable implementation which will lead to excessive collisions. For -// SwissTable we use murmur3 style mixing to reduce collisions to a minimum. -// -// SwissTable containers support heterogeneous lookup: -// -// In order to make heterogeneous lookup work, hash and equal functions must be -// polymorphic. At the same time they have to satisfy the same requirements the -// C++ standard imposes on hash functions and equality operators. That is: -// -// if hash_default_eq<T>(a, b) returns true for any a and b of type T, then -// hash_default_hash<T>(a) must equal hash_default_hash<T>(b) -// -// For SwissTable containers this requirement is relaxed to allow a and b of -// any and possibly different types. Note that like the standard the hash and -// equal functions are still bound to T. This is important because some type U -// can be hashed by/tested for equality differently depending on T. A notable -// example is `const char*`. `const char*` is treated as a c-style string when -// the hash function is hash<std::string> but as a pointer when the hash -// function is hash<void*>. -// -#ifndef ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_ -#define ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_ - -#include <stdint.h> -#include <cstddef> -#include <memory> -#include <string> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/hash/hash.h" -#include "absl/strings/cord.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// The hash of an object of type T is computed by using absl::Hash. -template <class T, class E = void> -struct HashEq { - using Hash = absl::Hash<T>; - using Eq = std::equal_to<T>; -}; - -struct StringHash { - using is_transparent = void; - - size_t operator()(absl::string_view v) const { - return absl::Hash<absl::string_view>{}(v); - } - size_t operator()(const absl::Cord& v) const { - return absl::Hash<absl::Cord>{}(v); - } -}; - -// Supports heterogeneous lookup for string-like elements. -struct StringHashEq { - using Hash = StringHash; - struct Eq { - 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; - } - }; -}; - -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> -struct HashEq<T*> { - struct Hash { - using is_transparent = void; - template <class U> - size_t operator()(const U& ptr) const { - return absl::Hash<const T*>{}(HashEq::ToPtr(ptr)); - } - }; - struct Eq { - using is_transparent = void; - template <class A, class B> - bool operator()(const A& a, const B& b) const { - return HashEq::ToPtr(a) == HashEq::ToPtr(b); - } - }; - - private: - static const T* ToPtr(const T* ptr) { return ptr; } - template <class U, class D> - static const T* ToPtr(const std::unique_ptr<U, D>& ptr) { - return ptr.get(); - } - template <class U> - static const T* ToPtr(const std::shared_ptr<U>& ptr) { - return ptr.get(); - } -}; - -template <class T, class D> -struct HashEq<std::unique_ptr<T, D>> : HashEq<T*> {}; -template <class T> -struct HashEq<std::shared_ptr<T>> : HashEq<T*> {}; - -// This header's visibility is restricted. If you need to access the default -// hasher please use the container's ::hasher alias instead. -// -// Example: typename Hash = typename absl::flat_hash_map<K, V>::hasher -template <class T> -using hash_default_hash = typename container_internal::HashEq<T>::Hash; - -// This header's visibility is restricted. If you need to access the default -// key equal please use the container's ::key_equal alias instead. -// -// Example: typename Eq = typename absl::flat_hash_map<K, V, Hash>::key_equal -template <class T> -using hash_default_eq = typename container_internal::HashEq<T>::Eq; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_ diff --git a/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 deleted file mode 100644 index 59576b8edebc..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_function_defaults_test.cc +++ /dev/null @@ -1,383 +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/hash_function_defaults.h" - -#include <functional> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/random/random.h" -#include "absl/strings/cord.h" -#include "absl/strings/cord_test_helpers.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::testing::Types; - -TEST(Eq, Int32) { - hash_default_eq<int32_t> eq; - EXPECT_TRUE(eq(1, 1u)); - EXPECT_TRUE(eq(1, char{1})); - EXPECT_TRUE(eq(1, true)); - EXPECT_TRUE(eq(1, double{1.1})); - EXPECT_FALSE(eq(1, char{2})); - EXPECT_FALSE(eq(1, 2u)); - EXPECT_FALSE(eq(1, false)); - EXPECT_FALSE(eq(1, 2.)); -} - -TEST(Hash, Int32) { - hash_default_hash<int32_t> hash; - auto h = hash(1); - EXPECT_EQ(h, hash(1u)); - EXPECT_EQ(h, hash(char{1})); - EXPECT_EQ(h, hash(true)); - EXPECT_EQ(h, hash(double{1.1})); - EXPECT_NE(h, hash(2u)); - EXPECT_NE(h, hash(char{2})); - EXPECT_NE(h, hash(false)); - EXPECT_NE(h, hash(2.)); -} - -enum class MyEnum { A, B, C, D }; - -TEST(Eq, Enum) { - hash_default_eq<MyEnum> eq; - EXPECT_TRUE(eq(MyEnum::A, MyEnum::A)); - EXPECT_FALSE(eq(MyEnum::A, MyEnum::B)); -} - -TEST(Hash, Enum) { - hash_default_hash<MyEnum> hash; - - for (MyEnum e : {MyEnum::A, MyEnum::B, MyEnum::C}) { - auto h = hash(e); - EXPECT_EQ(h, hash_default_hash<int>{}(static_cast<int>(e))); - EXPECT_NE(h, hash(MyEnum::D)); - } -} - -using StringTypes = ::testing::Types<std::string, absl::string_view>; - -template <class T> -struct EqString : ::testing::Test { - hash_default_eq<T> key_eq; -}; - -TYPED_TEST_SUITE(EqString, StringTypes); - -template <class T> -struct HashString : ::testing::Test { - hash_default_hash<T> hasher; -}; - -TYPED_TEST_SUITE(HashString, StringTypes); - -TYPED_TEST(EqString, Works) { - auto eq = this->key_eq; - EXPECT_TRUE(eq("a", "a")); - EXPECT_TRUE(eq("a", absl::string_view("a"))); - EXPECT_TRUE(eq("a", std::string("a"))); - EXPECT_FALSE(eq("a", "b")); - EXPECT_FALSE(eq("a", absl::string_view("b"))); - EXPECT_FALSE(eq("a", std::string("b"))); -} - -TYPED_TEST(HashString, Works) { - auto hash = this->hasher; - auto h = hash("a"); - EXPECT_EQ(h, hash(absl::string_view("a"))); - EXPECT_EQ(h, hash(std::string("a"))); - EXPECT_NE(h, hash(absl::string_view("b"))); - EXPECT_NE(h, hash(std::string("b"))); -} - -struct NoDeleter { - template <class T> - void operator()(const T* ptr) const {} -}; - -using PointerTypes = - ::testing::Types<const int*, int*, std::unique_ptr<const int>, - std::unique_ptr<const int, NoDeleter>, - std::unique_ptr<int>, std::unique_ptr<int, NoDeleter>, - std::shared_ptr<const int>, std::shared_ptr<int>>; - -template <class T> -struct EqPointer : ::testing::Test { - hash_default_eq<T> key_eq; -}; - -TYPED_TEST_SUITE(EqPointer, PointerTypes); - -template <class T> -struct HashPointer : ::testing::Test { - hash_default_hash<T> hasher; -}; - -TYPED_TEST_SUITE(HashPointer, PointerTypes); - -TYPED_TEST(EqPointer, Works) { - int dummy; - auto eq = this->key_eq; - auto sptr = std::make_shared<int>(); - std::shared_ptr<const int> csptr = sptr; - int* ptr = sptr.get(); - const int* cptr = ptr; - std::unique_ptr<int, NoDeleter> uptr(ptr); - std::unique_ptr<const int, NoDeleter> cuptr(ptr); - - EXPECT_TRUE(eq(ptr, cptr)); - EXPECT_TRUE(eq(ptr, sptr)); - EXPECT_TRUE(eq(ptr, uptr)); - EXPECT_TRUE(eq(ptr, csptr)); - EXPECT_TRUE(eq(ptr, cuptr)); - EXPECT_FALSE(eq(&dummy, cptr)); - EXPECT_FALSE(eq(&dummy, sptr)); - EXPECT_FALSE(eq(&dummy, uptr)); - EXPECT_FALSE(eq(&dummy, csptr)); - EXPECT_FALSE(eq(&dummy, cuptr)); -} - -TEST(Hash, DerivedAndBase) { - struct Base {}; - struct Derived : Base {}; - - hash_default_hash<Base*> hasher; - - Base base; - Derived derived; - EXPECT_NE(hasher(&base), hasher(&derived)); - EXPECT_EQ(hasher(static_cast<Base*>(&derived)), hasher(&derived)); - - auto dp = std::make_shared<Derived>(); - EXPECT_EQ(hasher(static_cast<Base*>(dp.get())), hasher(dp)); -} - -TEST(Hash, FunctionPointer) { - using Func = int (*)(); - hash_default_hash<Func> hasher; - hash_default_eq<Func> eq; - - Func p1 = [] { return 1; }, p2 = [] { return 2; }; - EXPECT_EQ(hasher(p1), hasher(p1)); - EXPECT_TRUE(eq(p1, p1)); - - EXPECT_NE(hasher(p1), hasher(p2)); - EXPECT_FALSE(eq(p1, p2)); -} - -TYPED_TEST(HashPointer, Works) { - int dummy; - auto hash = this->hasher; - auto sptr = std::make_shared<int>(); - std::shared_ptr<const int> csptr = sptr; - int* ptr = sptr.get(); - const int* cptr = ptr; - std::unique_ptr<int, NoDeleter> uptr(ptr); - std::unique_ptr<const int, NoDeleter> cuptr(ptr); - - EXPECT_EQ(hash(ptr), hash(cptr)); - EXPECT_EQ(hash(ptr), hash(sptr)); - EXPECT_EQ(hash(ptr), hash(uptr)); - EXPECT_EQ(hash(ptr), hash(csptr)); - EXPECT_EQ(hash(ptr), hash(cuptr)); - EXPECT_NE(hash(&dummy), hash(cptr)); - EXPECT_NE(hash(&dummy), hash(sptr)); - EXPECT_NE(hash(&dummy), hash(uptr)); - EXPECT_NE(hash(&dummy), hash(csptr)); - 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). -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>, - std::pair<absl::string_view, const char*>>; -// clang-format on - -constexpr char kFirstString[] = "abc123"; -constexpr char kSecondString[] = "ijk456"; - -template <typename T> -struct StringLikeTest : public ::testing::Test { - typename T::first_type a1{kFirstString}; - typename T::second_type b1{kFirstString}; - typename T::first_type a2{kSecondString}; - typename T::second_type b2{kSecondString}; - hash_default_eq<typename T::first_type> eq; - hash_default_hash<typename T::first_type> hash; -}; - -TYPED_TEST_CASE_P(StringLikeTest); - -TYPED_TEST_P(StringLikeTest, Eq) { - EXPECT_TRUE(this->eq(this->a1, this->b1)); - EXPECT_TRUE(this->eq(this->b1, this->a1)); -} - -TYPED_TEST_P(StringLikeTest, NotEq) { - EXPECT_FALSE(this->eq(this->a1, this->b2)); - EXPECT_FALSE(this->eq(this->b2, this->a1)); -} - -TYPED_TEST_P(StringLikeTest, HashEq) { - EXPECT_EQ(this->hash(this->a1), this->hash(this->b1)); - EXPECT_EQ(this->hash(this->a2), this->hash(this->b2)); - // It would be a poor hash function which collides on these strings. - EXPECT_NE(this->hash(this->a1), this->hash(this->b2)); -} - -TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct); - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -enum Hash : size_t { - kStd = 0x1, // std::hash -#ifdef _MSC_VER - kExtension = kStd, // In MSVC, std::hash == ::hash -#else // _MSC_VER - kExtension = 0x2, // ::hash (GCC extension) -#endif // _MSC_VER -}; - -// H is a bitmask of Hash enumerations. -// Hashable<H> is hashable via all means specified in H. -template <int H> -struct Hashable { - static constexpr bool HashableBy(Hash h) { return h & H; } -}; - -namespace std { -template <int H> -struct hash<Hashable<H>> { - template <class E = Hashable<H>, - class = typename std::enable_if<E::HashableBy(kStd)>::type> - size_t operator()(E) const { - return kStd; - } -}; -} // namespace std - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -template <class T> -size_t Hash(const T& v) { - return hash_default_hash<T>()(v); -} - -TEST(Delegate, HashDispatch) { - EXPECT_EQ(Hash(kStd), Hash(Hashable<kStd>())); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 59cc5aac7ab8..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_generator_testing.cc +++ /dev/null @@ -1,76 +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/hash_generator_testing.h" - -#include <deque> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace hash_internal { -namespace { - -class RandomDeviceSeedSeq { - public: - using result_type = typename std::random_device::result_type; - - template <class Iterator> - void generate(Iterator start, Iterator end) { - while (start != end) { - *start = gen_(); - ++start; - } - } - - private: - std::random_device gen_; -}; - -} // namespace - -std::mt19937_64* GetSharedRng() { - static auto* rng = [] { - RandomDeviceSeedSeq seed_seq; - return new std::mt19937_64(seed_seq); - }(); - return rng; -} - -std::string Generator<std::string>::operator()() const { - // NOLINTNEXTLINE(runtime/int) - std::uniform_int_distribution<short> chars(0x20, 0x7E); - std::string res; - res.resize(32); - std::generate(res.begin(), res.end(), - [&]() { return chars(*GetSharedRng()); }); - return res; -} - -absl::string_view Generator<absl::string_view>::operator()() const { - static auto* arena = new std::deque<std::string>(); - // NOLINTNEXTLINE(runtime/int) - std::uniform_int_distribution<short> chars(0x20, 0x7E); - arena->emplace_back(); - auto& res = arena->back(); - res.resize(32); - std::generate(res.begin(), res.end(), - [&]() { return chars(*GetSharedRng()); }); - return res; -} - -} // namespace hash_internal -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 6869fe45e8c8..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_generator_testing.h +++ /dev/null @@ -1,161 +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 random values for testing. Specialized only for the few types we -// care about. - -#ifndef ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ -#define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ - -#include <stdint.h> - -#include <algorithm> -#include <iosfwd> -#include <random> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/container/internal/hash_policy_testing.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace hash_internal { -namespace generator_internal { - -template <class Container, class = void> -struct IsMap : std::false_type {}; - -template <class Map> -struct IsMap<Map, absl::void_t<typename Map::mapped_type>> : std::true_type {}; - -} // namespace generator_internal - -std::mt19937_64* GetSharedRng(); - -enum Enum { - kEnumEmpty, - kEnumDeleted, -}; - -enum class EnumClass : uint64_t { - kEmpty, - kDeleted, -}; - -inline std::ostream& operator<<(std::ostream& o, const EnumClass& ec) { - return o << static_cast<uint64_t>(ec); -} - -template <class T, class E = void> -struct Generator; - -template <class T> -struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> { - T operator()() const { - std::uniform_int_distribution<T> dist; - return dist(*GetSharedRng()); - } -}; - -template <> -struct Generator<Enum> { - Enum operator()() const { - std::uniform_int_distribution<typename std::underlying_type<Enum>::type> - dist; - while (true) { - auto variate = dist(*GetSharedRng()); - if (variate != kEnumEmpty && variate != kEnumDeleted) - return static_cast<Enum>(variate); - } - } -}; - -template <> -struct Generator<EnumClass> { - EnumClass operator()() const { - std::uniform_int_distribution< - typename std::underlying_type<EnumClass>::type> - dist; - while (true) { - EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng())); - if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted) - return static_cast<EnumClass>(variate); - } - } -}; - -template <> -struct Generator<std::string> { - std::string operator()() const; -}; - -template <> -struct Generator<absl::string_view> { - absl::string_view operator()() const; -}; - -template <> -struct Generator<NonStandardLayout> { - NonStandardLayout operator()() const { - return NonStandardLayout(Generator<std::string>()()); - } -}; - -template <class K, class V> -struct Generator<std::pair<K, V>> { - std::pair<K, V> operator()() const { - return std::pair<K, V>(Generator<typename std::decay<K>::type>()(), - Generator<typename std::decay<V>::type>()()); - } -}; - -template <class... Ts> -struct Generator<std::tuple<Ts...>> { - std::tuple<Ts...> operator()() const { - return std::tuple<Ts...>(Generator<typename std::decay<Ts>::type>()()...); - } -}; - -template <class T> -struct Generator<std::unique_ptr<T>> { - std::unique_ptr<T> operator()() const { - return absl::make_unique<T>(Generator<T>()()); - } -}; - -template <class U> -struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()), - decltype(std::declval<U&>().value())>> - : Generator<std::pair< - typename std::decay<decltype(std::declval<U&>().key())>::type, - typename std::decay<decltype(std::declval<U&>().value())>::type>> {}; - -template <class Container> -using GeneratedType = decltype( - std::declval<const Generator< - typename std::conditional<generator_internal::IsMap<Container>::value, - typename Container::value_type, - typename Container::key_type>::type>&>()()); - -} // namespace hash_internal -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hash_policy_testing.h b/third_party/abseil_cpp/absl/container/internal/hash_policy_testing.h deleted file mode 100644 index 01c40d2e5cff..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_policy_testing.h +++ /dev/null @@ -1,184 +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. -// -// Utilities to help tests verify that hash tables properly handle stateful -// allocators and hash functions. - -#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ -#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ - -#include <cstdlib> -#include <limits> -#include <memory> -#include <ostream> -#include <type_traits> -#include <utility> -#include <vector> - -#include "absl/hash/hash.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace hash_testing_internal { - -template <class Derived> -struct WithId { - WithId() : id_(next_id<Derived>()) {} - WithId(const WithId& that) : id_(that.id_) {} - WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; } - WithId& operator=(const WithId& that) { - id_ = that.id_; - return *this; - } - WithId& operator=(WithId&& that) { - id_ = that.id_; - that.id_ = 0; - return *this; - } - - size_t id() const { return id_; } - - friend bool operator==(const WithId& a, const WithId& b) { - return a.id_ == b.id_; - } - friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); } - - protected: - explicit WithId(size_t id) : id_(id) {} - - private: - size_t id_; - - template <class T> - static size_t next_id() { - // 0 is reserved for moved from state. - static size_t gId = 1; - return gId++; - } -}; - -} // namespace hash_testing_internal - -struct NonStandardLayout { - NonStandardLayout() {} - explicit NonStandardLayout(std::string s) : value(std::move(s)) {} - virtual ~NonStandardLayout() {} - - friend bool operator==(const NonStandardLayout& a, - const NonStandardLayout& b) { - return a.value == b.value; - } - friend bool operator!=(const NonStandardLayout& a, - const NonStandardLayout& b) { - return a.value != b.value; - } - - template <typename H> - friend H AbslHashValue(H h, const NonStandardLayout& v) { - return H::combine(std::move(h), v.value); - } - - std::string value; -}; - -struct StatefulTestingHash - : absl::container_internal::hash_testing_internal::WithId< - StatefulTestingHash> { - template <class T> - size_t operator()(const T& t) const { - return absl::Hash<T>{}(t); - } -}; - -struct StatefulTestingEqual - : absl::container_internal::hash_testing_internal::WithId< - StatefulTestingEqual> { - template <class T, class U> - bool operator()(const T& t, const U& u) const { - return t == u; - } -}; - -// It is expected that Alloc() == Alloc() for all allocators so we cannot use -// WithId base. We need to explicitly assign ids. -template <class T = int> -struct Alloc : std::allocator<T> { - using propagate_on_container_swap = std::true_type; - - // Using old paradigm for this to ensure compatibility. - explicit Alloc(size_t id = 0) : id_(id) {} - - Alloc(const Alloc&) = default; - Alloc& operator=(const Alloc&) = default; - - template <class U> - Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {} - - template <class U> - struct rebind { - using other = Alloc<U>; - }; - - size_t id() const { return id_; } - - friend bool operator==(const Alloc& a, const Alloc& b) { - return a.id_ == b.id_; - } - friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); } - - private: - size_t id_ = (std::numeric_limits<size_t>::max)(); -}; - -template <class Map> -auto items(const Map& m) -> std::vector< - std::pair<typename Map::key_type, typename Map::mapped_type>> { - using std::get; - std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res; - res.reserve(m.size()); - for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v)); - return res; -} - -template <class Set> -auto keys(const Set& s) - -> std::vector<typename std::decay<typename Set::key_type>::type> { - std::vector<typename std::decay<typename Set::key_type>::type> res; - res.reserve(s.size()); - for (const auto& v : s) res.emplace_back(v); - return res; -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -// ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions -// where the unordered containers are missing certain constructors that -// take allocator arguments. This test is defined ad-hoc for the platforms -// we care about (notably Crosstool 17) because libstdcxx's useless -// versioning scheme precludes a more principled solution. -// From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html) -// "the unordered associative containers in <unordered_map> and <unordered_set> -// meet the allocator-aware container requirements;" -#if (defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 ) || \ -( __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9 )) -#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0 -#else -#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1 -#endif - -#endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hash_policy_testing_test.cc b/third_party/abseil_cpp/absl/container/internal/hash_policy_testing_test.cc deleted file mode 100644 index f0b20fe345e2..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_policy_testing_test.cc +++ /dev/null @@ -1,45 +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/hash_policy_testing.h" - -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -TEST(_, Hash) { - StatefulTestingHash h1; - EXPECT_EQ(1, h1.id()); - StatefulTestingHash h2; - EXPECT_EQ(2, h2.id()); - StatefulTestingHash h1c(h1); - EXPECT_EQ(1, h1c.id()); - StatefulTestingHash h2m(std::move(h2)); - EXPECT_EQ(2, h2m.id()); - EXPECT_EQ(0, h2.id()); - StatefulTestingHash h3; - EXPECT_EQ(3, h3.id()); - h3 = StatefulTestingHash(); - EXPECT_EQ(4, h3.id()); - h3 = std::move(h1); - EXPECT_EQ(1, h3.id()); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 46c97b18a227..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_policy_traits.h +++ /dev/null @@ -1,208 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_ -#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_ - -#include <cstddef> -#include <memory> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// Defines how slots are initialized/destroyed/moved. -template <class Policy, class = void> -struct hash_policy_traits { - // The type of the keys stored in the hashtable. - using key_type = typename Policy::key_type; - - private: - struct ReturnKey { - // When C++17 is available, we can use std::launder to provide mutable - // access to the key for use in node handle. -#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 - template <class Key, - absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0> - static key_type& Impl(Key&& k, int) { - return *std::launder( - const_cast<key_type*>(std::addressof(std::forward<Key>(k)))); - } -#endif - - template <class Key> - static Key Impl(Key&& k, char) { - return std::forward<Key>(k); - } - - // When Key=T&, we forward the lvalue reference. - // When Key=T, we return by value to avoid a dangling reference. - // eg, for string_hash_map. - template <class Key, class... Args> - auto operator()(Key&& k, const Args&...) const - -> decltype(Impl(std::forward<Key>(k), 0)) { - return Impl(std::forward<Key>(k), 0); - } - }; - - template <class P = Policy, class = void> - struct ConstantIteratorsImpl : std::false_type {}; - - template <class P> - struct ConstantIteratorsImpl<P, absl::void_t<typename P::constant_iterators>> - : P::constant_iterators {}; - - public: - // The actual object stored in the hash table. - using slot_type = typename Policy::slot_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. - using init_type = typename Policy::init_type; - - using reference = decltype(Policy::element(std::declval<slot_type*>())); - using pointer = typename std::remove_reference<reference>::type*; - using value_type = typename std::remove_reference<reference>::type; - - // Policies can set this variable to tell raw_hash_set that all iterators - // should be constant, even `iterator`. This is useful for set-like - // containers. - // Defaults to false if not provided by the policy. - using constant_iterators = ConstantIteratorsImpl<>; - - // PRECONDITION: `slot` is UNINITIALIZED - // POSTCONDITION: `slot` is INITIALIZED - template <class Alloc, class... Args> - static void construct(Alloc* alloc, slot_type* slot, Args&&... args) { - Policy::construct(alloc, slot, std::forward<Args>(args)...); - } - - // PRECONDITION: `slot` is INITIALIZED - // POSTCONDITION: `slot` is UNINITIALIZED - template <class Alloc> - static void destroy(Alloc* alloc, slot_type* slot) { - Policy::destroy(alloc, slot); - } - - // Transfers the `old_slot` to `new_slot`. Any memory allocated by the - // allocator inside `old_slot` to `new_slot` can be transferred. - // - // OPTIONAL: defaults to: - // - // clone(new_slot, std::move(*old_slot)); - // destroy(old_slot); - // - // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED - // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is - // UNINITIALIZED - template <class Alloc> - static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) { - transfer_impl(alloc, new_slot, old_slot, 0); - } - - // PRECONDITION: `slot` is INITIALIZED - // POSTCONDITION: `slot` is INITIALIZED - template <class P = Policy> - static auto element(slot_type* slot) -> decltype(P::element(slot)) { - return P::element(slot); - } - - // Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`. - // - // If `slot` is nullptr, returns the constant amount of memory owned by any - // full slot or -1 if slots own variable amounts of memory. - // - // PRECONDITION: `slot` is INITIALIZED or nullptr - template <class P = Policy> - static size_t space_used(const slot_type* slot) { - return P::space_used(slot); - } - - // Provides generalized access to the key for elements, both for elements in - // the table and for elements that have not yet been inserted (or even - // constructed). We would like an API that allows us to say: `key(args...)` - // but we cannot do that for all cases, so we use this more general API that - // can be used for many things, including the following: - // - // - Given an element in a table, get its key. - // - Given an element initializer, get its key. - // - Given `emplace()` arguments, get the element key. - // - // Implementations of this must adhere to a very strict technical - // specification around aliasing and consuming arguments: - // - // Let `value_type` be the result type of `element()` without ref- and - // cv-qualifiers. The first argument is a functor, the rest are constructor - // arguments for `value_type`. Returns `std::forward<F>(f)(k, xs...)`, where - // `k` is the element key, and `xs...` are the new constructor arguments for - // `value_type`. It's allowed for `k` to alias `xs...`, and for both to alias - // `ts...`. The key won't be touched once `xs...` are used to construct an - // element; `ts...` won't be touched at all, which allows `apply()` to consume - // any rvalues among them. - // - // If `value_type` is constructible from `Ts&&...`, `Policy::apply()` must not - // trigger a hard compile error unless it originates from `f`. In other words, - // `Policy::apply()` must be SFINAE-friendly. If `value_type` is not - // constructible from `Ts&&...`, either SFINAE or a hard compile error is OK. - // - // If `Ts...` is `[cv] value_type[&]` or `[cv] init_type[&]`, - // `Policy::apply()` must work. A compile error is not allowed, SFINAE or not. - template <class F, class... Ts, class P = Policy> - static auto apply(F&& f, Ts&&... ts) - -> decltype(P::apply(std::forward<F>(f), std::forward<Ts>(ts)...)) { - return P::apply(std::forward<F>(f), std::forward<Ts>(ts)...); - } - - // Returns the "key" portion of the slot. - // Used for node handle manipulation. - template <class P = Policy> - static auto mutable_key(slot_type* slot) - -> decltype(P::apply(ReturnKey(), element(slot))) { - return P::apply(ReturnKey(), element(slot)); - } - - // Returns the "value" (as opposed to the "key") portion of the element. Used - // by maps to implement `operator[]`, `at()` and `insert_or_assign()`. - template <class T, class P = Policy> - static auto value(T* elem) -> decltype(P::value(elem)) { - return P::value(elem); - } - - private: - // Use auto -> decltype as an enabler. - template <class Alloc, class P = Policy> - static auto transfer_impl(Alloc* alloc, slot_type* new_slot, - slot_type* old_slot, int) - -> decltype((void)P::transfer(alloc, new_slot, old_slot)) { - P::transfer(alloc, new_slot, old_slot); - } - template <class Alloc> - static void transfer_impl(Alloc* alloc, slot_type* new_slot, - slot_type* old_slot, char) { - construct(alloc, new_slot, std::move(element(old_slot))); - destroy(alloc, old_slot); - } -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hash_policy_traits_test.cc b/third_party/abseil_cpp/absl/container/internal/hash_policy_traits_test.cc deleted file mode 100644 index 6ef8b9e05fb1..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hash_policy_traits_test.cc +++ /dev/null @@ -1,144 +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/hash_policy_traits.h" - -#include <functional> -#include <memory> -#include <new> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::testing::MockFunction; -using ::testing::Return; -using ::testing::ReturnRef; - -using Alloc = std::allocator<int>; -using Slot = int; - -struct PolicyWithoutOptionalOps { - using slot_type = Slot; - using key_type = Slot; - using init_type = Slot; - - static std::function<void(void*, Slot*, Slot)> construct; - static std::function<void(void*, Slot*)> destroy; - - static std::function<Slot&(Slot*)> element; - static int apply(int v) { return apply_impl(v); } - static std::function<int(int)> apply_impl; - static std::function<Slot&(Slot*)> value; -}; - -std::function<void(void*, Slot*, Slot)> PolicyWithoutOptionalOps::construct; -std::function<void(void*, Slot*)> PolicyWithoutOptionalOps::destroy; - -std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::element; -std::function<int(int)> PolicyWithoutOptionalOps::apply_impl; -std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::value; - -struct PolicyWithOptionalOps : PolicyWithoutOptionalOps { - static std::function<void(void*, Slot*, Slot*)> transfer; -}; - -std::function<void(void*, Slot*, Slot*)> PolicyWithOptionalOps::transfer; - -struct Test : ::testing::Test { - Test() { - PolicyWithoutOptionalOps::construct = [&](void* a1, Slot* a2, Slot a3) { - construct.Call(a1, a2, std::move(a3)); - }; - PolicyWithoutOptionalOps::destroy = [&](void* a1, Slot* a2) { - destroy.Call(a1, a2); - }; - - PolicyWithoutOptionalOps::element = [&](Slot* a1) -> Slot& { - return element.Call(a1); - }; - PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int { - return apply.Call(a1); - }; - PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& { - return value.Call(a1); - }; - - PolicyWithOptionalOps::transfer = [&](void* a1, Slot* a2, Slot* a3) { - return transfer.Call(a1, a2, a3); - }; - } - - std::allocator<int> alloc; - int a = 53; - - MockFunction<void(void*, Slot*, Slot)> construct; - MockFunction<void(void*, Slot*)> destroy; - - MockFunction<Slot&(Slot*)> element; - MockFunction<int(int)> apply; - MockFunction<Slot&(Slot*)> value; - - MockFunction<void(void*, Slot*, Slot*)> transfer; -}; - -TEST_F(Test, construct) { - EXPECT_CALL(construct, Call(&alloc, &a, 53)); - hash_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53); -} - -TEST_F(Test, destroy) { - EXPECT_CALL(destroy, Call(&alloc, &a)); - hash_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a); -} - -TEST_F(Test, element) { - int b = 0; - EXPECT_CALL(element, Call(&a)).WillOnce(ReturnRef(b)); - EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::element(&a)); -} - -TEST_F(Test, apply) { - EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337)); - EXPECT_EQ(1337, (hash_policy_traits<PolicyWithoutOptionalOps>::apply(42))); -} - -TEST_F(Test, value) { - int b = 0; - EXPECT_CALL(value, Call(&a)).WillOnce(ReturnRef(b)); - EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::value(&a)); -} - -TEST_F(Test, without_transfer) { - int b = 42; - EXPECT_CALL(element, Call(&b)).WillOnce(::testing::ReturnRef(b)); - EXPECT_CALL(construct, Call(&alloc, &a, b)); - EXPECT_CALL(destroy, Call(&alloc, &b)); - hash_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b); -} - -TEST_F(Test, with_transfer) { - int b = 42; - EXPECT_CALL(transfer, Call(&alloc, &a, &b)); - hash_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/hashtable_debug.h b/third_party/abseil_cpp/absl/container/internal/hashtable_debug.h deleted file mode 100644 index 19d52121d688..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtable_debug.h +++ /dev/null @@ -1,110 +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. -// -// This library provides APIs to debug the probing behavior of hash tables. -// -// In general, the probing behavior is a black box for users and only the -// side effects can be measured in the form of performance differences. -// These APIs give a glimpse on the actual behavior of the probing algorithms in -// these hashtables given a specified hash function and a set of elements. -// -// The probe count distribution can be used to assess the quality of the hash -// function for that particular hash table. Note that a hash function that -// performs well in one hash table implementation does not necessarily performs -// well in a different one. -// -// This library supports std::unordered_{set,map}, dense_hash_{set,map} and -// absl::{flat,node,string}_hash_{set,map}. - -#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_ -#define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_ - -#include <cstddef> -#include <algorithm> -#include <type_traits> -#include <vector> - -#include "absl/container/internal/hashtable_debug_hooks.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// Returns the number of probes required to lookup `key`. Returns 0 for a -// search with no collisions. Higher values mean more hash collisions occurred; -// however, the exact meaning of this number varies according to the container -// type. -template <typename C> -size_t GetHashtableDebugNumProbes( - const C& c, const typename C::key_type& key) { - return absl::container_internal::hashtable_debug_internal:: - HashtableDebugAccess<C>::GetNumProbes(c, key); -} - -// Gets a histogram of the number of probes for each elements in the container. -// The sum of all the values in the vector is equal to container.size(). -template <typename C> -std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) { - std::vector<size_t> v; - for (auto it = container.begin(); it != container.end(); ++it) { - size_t num_probes = GetHashtableDebugNumProbes( - container, - absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0)); - v.resize((std::max)(v.size(), num_probes + 1)); - v[num_probes]++; - } - return v; -} - -struct HashtableDebugProbeSummary { - size_t total_elements; - size_t total_num_probes; - double mean; -}; - -// Gets a summary of the probe count distribution for the elements in the -// container. -template <typename C> -HashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container) { - auto probes = GetHashtableDebugNumProbesHistogram(container); - HashtableDebugProbeSummary summary = {}; - for (size_t i = 0; i < probes.size(); ++i) { - summary.total_elements += probes[i]; - summary.total_num_probes += probes[i] * i; - } - summary.mean = 1.0 * summary.total_num_probes / summary.total_elements; - return summary; -} - -// Returns the number of bytes requested from the allocator by the container -// and not freed. -template <typename C> -size_t AllocatedByteSize(const C& c) { - return absl::container_internal::hashtable_debug_internal:: - HashtableDebugAccess<C>::AllocatedByteSize(c); -} - -// Returns a tight lower bound for AllocatedByteSize(c) where `c` is of type `C` -// and `c.size()` is equal to `num_elements`. -template <typename C> -size_t LowerBoundAllocatedByteSize(size_t num_elements) { - return absl::container_internal::hashtable_debug_internal:: - HashtableDebugAccess<C>::LowerBoundAllocatedByteSize(num_elements); -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hashtable_debug_hooks.h b/third_party/abseil_cpp/absl/container/internal/hashtable_debug_hooks.h deleted file mode 100644 index 3e9ea5954e0a..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtable_debug_hooks.h +++ /dev/null @@ -1,85 +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. -// -// Provides the internal API for hashtable_debug.h. - -#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_ -#define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_ - -#include <cstddef> - -#include <algorithm> -#include <type_traits> -#include <vector> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace hashtable_debug_internal { - -// If it is a map, call get<0>(). -using std::get; -template <typename T, typename = typename T::mapped_type> -auto GetKey(const typename T::value_type& pair, int) -> decltype(get<0>(pair)) { - return get<0>(pair); -} - -// If it is not a map, return the value directly. -template <typename T> -const typename T::key_type& GetKey(const typename T::key_type& key, char) { - return key; -} - -// Containers should specialize this to provide debug information for that -// container. -template <class Container, typename Enabler = void> -struct HashtableDebugAccess { - // Returns the number of probes required to find `key` in `c`. The "number of - // probes" is a concept that can vary by container. Implementations should - // return 0 when `key` was found in the minimum number of operations and - // should increment the result for each non-trivial operation required to find - // `key`. - // - // The default implementation uses the bucket api from the standard and thus - // works for `std::unordered_*` containers. - static size_t GetNumProbes(const Container& c, - const typename Container::key_type& key) { - if (!c.bucket_count()) return {}; - size_t num_probes = 0; - size_t bucket = c.bucket(key); - for (auto it = c.begin(bucket), e = c.end(bucket);; ++it, ++num_probes) { - if (it == e) return num_probes; - if (c.key_eq()(key, GetKey<Container>(*it, 0))) return num_probes; - } - } - - // Returns the number of bytes requested from the allocator by the container - // and not freed. - // - // static size_t AllocatedByteSize(const Container& c); - - // Returns a tight lower bound for AllocatedByteSize(c) where `c` is of type - // `Container` and `c.size()` is equal to `num_elements`. - // - // static size_t LowerBoundAllocatedByteSize(size_t num_elements); -}; - -} // namespace hashtable_debug_internal -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.cc b/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.cc deleted file mode 100644 index e4484fbb1b43..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.cc +++ /dev/null @@ -1,270 +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/hashtablez_sampler.h" - -#include <atomic> -#include <cassert> -#include <cmath> -#include <functional> -#include <limits> - -#include "absl/base/attributes.h" -#include "absl/base/internal/exponential_biased.h" -#include "absl/container/internal/have_sse.h" -#include "absl/debugging/stacktrace.h" -#include "absl/memory/memory.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -constexpr int HashtablezInfo::kMaxStackDepth; - -namespace { -ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{ - false -}; -ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10}; -ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20}; - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased - g_exponential_biased_generator; -#endif - -} // namespace - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0; -#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - -HashtablezSampler& HashtablezSampler::Global() { - static auto* sampler = new HashtablezSampler(); - return *sampler; -} - -HashtablezSampler::DisposeCallback HashtablezSampler::SetDisposeCallback( - DisposeCallback f) { - return dispose_.exchange(f, std::memory_order_relaxed); -} - -HashtablezInfo::HashtablezInfo() { PrepareForSampling(); } -HashtablezInfo::~HashtablezInfo() = default; - -void HashtablezInfo::PrepareForSampling() { - capacity.store(0, std::memory_order_relaxed); - size.store(0, std::memory_order_relaxed); - num_erases.store(0, std::memory_order_relaxed); - num_rehashes.store(0, std::memory_order_relaxed); - max_probe_length.store(0, std::memory_order_relaxed); - total_probe_length.store(0, std::memory_order_relaxed); - hashes_bitwise_or.store(0, std::memory_order_relaxed); - hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed); - - create_time = absl::Now(); - // The inliner makes hardcoded skip_count difficult (especially when combined - // with LTO). We use the ability to exclude stacks by regex when encoding - // instead. - depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth, - /* skip_count= */ 0); - dead = nullptr; -} - -HashtablezSampler::HashtablezSampler() - : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) { - absl::MutexLock l(&graveyard_.init_mu); - graveyard_.dead = &graveyard_; -} - -HashtablezSampler::~HashtablezSampler() { - HashtablezInfo* s = all_.load(std::memory_order_acquire); - while (s != nullptr) { - HashtablezInfo* next = s->next; - delete s; - s = next; - } -} - -void HashtablezSampler::PushNew(HashtablezInfo* sample) { - sample->next = all_.load(std::memory_order_relaxed); - while (!all_.compare_exchange_weak(sample->next, sample, - std::memory_order_release, - std::memory_order_relaxed)) { - } -} - -void HashtablezSampler::PushDead(HashtablezInfo* sample) { - if (auto* dispose = dispose_.load(std::memory_order_relaxed)) { - dispose(*sample); - } - - absl::MutexLock graveyard_lock(&graveyard_.init_mu); - absl::MutexLock sample_lock(&sample->init_mu); - sample->dead = graveyard_.dead; - graveyard_.dead = sample; -} - -HashtablezInfo* HashtablezSampler::PopDead() { - absl::MutexLock graveyard_lock(&graveyard_.init_mu); - - // The list is circular, so eventually it collapses down to - // graveyard_.dead == &graveyard_ - // when it is empty. - HashtablezInfo* sample = graveyard_.dead; - if (sample == &graveyard_) return nullptr; - - absl::MutexLock sample_lock(&sample->init_mu); - graveyard_.dead = sample->dead; - sample->PrepareForSampling(); - return sample; -} - -HashtablezInfo* HashtablezSampler::Register() { - int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed); - if (size > g_hashtablez_max_samples.load(std::memory_order_relaxed)) { - size_estimate_.fetch_sub(1, std::memory_order_relaxed); - dropped_samples_.fetch_add(1, std::memory_order_relaxed); - return nullptr; - } - - HashtablezInfo* sample = PopDead(); - if (sample == nullptr) { - // Resurrection failed. Hire a new warlock. - sample = new HashtablezInfo(); - PushNew(sample); - } - - return sample; -} - -void HashtablezSampler::Unregister(HashtablezInfo* sample) { - PushDead(sample); - size_estimate_.fetch_sub(1, std::memory_order_relaxed); -} - -int64_t HashtablezSampler::Iterate( - const std::function<void(const HashtablezInfo& stack)>& f) { - HashtablezInfo* s = all_.load(std::memory_order_acquire); - while (s != nullptr) { - absl::MutexLock l(&s->init_mu); - if (s->dead == nullptr) { - f(*s); - } - s = s->next; - } - - return dropped_samples_.load(std::memory_order_relaxed); -} - -static bool ShouldForceSampling() { - enum ForceState { - kDontForce, - kForce, - kUninitialized - }; - ABSL_CONST_INIT static std::atomic<ForceState> global_state{ - kUninitialized}; - ForceState state = global_state.load(std::memory_order_relaxed); - if (ABSL_PREDICT_TRUE(state == kDontForce)) return false; - - if (state == kUninitialized) { - state = AbslContainerInternalSampleEverything() ? kForce : kDontForce; - global_state.store(state, std::memory_order_relaxed); - } - return state == kForce; -} - -HashtablezInfo* SampleSlow(int64_t* next_sample) { - if (ABSL_PREDICT_FALSE(ShouldForceSampling())) { - *next_sample = 1; - return HashtablezSampler::Global().Register(); - } - -#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - *next_sample = std::numeric_limits<int64_t>::max(); - return nullptr; -#else - bool first = *next_sample < 0; - *next_sample = g_exponential_biased_generator.GetStride( - g_hashtablez_sample_parameter.load(std::memory_order_relaxed)); - // Small values of interval are equivalent to just sampling next time. - ABSL_ASSERT(*next_sample >= 1); - - // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold - // low enough that we will start sampling in a reasonable time, so we just use - // the default sampling rate. - if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr; - - // We will only be negative on our first count, so we should just retry in - // that case. - if (first) { - if (ABSL_PREDICT_TRUE(--*next_sample > 0)) return nullptr; - return SampleSlow(next_sample); - } - - return HashtablezSampler::Global().Register(); -#endif -} - -void UnsampleSlow(HashtablezInfo* info) { - HashtablezSampler::Global().Unregister(info); -} - -void RecordInsertSlow(HashtablezInfo* info, size_t hash, - size_t distance_from_desired) { - // SwissTables probe in groups of 16, so scale this to count items probes and - // not offset from desired. - size_t probe_length = distance_from_desired; -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 - probe_length /= 16; -#else - probe_length /= 8; -#endif - - info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed); - info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed); - info->max_probe_length.store( - std::max(info->max_probe_length.load(std::memory_order_relaxed), - probe_length), - std::memory_order_relaxed); - info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed); - info->size.fetch_add(1, std::memory_order_relaxed); -} - -void SetHashtablezEnabled(bool enabled) { - g_hashtablez_enabled.store(enabled, std::memory_order_release); -} - -void SetHashtablezSampleParameter(int32_t rate) { - if (rate > 0) { - g_hashtablez_sample_parameter.store(rate, std::memory_order_release); - } else { - ABSL_RAW_LOG(ERROR, "Invalid hashtablez sample rate: %lld", - static_cast<long long>(rate)); // NOLINT(runtime/int) - } -} - -void SetHashtablezMaxSamples(int32_t max) { - if (max > 0) { - g_hashtablez_max_samples.store(max, std::memory_order_release); - } else { - ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld", - static_cast<long long>(max)); // NOLINT(runtime/int) - } -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.h b/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.h deleted file mode 100644 index 394348da58f5..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler.h +++ /dev/null @@ -1,321 +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: hashtablez_sampler.h -// ----------------------------------------------------------------------------- -// -// This header file defines the API for a low level library to sample hashtables -// and collect runtime statistics about them. -// -// `HashtablezSampler` controls the lifecycle of `HashtablezInfo` objects which -// store information about a single sample. -// -// `Record*` methods store information into samples. -// `Sample()` and `Unsample()` make use of a single global sampler with -// properties controlled by the flags hashtablez_enabled, -// hashtablez_sample_rate, and hashtablez_max_samples. -// -// WARNING -// -// Using this sampling API may cause sampled Swiss tables to use the global -// allocator (operator `new`) in addition to any custom allocator. If you -// are using a table in an unusual circumstance where allocation or calling a -// linux syscall is unacceptable, this could interfere. -// -// This utility is internal-only. Use at your own risk. - -#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ -#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ - -#include <atomic> -#include <functional> -#include <memory> -#include <vector> - -#include "absl/base/internal/per_thread_tls.h" -#include "absl/base/optimization.h" -#include "absl/container/internal/have_sse.h" -#include "absl/synchronization/mutex.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// Stores information about a sampled hashtable. All mutations to this *must* -// be made through `Record*` functions below. All reads from this *must* only -// occur in the callback to `HashtablezSampler::Iterate`. -struct HashtablezInfo { - // Constructs the object but does not fill in any fields. - HashtablezInfo(); - ~HashtablezInfo(); - HashtablezInfo(const HashtablezInfo&) = delete; - HashtablezInfo& operator=(const HashtablezInfo&) = delete; - - // Puts the object into a clean state, fills in the logically `const` members, - // blocking for any readers that are currently sampling the object. - void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu); - - // These fields are mutated by the various Record* APIs and need to be - // thread-safe. - std::atomic<size_t> capacity; - std::atomic<size_t> size; - std::atomic<size_t> num_erases; - std::atomic<size_t> num_rehashes; - std::atomic<size_t> max_probe_length; - std::atomic<size_t> total_probe_length; - std::atomic<size_t> hashes_bitwise_or; - std::atomic<size_t> hashes_bitwise_and; - - // `HashtablezSampler` maintains intrusive linked lists for all samples. See - // comments on `HashtablezSampler::all_` for details on these. `init_mu` - // guards the ability to restore the sample to a pristine state. This - // prevents races with sampling and resurrecting an object. - absl::Mutex init_mu; - HashtablezInfo* next; - HashtablezInfo* dead ABSL_GUARDED_BY(init_mu); - - // All of the fields below are set by `PrepareForSampling`, they must not be - // mutated in `Record*` functions. They are logically `const` in that sense. - // These are guarded by init_mu, but that is not externalized to clients, who - // can only read them during `HashtablezSampler::Iterate` which will hold the - // lock. - static constexpr int kMaxStackDepth = 64; - absl::Time create_time; - int32_t depth; - void* stack[kMaxStackDepth]; -}; - -inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) { -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 - total_probe_length /= 16; -#else - total_probe_length /= 8; -#endif - info->total_probe_length.store(total_probe_length, std::memory_order_relaxed); - info->num_erases.store(0, std::memory_order_relaxed); - // There is only one concurrent writer, so `load` then `store` is sufficient - // instead of using `fetch_add`. - info->num_rehashes.store( - 1 + info->num_rehashes.load(std::memory_order_relaxed), - std::memory_order_relaxed); -} - -inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size, - size_t capacity) { - info->size.store(size, std::memory_order_relaxed); - info->capacity.store(capacity, std::memory_order_relaxed); - if (size == 0) { - // This is a clear, reset the total/num_erases too. - info->total_probe_length.store(0, std::memory_order_relaxed); - info->num_erases.store(0, std::memory_order_relaxed); - } -} - -void RecordInsertSlow(HashtablezInfo* info, size_t hash, - size_t distance_from_desired); - -inline void RecordEraseSlow(HashtablezInfo* info) { - info->size.fetch_sub(1, std::memory_order_relaxed); - // There is only one concurrent writer, so `load` then `store` is sufficient - // instead of using `fetch_add`. - info->num_erases.store( - 1 + info->num_erases.load(std::memory_order_relaxed), - std::memory_order_relaxed); -} - -HashtablezInfo* SampleSlow(int64_t* next_sample); -void UnsampleSlow(HashtablezInfo* info); - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set -#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -class HashtablezInfoHandle { - public: - explicit HashtablezInfoHandle() : info_(nullptr) {} - explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {} - ~HashtablezInfoHandle() { - if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; - UnsampleSlow(info_); - } - - HashtablezInfoHandle(const HashtablezInfoHandle&) = delete; - HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete; - - HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept - : info_(absl::exchange(o.info_, nullptr)) {} - HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept { - if (ABSL_PREDICT_FALSE(info_ != nullptr)) { - UnsampleSlow(info_); - } - info_ = absl::exchange(o.info_, nullptr); - return *this; - } - - inline void RecordStorageChanged(size_t size, size_t capacity) { - if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; - RecordStorageChangedSlow(info_, size, capacity); - } - - inline void RecordRehash(size_t total_probe_length) { - if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; - RecordRehashSlow(info_, total_probe_length); - } - - inline void RecordInsert(size_t hash, size_t distance_from_desired) { - if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; - RecordInsertSlow(info_, hash, distance_from_desired); - } - - inline void RecordErase() { - if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; - RecordEraseSlow(info_); - } - - friend inline void swap(HashtablezInfoHandle& lhs, - HashtablezInfoHandle& rhs) { - std::swap(lhs.info_, rhs.info_); - } - - private: - friend class HashtablezInfoHandlePeer; - HashtablezInfo* info_; -}; -#else -// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can -// be removed by the linker, in order to reduce the binary size. -class HashtablezInfoHandle { - public: - explicit HashtablezInfoHandle() = default; - explicit HashtablezInfoHandle(std::nullptr_t) {} - - inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {} - inline void RecordRehash(size_t /*total_probe_length*/) {} - inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {} - inline void RecordErase() {} - - friend inline void swap(HashtablezInfoHandle& /*lhs*/, - HashtablezInfoHandle& /*rhs*/) {} -}; -#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample; -#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - -// Returns an RAII sampling handle that manages registration and unregistation -// with the global sampler. -inline HashtablezInfoHandle Sample() { -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) { - return HashtablezInfoHandle(nullptr); - } - return HashtablezInfoHandle(SampleSlow(&global_next_sample)); -#else - return HashtablezInfoHandle(nullptr); -#endif // !ABSL_PER_THREAD_TLS -} - -// Holds samples and their associated stack traces with a soft limit of -// `SetHashtablezMaxSamples()`. -// -// Thread safe. -class HashtablezSampler { - public: - // Returns a global Sampler. - static HashtablezSampler& Global(); - - HashtablezSampler(); - ~HashtablezSampler(); - - // Registers for sampling. Returns an opaque registration info. - HashtablezInfo* Register(); - - // Unregisters the sample. - void Unregister(HashtablezInfo* sample); - - // The dispose callback will be called on all samples the moment they are - // being unregistered. Only affects samples that are unregistered after the - // callback has been set. - // Returns the previous callback. - using DisposeCallback = void (*)(const HashtablezInfo&); - DisposeCallback SetDisposeCallback(DisposeCallback f); - - // Iterates over all the registered `StackInfo`s. Returning the number of - // samples that have been dropped. - int64_t Iterate(const std::function<void(const HashtablezInfo& stack)>& f); - - private: - void PushNew(HashtablezInfo* sample); - void PushDead(HashtablezInfo* sample); - HashtablezInfo* PopDead(); - - std::atomic<size_t> dropped_samples_; - std::atomic<size_t> size_estimate_; - - // Intrusive lock free linked lists for tracking samples. - // - // `all_` records all samples (they are never removed from this list) and is - // terminated with a `nullptr`. - // - // `graveyard_.dead` is a circular linked list. When it is empty, - // `graveyard_.dead == &graveyard`. The list is circular so that - // every item on it (even the last) has a non-null dead pointer. This allows - // `Iterate` to determine if a given sample is live or dead using only - // information on the sample itself. - // - // For example, nodes [A, B, C, D, E] with [A, C, E] alive and [B, D] dead - // looks like this (G is the Graveyard): - // - // +---+ +---+ +---+ +---+ +---+ - // all -->| A |--->| B |--->| C |--->| D |--->| E | - // | | | | | | | | | | - // +---+ | | +->| |-+ | | +->| |-+ | | - // | G | +---+ | +---+ | +---+ | +---+ | +---+ - // | | | | | | - // | | --------+ +--------+ | - // +---+ | - // ^ | - // +--------------------------------------+ - // - std::atomic<HashtablezInfo*> all_; - HashtablezInfo graveyard_; - - std::atomic<DisposeCallback> dispose_; -}; - -// Enables or disables sampling for Swiss tables. -void SetHashtablezEnabled(bool enabled); - -// Sets the rate at which Swiss tables will be sampled. -void SetHashtablezSampleParameter(int32_t rate); - -// Sets a soft max for the number of samples that will be kept. -void SetHashtablezMaxSamples(int32_t max); - -// Configuration override. -// This allows process-wide sampling without depending on order of -// initialization of static storage duration objects. -// The definition of this constant is weak, which allows us to inject a -// different value for it at link time. -extern "C" bool AbslContainerInternalSampleEverything(); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ 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 deleted file mode 100644 index 78b9d362acf3..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc +++ /dev/null @@ -1,30 +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/hashtablez_sampler.h" - -#include "absl/base/attributes.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// See hashtablez_sampler.h for details. -extern "C" ABSL_ATTRIBUTE_WEAK bool AbslContainerInternalSampleEverything() { - return false; -} - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 8d10a1e94030..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/hashtablez_sampler_test.cc +++ /dev/null @@ -1,371 +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/hashtablez_sampler.h" - -#include <atomic> -#include <limits> -#include <random> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/container/internal/have_sse.h" -#include "absl/synchronization/blocking_counter.h" -#include "absl/synchronization/internal/thread_pool.h" -#include "absl/synchronization/mutex.h" -#include "absl/synchronization/notification.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" - -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 -constexpr int kProbeLength = 16; -#else -constexpr int kProbeLength = 8; -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -class HashtablezInfoHandlePeer { - public: - static bool IsSampled(const HashtablezInfoHandle& h) { - return h.info_ != nullptr; - } - - static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; } -}; -#else -class HashtablezInfoHandlePeer { - public: - static bool IsSampled(const HashtablezInfoHandle&) { return false; } - static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; } -}; -#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) - -namespace { -using ::absl::synchronization_internal::ThreadPool; -using ::testing::IsEmpty; -using ::testing::UnorderedElementsAre; - -std::vector<size_t> GetSizes(HashtablezSampler* s) { - std::vector<size_t> res; - s->Iterate([&](const HashtablezInfo& info) { - res.push_back(info.size.load(std::memory_order_acquire)); - }); - return res; -} - -HashtablezInfo* Register(HashtablezSampler* s, size_t size) { - auto* info = s->Register(); - assert(info != nullptr); - info->size.store(size); - return info; -} - -TEST(HashtablezInfoTest, PrepareForSampling) { - absl::Time test_start = absl::Now(); - HashtablezInfo info; - absl::MutexLock l(&info.init_mu); - info.PrepareForSampling(); - - EXPECT_EQ(info.capacity.load(), 0); - EXPECT_EQ(info.size.load(), 0); - EXPECT_EQ(info.num_erases.load(), 0); - EXPECT_EQ(info.num_rehashes.load(), 0); - EXPECT_EQ(info.max_probe_length.load(), 0); - EXPECT_EQ(info.total_probe_length.load(), 0); - EXPECT_EQ(info.hashes_bitwise_or.load(), 0); - EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{}); - EXPECT_GE(info.create_time, test_start); - - info.capacity.store(1, std::memory_order_relaxed); - info.size.store(1, std::memory_order_relaxed); - info.num_erases.store(1, std::memory_order_relaxed); - info.max_probe_length.store(1, std::memory_order_relaxed); - info.total_probe_length.store(1, std::memory_order_relaxed); - info.hashes_bitwise_or.store(1, std::memory_order_relaxed); - info.hashes_bitwise_and.store(1, std::memory_order_relaxed); - info.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_GE(info.create_time, test_start); -} - -TEST(HashtablezInfoTest, RecordStorageChanged) { - HashtablezInfo info; - absl::MutexLock l(&info.init_mu); - info.PrepareForSampling(); - RecordStorageChangedSlow(&info, 17, 47); - EXPECT_EQ(info.size.load(), 17); - EXPECT_EQ(info.capacity.load(), 47); - RecordStorageChangedSlow(&info, 20, 20); - EXPECT_EQ(info.size.load(), 20); - EXPECT_EQ(info.capacity.load(), 20); -} - -TEST(HashtablezInfoTest, RecordInsert) { - HashtablezInfo info; - absl::MutexLock l(&info.init_mu); - info.PrepareForSampling(); - EXPECT_EQ(info.max_probe_length.load(), 0); - RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength); - EXPECT_EQ(info.max_probe_length.load(), 6); - EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000FF00); - EXPECT_EQ(info.hashes_bitwise_or.load(), 0x0000FF00); - 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); - 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); -} - -TEST(HashtablezInfoTest, RecordErase) { - HashtablezInfo info; - absl::MutexLock l(&info.init_mu); - info.PrepareForSampling(); - EXPECT_EQ(info.num_erases.load(), 0); - EXPECT_EQ(info.size.load(), 0); - RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength); - EXPECT_EQ(info.size.load(), 1); - RecordEraseSlow(&info); - EXPECT_EQ(info.size.load(), 0); - EXPECT_EQ(info.num_erases.load(), 1); -} - -TEST(HashtablezInfoTest, RecordRehash) { - HashtablezInfo info; - absl::MutexLock l(&info.init_mu); - info.PrepareForSampling(); - RecordInsertSlow(&info, 0x1, 0); - RecordInsertSlow(&info, 0x2, kProbeLength); - RecordInsertSlow(&info, 0x4, kProbeLength); - RecordInsertSlow(&info, 0x8, 2 * kProbeLength); - EXPECT_EQ(info.size.load(), 4); - EXPECT_EQ(info.total_probe_length.load(), 4); - - RecordEraseSlow(&info); - RecordEraseSlow(&info); - EXPECT_EQ(info.size.load(), 2); - EXPECT_EQ(info.total_probe_length.load(), 4); - EXPECT_EQ(info.num_erases.load(), 2); - - RecordRehashSlow(&info, 3 * kProbeLength); - EXPECT_EQ(info.size.load(), 2); - EXPECT_EQ(info.total_probe_length.load(), 3); - EXPECT_EQ(info.num_erases.load(), 0); - EXPECT_EQ(info.num_rehashes.load(), 1); -} - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -TEST(HashtablezSamplerTest, SmallSampleParameter) { - SetHashtablezEnabled(true); - SetHashtablezSampleParameter(100); - - for (int i = 0; i < 1000; ++i) { - int64_t next_sample = 0; - HashtablezInfo* sample = SampleSlow(&next_sample); - EXPECT_GT(next_sample, 0); - EXPECT_NE(sample, nullptr); - UnsampleSlow(sample); - } -} - -TEST(HashtablezSamplerTest, LargeSampleParameter) { - SetHashtablezEnabled(true); - SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max()); - - for (int i = 0; i < 1000; ++i) { - int64_t next_sample = 0; - HashtablezInfo* sample = SampleSlow(&next_sample); - EXPECT_GT(next_sample, 0); - EXPECT_NE(sample, nullptr); - UnsampleSlow(sample); - } -} - -TEST(HashtablezSamplerTest, Sample) { - SetHashtablezEnabled(true); - SetHashtablezSampleParameter(100); - int64_t num_sampled = 0; - int64_t total = 0; - double sample_rate = 0.0; - for (int i = 0; i < 1000000; ++i) { - HashtablezInfoHandle h = Sample(); - ++total; - if (HashtablezInfoHandlePeer::IsSampled(h)) { - ++num_sampled; - } - sample_rate = static_cast<double>(num_sampled) / total; - if (0.005 < sample_rate && sample_rate < 0.015) break; - } - EXPECT_NEAR(sample_rate, 0.01, 0.005); -} - -TEST(HashtablezSamplerTest, Handle) { - auto& sampler = HashtablezSampler::Global(); - HashtablezInfoHandle h(sampler.Register()); - auto* info = HashtablezInfoHandlePeer::GetInfo(&h); - info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed); - - bool found = false; - sampler.Iterate([&](const HashtablezInfo& h) { - if (&h == info) { - EXPECT_EQ(h.hashes_bitwise_and.load(), 0x12345678); - found = true; - } - }); - EXPECT_TRUE(found); - - h = HashtablezInfoHandle(); - found = false; - sampler.Iterate([&](const HashtablezInfo& h) { - if (&h == info) { - // this will only happen if some other thread has resurrected the info - // the old handle was using. - if (h.hashes_bitwise_and.load() == 0x12345678) { - found = true; - } - } - }); - EXPECT_FALSE(found); -} -#endif - - -TEST(HashtablezSamplerTest, Registration) { - HashtablezSampler sampler; - auto* info1 = Register(&sampler, 1); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1)); - - auto* info2 = Register(&sampler, 2); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2)); - info1->size.store(3); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2)); - - sampler.Unregister(info1); - sampler.Unregister(info2); -} - -TEST(HashtablezSamplerTest, Unregistration) { - HashtablezSampler sampler; - std::vector<HashtablezInfo*> infos; - for (size_t i = 0; i < 3; ++i) { - infos.push_back(Register(&sampler, i)); - } - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2)); - - sampler.Unregister(infos[1]); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2)); - - infos.push_back(Register(&sampler, 3)); - infos.push_back(Register(&sampler, 4)); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4)); - sampler.Unregister(infos[3]); - EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4)); - - sampler.Unregister(infos[0]); - sampler.Unregister(infos[2]); - sampler.Unregister(infos[4]); - EXPECT_THAT(GetSizes(&sampler), IsEmpty()); -} - -TEST(HashtablezSamplerTest, MultiThreaded) { - HashtablezSampler sampler; - Notification stop; - ThreadPool pool(10); - - for (int i = 0; i < 10; ++i) { - pool.Schedule([&sampler, &stop]() { - std::random_device rd; - std::mt19937 gen(rd()); - - std::vector<HashtablezInfo*> infoz; - while (!stop.HasBeenNotified()) { - if (infoz.empty()) { - infoz.push_back(sampler.Register()); - } - switch (std::uniform_int_distribution<>(0, 2)(gen)) { - case 0: { - infoz.push_back(sampler.Register()); - break; - } - case 1: { - size_t p = - std::uniform_int_distribution<>(0, infoz.size() - 1)(gen); - HashtablezInfo* info = infoz[p]; - infoz[p] = infoz.back(); - infoz.pop_back(); - sampler.Unregister(info); - break; - } - case 2: { - absl::Duration oldest = absl::ZeroDuration(); - sampler.Iterate([&](const HashtablezInfo& info) { - oldest = std::max(oldest, absl::Now() - info.create_time); - }); - ASSERT_GE(oldest, absl::ZeroDuration()); - break; - } - } - } - }); - } - // The threads will hammer away. Give it a little bit of time for tsan to - // spot errors. - absl::SleepFor(absl::Seconds(3)); - stop.Notify(); -} - -TEST(HashtablezSamplerTest, Callback) { - HashtablezSampler sampler; - - auto* info1 = Register(&sampler, 1); - auto* info2 = Register(&sampler, 2); - - static const HashtablezInfo* expected; - - auto callback = [](const HashtablezInfo& info) { - // We can't use `info` outside of this callback because the object will be - // disposed as soon as we return from here. - EXPECT_EQ(&info, expected); - }; - - // Set the callback. - EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr); - expected = info1; - sampler.Unregister(info1); - - // Unset the callback. - EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr)); - expected = nullptr; // no more calls. - sampler.Unregister(info2); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/have_sse.h b/third_party/abseil_cpp/absl/container/internal/have_sse.h deleted file mode 100644 index e75e1a16d327..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/have_sse.h +++ /dev/null @@ -1,50 +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. -// -// Shared config probing for SSE instructions used in Swiss tables. -#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_ -#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_ - -#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 -#if defined(__SSE2__) || \ - (defined(_MSC_VER) && \ - (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2))) -#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 1 -#else -#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 0 -#endif -#endif - -#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 -#ifdef __SSSE3__ -#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 1 -#else -#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 0 -#endif -#endif - -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 && \ - !ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 -#error "Bad configuration!" -#endif - -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 -#include <emmintrin.h> -#endif - -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 -#include <tmmintrin.h> -#endif - -#endif // ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/inlined_vector.h b/third_party/abseil_cpp/absl/container/internal/inlined_vector.h deleted file mode 100644 index c98c25c44221..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/inlined_vector.h +++ /dev/null @@ -1,895 +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_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ -#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ - -#include <algorithm> -#include <cstddef> -#include <cstring> -#include <iterator> -#include <limits> -#include <memory> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace inlined_vector_internal { - -template <typename Iterator> -using IsAtLeastForwardIterator = std::is_convertible< - typename std::iterator_traits<Iterator>::iterator_category, - std::forward_iterator_tag>; - -template <typename AllocatorType, - typename ValueType = - typename absl::allocator_traits<AllocatorType>::value_type> -using IsMemcpyOk = - absl::conjunction<std::is_same<AllocatorType, std::allocator<ValueType>>, - absl::is_trivially_copy_constructible<ValueType>, - absl::is_trivially_copy_assignable<ValueType>, - absl::is_trivially_destructible<ValueType>>; - -template <typename AllocatorType, typename Pointer, typename SizeType> -void DestroyElements(AllocatorType* alloc_ptr, Pointer destroy_first, - SizeType destroy_size) { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - - if (destroy_first != nullptr) { - for (auto i = destroy_size; i != 0;) { - --i; - AllocatorTraits::destroy(*alloc_ptr, destroy_first + i); - } - -#if !defined(NDEBUG) - { - using ValueType = typename AllocatorTraits::value_type; - - // Overwrite unused memory with `0xab` so we can catch uninitialized - // usage. - // - // Cast to `void*` to tell the compiler that we don't care that we might - // be scribbling on a vtable pointer. - void* memory_ptr = destroy_first; - auto memory_size = destroy_size * sizeof(ValueType); - std::memset(memory_ptr, 0xab, memory_size); - } -#endif // !defined(NDEBUG) - } -} - -template <typename AllocatorType, typename Pointer, typename ValueAdapter, - typename SizeType> -void ConstructElements(AllocatorType* alloc_ptr, Pointer construct_first, - ValueAdapter* values_ptr, SizeType construct_size) { - for (SizeType i = 0; i < construct_size; ++i) { - ABSL_INTERNAL_TRY { - values_ptr->ConstructNext(alloc_ptr, construct_first + i); - } - ABSL_INTERNAL_CATCH_ANY { - inlined_vector_internal::DestroyElements(alloc_ptr, construct_first, i); - ABSL_INTERNAL_RETHROW; - } - } -} - -template <typename Pointer, typename ValueAdapter, typename SizeType> -void AssignElements(Pointer assign_first, ValueAdapter* values_ptr, - SizeType assign_size) { - for (SizeType i = 0; i < assign_size; ++i) { - values_ptr->AssignNext(assign_first + i); - } -} - -template <typename AllocatorType> -struct StorageView { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using Pointer = typename AllocatorTraits::pointer; - using SizeType = typename AllocatorTraits::size_type; - - Pointer data; - SizeType size; - SizeType capacity; -}; - -template <typename AllocatorType, typename Iterator> -class IteratorValueAdapter { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using Pointer = typename AllocatorTraits::pointer; - - public: - explicit IteratorValueAdapter(const Iterator& it) : it_(it) {} - - void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) { - AllocatorTraits::construct(*alloc_ptr, construct_at, *it_); - ++it_; - } - - void AssignNext(Pointer assign_at) { - *assign_at = *it_; - ++it_; - } - - private: - Iterator it_; -}; - -template <typename AllocatorType> -class CopyValueAdapter { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using ValueType = typename AllocatorTraits::value_type; - using Pointer = typename AllocatorTraits::pointer; - using ConstPointer = typename AllocatorTraits::const_pointer; - - public: - explicit CopyValueAdapter(const ValueType& v) : ptr_(std::addressof(v)) {} - - void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) { - AllocatorTraits::construct(*alloc_ptr, construct_at, *ptr_); - } - - void AssignNext(Pointer assign_at) { *assign_at = *ptr_; } - - private: - ConstPointer ptr_; -}; - -template <typename AllocatorType> -class DefaultValueAdapter { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using ValueType = typename AllocatorTraits::value_type; - using Pointer = typename AllocatorTraits::pointer; - - public: - explicit DefaultValueAdapter() {} - - void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) { - AllocatorTraits::construct(*alloc_ptr, construct_at); - } - - void AssignNext(Pointer assign_at) { *assign_at = ValueType(); } -}; - -template <typename AllocatorType> -class AllocationTransaction { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using Pointer = typename AllocatorTraits::pointer; - using SizeType = typename AllocatorTraits::size_type; - - public: - explicit AllocationTransaction(AllocatorType* alloc_ptr) - : alloc_data_(*alloc_ptr, nullptr) {} - - ~AllocationTransaction() { - if (DidAllocate()) { - AllocatorTraits::deallocate(GetAllocator(), GetData(), GetCapacity()); - } - } - - AllocationTransaction(const AllocationTransaction&) = delete; - void operator=(const AllocationTransaction&) = delete; - - AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); } - Pointer& GetData() { return alloc_data_.template get<1>(); } - SizeType& GetCapacity() { return capacity_; } - - bool DidAllocate() { return GetData() != nullptr; } - Pointer Allocate(SizeType capacity) { - GetData() = AllocatorTraits::allocate(GetAllocator(), capacity); - GetCapacity() = capacity; - return GetData(); - } - - void Reset() { - GetData() = nullptr; - GetCapacity() = 0; - } - - private: - container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_; - SizeType capacity_ = 0; -}; - -template <typename AllocatorType> -class ConstructionTransaction { - using AllocatorTraits = absl::allocator_traits<AllocatorType>; - using Pointer = typename AllocatorTraits::pointer; - using SizeType = typename AllocatorTraits::size_type; - - public: - explicit ConstructionTransaction(AllocatorType* alloc_ptr) - : alloc_data_(*alloc_ptr, nullptr) {} - - ~ConstructionTransaction() { - if (DidConstruct()) { - inlined_vector_internal::DestroyElements(std::addressof(GetAllocator()), - GetData(), GetSize()); - } - } - - ConstructionTransaction(const ConstructionTransaction&) = delete; - void operator=(const ConstructionTransaction&) = delete; - - AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); } - Pointer& GetData() { return alloc_data_.template get<1>(); } - SizeType& GetSize() { return size_; } - - bool DidConstruct() { return GetData() != nullptr; } - template <typename ValueAdapter> - void Construct(Pointer data, ValueAdapter* values_ptr, SizeType size) { - inlined_vector_internal::ConstructElements(std::addressof(GetAllocator()), - data, values_ptr, size); - GetData() = data; - GetSize() = size; - } - void Commit() { - GetData() = nullptr; - GetSize() = 0; - } - - private: - container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_; - SizeType size_ = 0; -}; - -template <typename T, size_t N, typename A> -class Storage { - public: - using AllocatorTraits = absl::allocator_traits<A>; - using allocator_type = typename AllocatorTraits::allocator_type; - using value_type = typename AllocatorTraits::value_type; - using pointer = typename AllocatorTraits::pointer; - using const_pointer = typename AllocatorTraits::const_pointer; - using size_type = typename AllocatorTraits::size_type; - using difference_type = typename AllocatorTraits::difference_type; - - using reference = value_type&; - using const_reference = const value_type&; - using RValueReference = value_type&&; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using MoveIterator = std::move_iterator<iterator>; - using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<allocator_type>; - - using StorageView = inlined_vector_internal::StorageView<allocator_type>; - - template <typename Iterator> - using IteratorValueAdapter = - inlined_vector_internal::IteratorValueAdapter<allocator_type, Iterator>; - using CopyValueAdapter = - inlined_vector_internal::CopyValueAdapter<allocator_type>; - using DefaultValueAdapter = - inlined_vector_internal::DefaultValueAdapter<allocator_type>; - - using AllocationTransaction = - inlined_vector_internal::AllocationTransaction<allocator_type>; - using ConstructionTransaction = - inlined_vector_internal::ConstructionTransaction<allocator_type>; - - static size_type NextCapacity(size_type current_capacity) { - return current_capacity * 2; - } - - static size_type ComputeCapacity(size_type current_capacity, - size_type requested_capacity) { - return (std::max)(NextCapacity(current_capacity), requested_capacity); - } - - // --------------------------------------------------------------------------- - // Storage Constructors and Destructor - // --------------------------------------------------------------------------- - - Storage() : metadata_() {} - - explicit Storage(const allocator_type& alloc) : metadata_(alloc, {}) {} - - ~Storage() { - pointer data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData(); - inlined_vector_internal::DestroyElements(GetAllocPtr(), data, GetSize()); - DeallocateIfAllocated(); - } - - // --------------------------------------------------------------------------- - // Storage Member Accessors - // --------------------------------------------------------------------------- - - size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); } - - const size_type& GetSizeAndIsAllocated() const { - return metadata_.template get<1>(); - } - - size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; } - - bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; } - - pointer GetAllocatedData() { return data_.allocated.allocated_data; } - - const_pointer GetAllocatedData() const { - return data_.allocated.allocated_data; - } - - pointer GetInlinedData() { - return reinterpret_cast<pointer>( - std::addressof(data_.inlined.inlined_data[0])); - } - - const_pointer GetInlinedData() const { - return reinterpret_cast<const_pointer>( - std::addressof(data_.inlined.inlined_data[0])); - } - - size_type GetAllocatedCapacity() const { - return data_.allocated.allocated_capacity; - } - - size_type GetInlinedCapacity() const { return static_cast<size_type>(N); } - - StorageView MakeStorageView() { - return GetIsAllocated() - ? StorageView{GetAllocatedData(), GetSize(), - GetAllocatedCapacity()} - : StorageView{GetInlinedData(), GetSize(), GetInlinedCapacity()}; - } - - allocator_type* GetAllocPtr() { - return std::addressof(metadata_.template get<0>()); - } - - const allocator_type* GetAllocPtr() const { - return std::addressof(metadata_.template get<0>()); - } - - // --------------------------------------------------------------------------- - // Storage Member Mutators - // --------------------------------------------------------------------------- - - template <typename ValueAdapter> - void Initialize(ValueAdapter values, size_type new_size); - - template <typename ValueAdapter> - void Assign(ValueAdapter values, size_type new_size); - - template <typename ValueAdapter> - void Resize(ValueAdapter values, size_type new_size); - - template <typename ValueAdapter> - iterator Insert(const_iterator pos, ValueAdapter values, - size_type insert_count); - - template <typename... Args> - reference EmplaceBack(Args&&... args); - - iterator Erase(const_iterator from, const_iterator to); - - void Reserve(size_type requested_capacity); - - void ShrinkToFit(); - - void Swap(Storage* other_storage_ptr); - - void SetIsAllocated() { - GetSizeAndIsAllocated() |= static_cast<size_type>(1); - } - - void UnsetIsAllocated() { - GetSizeAndIsAllocated() &= ((std::numeric_limits<size_type>::max)() - 1); - } - - void SetSize(size_type size) { - GetSizeAndIsAllocated() = - (size << 1) | static_cast<size_type>(GetIsAllocated()); - } - - void SetAllocatedSize(size_type size) { - GetSizeAndIsAllocated() = (size << 1) | static_cast<size_type>(1); - } - - void SetInlinedSize(size_type size) { - GetSizeAndIsAllocated() = size << static_cast<size_type>(1); - } - - void AddSize(size_type count) { - GetSizeAndIsAllocated() += count << static_cast<size_type>(1); - } - - void SubtractSize(size_type count) { - assert(count <= GetSize()); - - GetSizeAndIsAllocated() -= count << static_cast<size_type>(1); - } - - void SetAllocatedData(pointer data, size_type capacity) { - data_.allocated.allocated_data = data; - data_.allocated.allocated_capacity = capacity; - } - - void AcquireAllocatedData(AllocationTransaction* allocation_tx_ptr) { - SetAllocatedData(allocation_tx_ptr->GetData(), - allocation_tx_ptr->GetCapacity()); - - allocation_tx_ptr->Reset(); - } - - void MemcpyFrom(const Storage& other_storage) { - assert(IsMemcpyOk::value || other_storage.GetIsAllocated()); - - GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated(); - data_ = other_storage.data_; - } - - void DeallocateIfAllocated() { - if (GetIsAllocated()) { - AllocatorTraits::deallocate(*GetAllocPtr(), GetAllocatedData(), - GetAllocatedCapacity()); - } - } - - private: - using Metadata = - container_internal::CompressedTuple<allocator_type, size_type>; - - struct Allocated { - pointer allocated_data; - size_type allocated_capacity; - }; - - struct Inlined { - alignas(value_type) char inlined_data[sizeof(value_type[N])]; - }; - - union Data { - Allocated allocated; - Inlined inlined; - }; - - template <typename... Args> - ABSL_ATTRIBUTE_NOINLINE reference EmplaceBackSlow(Args&&... args); - - Metadata metadata_; - Data data_; -}; - -template <typename T, size_t N, typename A> -template <typename ValueAdapter> -auto Storage<T, N, A>::Initialize(ValueAdapter values, size_type new_size) - -> void { - // Only callable from constructors! - assert(!GetIsAllocated()); - assert(GetSize() == 0); - - pointer construct_data; - if (new_size > GetInlinedCapacity()) { - // Because this is only called from the `InlinedVector` constructors, it's - // safe to take on the allocation with size `0`. If `ConstructElements(...)` - // throws, deallocation will be automatically handled by `~Storage()`. - size_type new_capacity = ComputeCapacity(GetInlinedCapacity(), new_size); - construct_data = AllocatorTraits::allocate(*GetAllocPtr(), new_capacity); - SetAllocatedData(construct_data, new_capacity); - SetIsAllocated(); - } else { - construct_data = GetInlinedData(); - } - - inlined_vector_internal::ConstructElements(GetAllocPtr(), construct_data, - &values, new_size); - - // Since the initial size was guaranteed to be `0` and the allocated bit is - // already correct for either case, *adding* `new_size` gives us the correct - // result faster than setting it directly. - AddSize(new_size); -} - -template <typename T, size_t N, typename A> -template <typename ValueAdapter> -auto Storage<T, N, A>::Assign(ValueAdapter values, size_type new_size) -> void { - StorageView storage_view = MakeStorageView(); - - AllocationTransaction allocation_tx(GetAllocPtr()); - - absl::Span<value_type> assign_loop; - absl::Span<value_type> construct_loop; - absl::Span<value_type> destroy_loop; - - if (new_size > storage_view.capacity) { - size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size); - construct_loop = {allocation_tx.Allocate(new_capacity), new_size}; - destroy_loop = {storage_view.data, storage_view.size}; - } else if (new_size > storage_view.size) { - assign_loop = {storage_view.data, storage_view.size}; - construct_loop = {storage_view.data + storage_view.size, - new_size - storage_view.size}; - } else { - assign_loop = {storage_view.data, new_size}; - destroy_loop = {storage_view.data + new_size, storage_view.size - new_size}; - } - - inlined_vector_internal::AssignElements(assign_loop.data(), &values, - assign_loop.size()); - - inlined_vector_internal::ConstructElements( - GetAllocPtr(), construct_loop.data(), &values, construct_loop.size()); - - inlined_vector_internal::DestroyElements(GetAllocPtr(), destroy_loop.data(), - destroy_loop.size()); - - if (allocation_tx.DidAllocate()) { - DeallocateIfAllocated(); - AcquireAllocatedData(&allocation_tx); - SetIsAllocated(); - } - - SetSize(new_size); -} - -template <typename T, size_t N, typename A> -template <typename ValueAdapter> -auto Storage<T, N, A>::Resize(ValueAdapter values, size_type new_size) -> void { - StorageView storage_view = MakeStorageView(); - auto* const base = storage_view.data; - const size_type size = storage_view.size; - auto* alloc = GetAllocPtr(); - if (new_size <= size) { - // Destroy extra old elements. - inlined_vector_internal::DestroyElements(alloc, base + new_size, - size - new_size); - } else if (new_size <= storage_view.capacity) { - // Construct new elements in place. - inlined_vector_internal::ConstructElements(alloc, base + size, &values, - new_size - size); - } else { - // Steps: - // a. Allocate new backing store. - // b. Construct new elements in new backing store. - // c. Move existing elements from old backing store to now. - // d. Destroy all elements in old backing store. - // Use transactional wrappers for the first two steps so we can roll - // back if necessary due to exceptions. - AllocationTransaction allocation_tx(alloc); - size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size); - pointer new_data = allocation_tx.Allocate(new_capacity); - - ConstructionTransaction construction_tx(alloc); - construction_tx.Construct(new_data + size, &values, new_size - size); - - IteratorValueAdapter<MoveIterator> move_values((MoveIterator(base))); - inlined_vector_internal::ConstructElements(alloc, new_data, &move_values, - size); - - inlined_vector_internal::DestroyElements(alloc, base, size); - construction_tx.Commit(); - DeallocateIfAllocated(); - AcquireAllocatedData(&allocation_tx); - SetIsAllocated(); - } - SetSize(new_size); -} - -template <typename T, size_t N, typename A> -template <typename ValueAdapter> -auto Storage<T, N, A>::Insert(const_iterator pos, ValueAdapter values, - size_type insert_count) -> iterator { - StorageView storage_view = MakeStorageView(); - - size_type insert_index = - std::distance(const_iterator(storage_view.data), pos); - size_type insert_end_index = insert_index + insert_count; - size_type new_size = storage_view.size + insert_count; - - if (new_size > storage_view.capacity) { - AllocationTransaction allocation_tx(GetAllocPtr()); - ConstructionTransaction construction_tx(GetAllocPtr()); - ConstructionTransaction move_construciton_tx(GetAllocPtr()); - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(storage_view.data)); - - size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size); - pointer new_data = allocation_tx.Allocate(new_capacity); - - construction_tx.Construct(new_data + insert_index, &values, insert_count); - - move_construciton_tx.Construct(new_data, &move_values, insert_index); - - inlined_vector_internal::ConstructElements( - GetAllocPtr(), new_data + insert_end_index, &move_values, - storage_view.size - insert_index); - - inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data, - storage_view.size); - - construction_tx.Commit(); - move_construciton_tx.Commit(); - DeallocateIfAllocated(); - AcquireAllocatedData(&allocation_tx); - - SetAllocatedSize(new_size); - return iterator(new_data + insert_index); - } else { - size_type move_construction_destination_index = - (std::max)(insert_end_index, storage_view.size); - - ConstructionTransaction move_construction_tx(GetAllocPtr()); - - IteratorValueAdapter<MoveIterator> move_construction_values( - MoveIterator(storage_view.data + - (move_construction_destination_index - insert_count))); - absl::Span<value_type> move_construction = { - storage_view.data + move_construction_destination_index, - new_size - move_construction_destination_index}; - - pointer move_assignment_values = storage_view.data + insert_index; - absl::Span<value_type> move_assignment = { - storage_view.data + insert_end_index, - move_construction_destination_index - insert_end_index}; - - absl::Span<value_type> insert_assignment = {move_assignment_values, - move_construction.size()}; - - absl::Span<value_type> insert_construction = { - insert_assignment.data() + insert_assignment.size(), - insert_count - insert_assignment.size()}; - - move_construction_tx.Construct(move_construction.data(), - &move_construction_values, - move_construction.size()); - - for (pointer destination = move_assignment.data() + move_assignment.size(), - last_destination = move_assignment.data(), - source = move_assignment_values + move_assignment.size(); - ;) { - --destination; - --source; - if (destination < last_destination) break; - *destination = std::move(*source); - } - - inlined_vector_internal::AssignElements(insert_assignment.data(), &values, - insert_assignment.size()); - - inlined_vector_internal::ConstructElements( - GetAllocPtr(), insert_construction.data(), &values, - insert_construction.size()); - - move_construction_tx.Commit(); - - AddSize(insert_count); - return iterator(storage_view.data + insert_index); - } -} - -template <typename T, size_t N, typename A> -template <typename... Args> -auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> reference { - StorageView storage_view = MakeStorageView(); - const auto n = storage_view.size; - if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) { - // Fast path; new element fits. - pointer last_ptr = storage_view.data + n; - AllocatorTraits::construct(*GetAllocPtr(), last_ptr, - std::forward<Args>(args)...); - AddSize(1); - return *last_ptr; - } - // TODO(b/173712035): Annotate with musttail attribute to prevent regression. - return EmplaceBackSlow(std::forward<Args>(args)...); -} - -template <typename T, size_t N, typename A> -template <typename... Args> -auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> reference { - StorageView storage_view = MakeStorageView(); - AllocationTransaction allocation_tx(GetAllocPtr()); - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(storage_view.data)); - size_type new_capacity = NextCapacity(storage_view.capacity); - pointer construct_data = allocation_tx.Allocate(new_capacity); - pointer last_ptr = construct_data + storage_view.size; - - // Construct new element. - AllocatorTraits::construct(*GetAllocPtr(), last_ptr, - std::forward<Args>(args)...); - // Move elements from old backing store to new backing store. - ABSL_INTERNAL_TRY { - inlined_vector_internal::ConstructElements( - GetAllocPtr(), allocation_tx.GetData(), &move_values, - storage_view.size); - } - ABSL_INTERNAL_CATCH_ANY { - AllocatorTraits::destroy(*GetAllocPtr(), last_ptr); - ABSL_INTERNAL_RETHROW; - } - // Destroy elements in old backing store. - inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data, - storage_view.size); - - DeallocateIfAllocated(); - AcquireAllocatedData(&allocation_tx); - SetIsAllocated(); - AddSize(1); - return *last_ptr; -} - -template <typename T, size_t N, typename A> -auto Storage<T, N, A>::Erase(const_iterator from, const_iterator to) - -> iterator { - StorageView storage_view = MakeStorageView(); - - size_type erase_size = std::distance(from, to); - size_type erase_index = - std::distance(const_iterator(storage_view.data), from); - size_type erase_end_index = erase_index + erase_size; - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(storage_view.data + erase_end_index)); - - inlined_vector_internal::AssignElements(storage_view.data + erase_index, - &move_values, - storage_view.size - erase_end_index); - - inlined_vector_internal::DestroyElements( - GetAllocPtr(), storage_view.data + (storage_view.size - erase_size), - erase_size); - - SubtractSize(erase_size); - return iterator(storage_view.data + erase_index); -} - -template <typename T, size_t N, typename A> -auto Storage<T, N, A>::Reserve(size_type requested_capacity) -> void { - StorageView storage_view = MakeStorageView(); - - if (ABSL_PREDICT_FALSE(requested_capacity <= storage_view.capacity)) return; - - AllocationTransaction allocation_tx(GetAllocPtr()); - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(storage_view.data)); - - size_type new_capacity = - ComputeCapacity(storage_view.capacity, requested_capacity); - pointer new_data = allocation_tx.Allocate(new_capacity); - - inlined_vector_internal::ConstructElements(GetAllocPtr(), new_data, - &move_values, storage_view.size); - - inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data, - storage_view.size); - - DeallocateIfAllocated(); - AcquireAllocatedData(&allocation_tx); - SetIsAllocated(); -} - -template <typename T, size_t N, typename A> -auto Storage<T, N, A>::ShrinkToFit() -> void { - // May only be called on allocated instances! - assert(GetIsAllocated()); - - StorageView storage_view{GetAllocatedData(), GetSize(), - GetAllocatedCapacity()}; - - if (ABSL_PREDICT_FALSE(storage_view.size == storage_view.capacity)) return; - - AllocationTransaction allocation_tx(GetAllocPtr()); - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(storage_view.data)); - - pointer construct_data; - if (storage_view.size > GetInlinedCapacity()) { - size_type new_capacity = storage_view.size; - construct_data = allocation_tx.Allocate(new_capacity); - } else { - construct_data = GetInlinedData(); - } - - ABSL_INTERNAL_TRY { - inlined_vector_internal::ConstructElements(GetAllocPtr(), construct_data, - &move_values, storage_view.size); - } - ABSL_INTERNAL_CATCH_ANY { - SetAllocatedData(storage_view.data, storage_view.capacity); - ABSL_INTERNAL_RETHROW; - } - - inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data, - storage_view.size); - - AllocatorTraits::deallocate(*GetAllocPtr(), storage_view.data, - storage_view.capacity); - - if (allocation_tx.DidAllocate()) { - AcquireAllocatedData(&allocation_tx); - } else { - UnsetIsAllocated(); - } -} - -template <typename T, size_t N, typename A> -auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void { - using std::swap; - assert(this != other_storage_ptr); - - if (GetIsAllocated() && other_storage_ptr->GetIsAllocated()) { - swap(data_.allocated, other_storage_ptr->data_.allocated); - } else if (!GetIsAllocated() && !other_storage_ptr->GetIsAllocated()) { - Storage* small_ptr = this; - Storage* large_ptr = other_storage_ptr; - if (small_ptr->GetSize() > large_ptr->GetSize()) swap(small_ptr, large_ptr); - - for (size_type i = 0; i < small_ptr->GetSize(); ++i) { - swap(small_ptr->GetInlinedData()[i], large_ptr->GetInlinedData()[i]); - } - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(large_ptr->GetInlinedData() + small_ptr->GetSize())); - - inlined_vector_internal::ConstructElements( - large_ptr->GetAllocPtr(), - small_ptr->GetInlinedData() + small_ptr->GetSize(), &move_values, - large_ptr->GetSize() - small_ptr->GetSize()); - - inlined_vector_internal::DestroyElements( - large_ptr->GetAllocPtr(), - large_ptr->GetInlinedData() + small_ptr->GetSize(), - large_ptr->GetSize() - small_ptr->GetSize()); - } else { - Storage* allocated_ptr = this; - Storage* inlined_ptr = other_storage_ptr; - if (!allocated_ptr->GetIsAllocated()) swap(allocated_ptr, inlined_ptr); - - StorageView allocated_storage_view{allocated_ptr->GetAllocatedData(), - allocated_ptr->GetSize(), - allocated_ptr->GetAllocatedCapacity()}; - - IteratorValueAdapter<MoveIterator> move_values( - MoveIterator(inlined_ptr->GetInlinedData())); - - ABSL_INTERNAL_TRY { - inlined_vector_internal::ConstructElements( - inlined_ptr->GetAllocPtr(), allocated_ptr->GetInlinedData(), - &move_values, inlined_ptr->GetSize()); - } - ABSL_INTERNAL_CATCH_ANY { - allocated_ptr->SetAllocatedData(allocated_storage_view.data, - allocated_storage_view.capacity); - ABSL_INTERNAL_RETHROW; - } - - inlined_vector_internal::DestroyElements(inlined_ptr->GetAllocPtr(), - inlined_ptr->GetInlinedData(), - inlined_ptr->GetSize()); - - inlined_ptr->SetAllocatedData(allocated_storage_view.data, - allocated_storage_view.capacity); - } - - swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated()); - swap(*GetAllocPtr(), *other_storage_ptr->GetAllocPtr()); -} - -} // namespace inlined_vector_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/layout.h b/third_party/abseil_cpp/absl/container/internal/layout.h deleted file mode 100644 index 233678331543..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/layout.h +++ /dev/null @@ -1,743 +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. -// -// MOTIVATION AND TUTORIAL -// -// If you want to put in a single heap allocation N doubles followed by M ints, -// it's easy if N and M are known at compile time. -// -// struct S { -// double a[N]; -// int b[M]; -// }; -// -// S* p = new S; -// -// But what if N and M are known only in run time? Class template Layout to the -// rescue! It's a portable generalization of the technique known as struct hack. -// -// // This object will tell us everything we need to know about the memory -// // layout of double[N] followed by int[M]. It's structurally identical to -// // size_t[2] that stores N and M. It's very cheap to create. -// const Layout<double, int> layout(N, M); -// -// // Allocate enough memory for both arrays. `AllocSize()` tells us how much -// // memory is needed. We are free to use any allocation function we want as -// // long as it returns aligned memory. -// std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]); -// -// // Obtain the pointer to the array of doubles. -// // Equivalent to `reinterpret_cast<double*>(p.get())`. -// // -// // We could have written layout.Pointer<0>(p) instead. If all the types are -// // unique you can use either form, but if some types are repeated you must -// // use the index form. -// double* a = layout.Pointer<double>(p.get()); -// -// // Obtain the pointer to the array of ints. -// // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`. -// int* b = layout.Pointer<int>(p); -// -// If we are unable to specify sizes of all fields, we can pass as many sizes as -// we can to `Partial()`. In return, it'll allow us to access the fields whose -// locations and sizes can be computed from the provided information. -// `Partial()` comes in handy when the array sizes are embedded into the -// allocation. -// -// // size_t[1] containing N, size_t[1] containing M, double[N], int[M]. -// using L = Layout<size_t, size_t, double, int>; -// -// unsigned char* Allocate(size_t n, size_t m) { -// const L layout(1, 1, n, m); -// unsigned char* p = new unsigned char[layout.AllocSize()]; -// *layout.Pointer<0>(p) = n; -// *layout.Pointer<1>(p) = m; -// return p; -// } -// -// void Use(unsigned char* p) { -// // First, extract N and M. -// // Specify that the first array has only one element. Using `prefix` we -// // can access the first two arrays but not more. -// constexpr auto prefix = L::Partial(1); -// size_t n = *prefix.Pointer<0>(p); -// size_t m = *prefix.Pointer<1>(p); -// -// // Now we can get pointers to the payload. -// const L layout(1, 1, n, m); -// double* a = layout.Pointer<double>(p); -// int* b = layout.Pointer<int>(p); -// } -// -// The layout we used above combines fixed-size with dynamically-sized fields. -// This is quite common. Layout is optimized for this use case and generates -// optimal code. All computations that can be performed at compile time are -// indeed performed at compile time. -// -// Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to -// ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no -// padding in between arrays. -// -// You can manually override the alignment of an array by wrapping the type in -// `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API -// and behavior as `Layout<..., T, ...>` except that the first element of the -// array of `T` is aligned to `N` (the rest of the elements follow without -// padding). `N` cannot be less than `alignof(T)`. -// -// `AllocSize()` and `Pointer()` are the most basic methods for dealing with -// memory layouts. Check out the reference or code below to discover more. -// -// EXAMPLE -// -// // Immutable move-only string with sizeof equal to sizeof(void*). The -// // string size and the characters are kept in the same heap allocation. -// class CompactString { -// public: -// CompactString(const char* s = "") { -// const size_t size = strlen(s); -// // size_t[1] followed by char[size + 1]. -// const L layout(1, size + 1); -// p_.reset(new unsigned char[layout.AllocSize()]); -// // If running under ASAN, mark the padding bytes, if any, to catch -// // memory errors. -// layout.PoisonPadding(p_.get()); -// // Store the size in the allocation. -// *layout.Pointer<size_t>(p_.get()) = size; -// // Store the characters in the allocation. -// memcpy(layout.Pointer<char>(p_.get()), s, size + 1); -// } -// -// size_t size() const { -// // Equivalent to reinterpret_cast<size_t&>(*p). -// return *L::Partial().Pointer<size_t>(p_.get()); -// } -// -// const char* c_str() const { -// // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)). -// // The argument in Partial(1) specifies that we have size_t[1] in front -// // of the characters. -// return L::Partial(1).Pointer<char>(p_.get()); -// } -// -// private: -// // Our heap allocation contains a size_t followed by an array of chars. -// using L = Layout<size_t, char>; -// std::unique_ptr<unsigned char[]> p_; -// }; -// -// int main() { -// CompactString s = "hello"; -// assert(s.size() == 5); -// assert(strcmp(s.c_str(), "hello") == 0); -// } -// -// DOCUMENTATION -// -// The interface exported by this file consists of: -// - class `Layout<>` and its public members. -// - The public members of class `internal_layout::LayoutImpl<>`. That class -// isn't intended to be used directly, and its name and template parameter -// list are internal implementation details, but the class itself provides -// most of the functionality in this file. See comments on its members for -// detailed documentation. -// -// `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a -// `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)` -// creates a `Layout` object, which exposes the same functionality by inheriting -// from `LayoutImpl<>`. - -#ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_ -#define ABSL_CONTAINER_INTERNAL_LAYOUT_H_ - -#include <assert.h> -#include <stddef.h> -#include <stdint.h> - -#include <ostream> -#include <string> -#include <tuple> -#include <type_traits> -#include <typeinfo> -#include <utility> - -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/str_cat.h" -#include "absl/types/span.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_HAVE_ADDRESS_SANITIZER -#include <sanitizer/asan_interface.h> -#endif - -#if defined(__GXX_RTTI) -#define ABSL_INTERNAL_HAS_CXA_DEMANGLE -#endif - -#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE -#include <cxxabi.h> -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// A type wrapper that instructs `Layout` to use the specific alignment for the -// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API -// and behavior as `Layout<..., T, ...>` except that the first element of the -// array of `T` is aligned to `N` (the rest of the elements follow without -// padding). -// -// Requires: `N >= alignof(T)` and `N` is a power of 2. -template <class T, size_t N> -struct Aligned; - -namespace internal_layout { - -template <class T> -struct NotAligned {}; - -template <class T, size_t N> -struct NotAligned<const Aligned<T, N>> { - static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified"); -}; - -template <size_t> -using IntToSize = size_t; - -template <class> -using TypeToSize = size_t; - -template <class T> -struct Type : NotAligned<T> { - using type = T; -}; - -template <class T, size_t N> -struct Type<Aligned<T, N>> { - using type = T; -}; - -template <class T> -struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {}; - -template <class T, size_t N> -struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {}; - -// Note: workaround for https://gcc.gnu.org/PR88115 -template <class T> -struct AlignOf : NotAligned<T> { - static constexpr size_t value = alignof(T); -}; - -template <class T, size_t N> -struct AlignOf<Aligned<T, N>> { - static_assert(N % alignof(T) == 0, - "Custom alignment can't be lower than the type's alignment"); - static constexpr size_t value = N; -}; - -// Does `Ts...` contain `T`? -template <class T, class... Ts> -using Contains = absl::disjunction<std::is_same<T, Ts>...>; - -template <class From, class To> -using CopyConst = - typename std::conditional<std::is_const<From>::value, const To, To>::type; - -// Note: We're not qualifying this with absl:: because it doesn't compile under -// MSVC. -template <class T> -using SliceType = Span<T>; - -// This namespace contains no types. It prevents functions defined in it from -// being found by ADL. -namespace adl_barrier { - -template <class Needle, class... Ts> -constexpr size_t Find(Needle, Needle, Ts...) { - static_assert(!Contains<Needle, Ts...>(), "Duplicate element type"); - return 0; -} - -template <class Needle, class T, class... Ts> -constexpr size_t Find(Needle, T, Ts...) { - return adl_barrier::Find(Needle(), Ts()...) + 1; -} - -constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); } - -// Returns `q * m` for the smallest `q` such that `q * m >= n`. -// Requires: `m` is a power of two. It's enforced by IsLegalElementType below. -constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); } - -constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; } - -constexpr size_t Max(size_t a) { return a; } - -template <class... Ts> -constexpr size_t Max(size_t a, size_t b, Ts... rest) { - return adl_barrier::Max(b < a ? a : b, rest...); -} - -template <class T> -std::string TypeName() { - std::string out; - int status = 0; - char* demangled = nullptr; -#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE - demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); -#endif - if (status == 0 && demangled != nullptr) { // Demangling succeeded. - absl::StrAppend(&out, "<", demangled, ">"); - free(demangled); - } else { -#if defined(__GXX_RTTI) || defined(_CPPRTTI) - absl::StrAppend(&out, "<", typeid(T).name(), ">"); -#endif - } - return out; -} - -} // namespace adl_barrier - -template <bool C> -using EnableIf = typename std::enable_if<C, int>::type; - -// Can `T` be a template argument of `Layout`? -template <class T> -using IsLegalElementType = std::integral_constant< - bool, !std::is_reference<T>::value && !std::is_volatile<T>::value && - !std::is_reference<typename Type<T>::type>::value && - !std::is_volatile<typename Type<T>::type>::value && - adl_barrier::IsPow2(AlignOf<T>::value)>; - -template <class Elements, class SizeSeq, class OffsetSeq> -class LayoutImpl; - -// Public base class of `Layout` and the result type of `Layout::Partial()`. -// -// `Elements...` contains all template arguments of `Layout` that created this -// instance. -// -// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is the number of arguments -// passed to `Layout::Partial()` or `Layout::Layout()`. -// -// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is -// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we -// can compute offsets). -template <class... Elements, size_t... SizeSeq, size_t... OffsetSeq> -class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>, - absl::index_sequence<OffsetSeq...>> { - private: - static_assert(sizeof...(Elements) > 0, "At least one field is required"); - static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value, - "Invalid element type (see IsLegalElementType)"); - - enum { - NumTypes = sizeof...(Elements), - NumSizes = sizeof...(SizeSeq), - NumOffsets = sizeof...(OffsetSeq), - }; - - // These are guaranteed by `Layout`. - static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1), - "Internal error"); - static_assert(NumTypes > 0, "Internal error"); - - // Returns the index of `T` in `Elements...`. Results in a compilation error - // if `Elements...` doesn't contain exactly one instance of `T`. - template <class T> - static constexpr size_t ElementIndex() { - static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(), - "Type not found"); - return adl_barrier::Find(Type<T>(), - Type<typename Type<Elements>::type>()...); - } - - template <size_t N> - using ElementAlignment = - AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>; - - public: - // Element types of all arrays packed in a tuple. - using ElementTypes = std::tuple<typename Type<Elements>::type...>; - - // Element type of the Nth array. - template <size_t N> - using ElementType = typename std::tuple_element<N, ElementTypes>::type; - - constexpr explicit LayoutImpl(IntToSize<SizeSeq>... sizes) - : size_{sizes...} {} - - // Alignment of the layout, equal to the strictest alignment of all elements. - // All pointers passed to the methods of layout must be aligned to this value. - static constexpr size_t Alignment() { - return adl_barrier::Max(AlignOf<Elements>::value...); - } - - // Offset in bytes of the Nth array. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Offset<0>() == 0); // The ints starts from 0. - // assert(x.Offset<1>() == 16); // The doubles starts from 16. - // - // Requires: `N <= NumSizes && N < sizeof...(Ts)`. - template <size_t N, EnableIf<N == 0> = 0> - constexpr size_t Offset() const { - return 0; - } - - template <size_t N, EnableIf<N != 0> = 0> - constexpr size_t Offset() const { - static_assert(N < NumOffsets, "Index out of bounds"); - return adl_barrier::Align( - Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1], - ElementAlignment<N>::value); - } - - // Offset in bytes of the array with the specified element type. There must - // be exactly one such array and its zero-based index must be at most - // `NumSizes`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Offset<int>() == 0); // The ints starts from 0. - // assert(x.Offset<double>() == 16); // The doubles starts from 16. - template <class T> - constexpr size_t Offset() const { - return Offset<ElementIndex<T>()>(); - } - - // Offsets in bytes of all arrays for which the offsets are known. - constexpr std::array<size_t, NumOffsets> Offsets() const { - return {{Offset<OffsetSeq>()...}}; - } - - // The number of elements in the Nth array. This is the Nth argument of - // `Layout::Partial()` or `Layout::Layout()` (zero-based). - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Size<0>() == 3); - // assert(x.Size<1>() == 4); - // - // Requires: `N < NumSizes`. - template <size_t N> - constexpr size_t Size() const { - static_assert(N < NumSizes, "Index out of bounds"); - return size_[N]; - } - - // The number of elements in the array with the specified element type. - // There must be exactly one such array and its zero-based index must be - // at most `NumSizes`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Size<int>() == 3); - // assert(x.Size<double>() == 4); - template <class T> - constexpr size_t Size() const { - return Size<ElementIndex<T>()>(); - } - - // The number of elements of all arrays for which they are known. - constexpr std::array<size_t, NumSizes> Sizes() const { - return {{Size<SizeSeq>()...}}; - } - - // Pointer to the beginning of the Nth array. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // int* ints = x.Pointer<0>(p); - // double* doubles = x.Pointer<1>(p); - // - // Requires: `N <= NumSizes && N < sizeof...(Ts)`. - // Requires: `p` is aligned to `Alignment()`. - template <size_t N, class Char> - CopyConst<Char, ElementType<N>>* Pointer(Char* p) const { - using C = typename std::remove_const<Char>::type; - static_assert( - std::is_same<C, char>() || std::is_same<C, unsigned char>() || - std::is_same<C, signed char>(), - "The argument must be a pointer to [const] [signed|unsigned] char"); - constexpr size_t alignment = Alignment(); - (void)alignment; - assert(reinterpret_cast<uintptr_t>(p) % alignment == 0); - return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>()); - } - - // Pointer to the beginning of the array with the specified element type. - // There must be exactly one such array and its zero-based index must be at - // most `NumSizes`. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // int* ints = x.Pointer<int>(p); - // double* doubles = x.Pointer<double>(p); - // - // Requires: `p` is aligned to `Alignment()`. - template <class T, class Char> - CopyConst<Char, T>* Pointer(Char* p) const { - return Pointer<ElementIndex<T>()>(p); - } - - // Pointers to all arrays for which pointers are known. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // - // int* ints; - // double* doubles; - // std::tie(ints, doubles) = x.Pointers(p); - // - // Requires: `p` is aligned to `Alignment()`. - // - // Note: We're not using ElementType alias here because it does not compile - // under MSVC. - template <class Char> - std::tuple<CopyConst< - Char, typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...> - Pointers(Char* p) const { - return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>( - Pointer<OffsetSeq>(p)...); - } - - // The Nth array. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // Span<int> ints = x.Slice<0>(p); - // Span<double> doubles = x.Slice<1>(p); - // - // Requires: `N < NumSizes`. - // Requires: `p` is aligned to `Alignment()`. - template <size_t N, class Char> - SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const { - return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>()); - } - - // The array with the specified element type. There must be exactly one - // such array and its zero-based index must be less than `NumSizes`. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // Span<int> ints = x.Slice<int>(p); - // Span<double> doubles = x.Slice<double>(p); - // - // Requires: `p` is aligned to `Alignment()`. - template <class T, class Char> - SliceType<CopyConst<Char, T>> Slice(Char* p) const { - return Slice<ElementIndex<T>()>(p); - } - - // All arrays with known sizes. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // - // Span<int> ints; - // Span<double> doubles; - // std::tie(ints, doubles) = x.Slices(p); - // - // Requires: `p` is aligned to `Alignment()`. - // - // Note: We're not using ElementType alias here because it does not compile - // under MSVC. - template <class Char> - std::tuple<SliceType<CopyConst< - Char, typename std::tuple_element<SizeSeq, ElementTypes>::type>>...> - Slices(Char* p) const { - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63875 (fixed - // in 6.1). - (void)p; - return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>( - Slice<SizeSeq>(p)...); - } - - // The size of the allocation that fits all arrays. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes - // - // Requires: `NumSizes == sizeof...(Ts)`. - constexpr size_t AllocSize() const { - static_assert(NumTypes == NumSizes, "You must specify sizes of all fields"); - return Offset<NumTypes - 1>() + - SizeOf<ElementType<NumTypes - 1>>() * size_[NumTypes - 1]; - } - - // If built with --config=asan, poisons padding bytes (if any) in the - // allocation. The pointer must point to a memory block at least - // `AllocSize()` bytes in length. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // Requires: `p` is aligned to `Alignment()`. - template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0> - void PoisonPadding(const Char* p) const { - Pointer<0>(p); // verify the requirements on `Char` and `p` - } - - template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0> - void PoisonPadding(const Char* p) const { - static_assert(N < NumOffsets, "Index out of bounds"); - (void)p; -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - PoisonPadding<Char, N - 1>(p); - // The `if` is an optimization. It doesn't affect the observable behaviour. - if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) { - size_t start = - Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1]; - ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start); - } -#endif - } - - // Human-readable description of the memory layout. Useful for debugging. - // Slow. - // - // // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed - // // by an unknown number of doubles. - // auto x = Layout<char, int, double>::Partial(5, 3); - // assert(x.DebugString() == - // "@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)"); - // - // Each field is in the following format: @offset<type>(sizeof)[size] (<type> - // may be missing depending on the target platform). For example, - // @8<int>(4)[3] means that at offset 8 we have an array of ints, where each - // int is 4 bytes, and we have 3 of those ints. The size of the last field may - // be missing (as in the example above). Only fields with known offsets are - // described. Type names may differ across platforms: one compiler might - // produce "unsigned*" where another produces "unsigned int *". - std::string DebugString() const { - const auto offsets = Offsets(); - const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>()...}; - const std::string types[] = { - adl_barrier::TypeName<ElementType<OffsetSeq>>()...}; - std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")"); - for (size_t i = 0; i != NumOffsets - 1; ++i) { - absl::StrAppend(&res, "[", size_[i], "]; @", offsets[i + 1], types[i + 1], - "(", sizes[i + 1], ")"); - } - // NumSizes is a constant that may be zero. Some compilers cannot see that - // inside the if statement "size_[NumSizes - 1]" must be valid. - int last = static_cast<int>(NumSizes) - 1; - if (NumTypes == NumSizes && last >= 0) { - absl::StrAppend(&res, "[", size_[last], "]"); - } - return res; - } - - private: - // Arguments of `Layout::Partial()` or `Layout::Layout()`. - size_t size_[NumSizes > 0 ? NumSizes : 1]; -}; - -template <size_t NumSizes, class... Ts> -using LayoutType = LayoutImpl< - std::tuple<Ts...>, absl::make_index_sequence<NumSizes>, - absl::make_index_sequence<adl_barrier::Min(sizeof...(Ts), NumSizes + 1)>>; - -} // namespace internal_layout - -// Descriptor of arrays of various types and sizes laid out in memory one after -// another. See the top of the file for documentation. -// -// Check out the public API of internal_layout::LayoutImpl above. The type is -// internal to the library but its methods are public, and they are inherited -// by `Layout`. -template <class... Ts> -class Layout : public internal_layout::LayoutType<sizeof...(Ts), Ts...> { - public: - static_assert(sizeof...(Ts) > 0, "At least one field is required"); - static_assert( - absl::conjunction<internal_layout::IsLegalElementType<Ts>...>::value, - "Invalid element type (see IsLegalElementType)"); - - // The result type of `Partial()` with `NumSizes` arguments. - template <size_t NumSizes> - using PartialType = internal_layout::LayoutType<NumSizes, Ts...>; - - // `Layout` knows the element types of the arrays we want to lay out in - // memory but not the number of elements in each array. - // `Partial(size1, ..., sizeN)` allows us to specify the latter. The - // resulting immutable object can be used to obtain pointers to the - // individual arrays. - // - // It's allowed to pass fewer array sizes than the number of arrays. E.g., - // if all you need is to the offset of the second array, you only need to - // pass one argument -- the number of elements in the first array. - // - // // int[3] followed by 4 bytes of padding and an unknown number of - // // doubles. - // auto x = Layout<int, double>::Partial(3); - // // doubles start at byte 16. - // assert(x.Offset<1>() == 16); - // - // If you know the number of elements in all arrays, you can still call - // `Partial()` but it's more convenient to use the constructor of `Layout`. - // - // Layout<int, double> x(3, 5); - // - // Note: The sizes of the arrays must be specified in number of elements, - // not in bytes. - // - // Requires: `sizeof...(Sizes) <= sizeof...(Ts)`. - // Requires: all arguments are convertible to `size_t`. - template <class... Sizes> - static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) { - static_assert(sizeof...(Sizes) <= sizeof...(Ts), ""); - return PartialType<sizeof...(Sizes)>(absl::forward<Sizes>(sizes)...); - } - - // Creates a layout with the sizes of all arrays specified. If you know - // only the sizes of the first N arrays (where N can be zero), you can use - // `Partial()` defined above. The constructor is essentially equivalent to - // calling `Partial()` and passing in all array sizes; the constructor is - // provided as a convenient abbreviation. - // - // Note: The sizes of the arrays must be specified in number of elements, - // not in bytes. - constexpr explicit Layout(internal_layout::TypeToSize<Ts>... sizes) - : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {} -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/layout_test.cc b/third_party/abseil_cpp/absl/container/internal/layout_test.cc deleted file mode 100644 index 1d7158ffc0b9..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/layout_test.cc +++ /dev/null @@ -1,1635 +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/layout.h" - -// 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> -#include <type_traits> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::absl::Span; -using ::testing::ElementsAre; - -size_t Distance(const void* from, const void* to) { - ABSL_RAW_CHECK(from <= to, "Distance must be non-negative"); - return static_cast<const char*>(to) - static_cast<const char*>(from); -} - -template <class Expected, class Actual> -Expected Type(Actual val) { - static_assert(std::is_same<Expected, Actual>(), ""); - return val; -} - -// Helper classes to test different size and alignments. -struct alignas(8) Int128 { - uint64_t a, b; - friend bool operator==(Int128 lhs, Int128 rhs) { - return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b); - } - - static std::string Name() { - return internal_layout::adl_barrier::TypeName<Int128>(); - } -}; - -// int64_t is *not* 8-byte aligned on all platforms! -struct alignas(8) Int64 { - int64_t a; - friend bool operator==(Int64 lhs, Int64 rhs) { - return lhs.a == rhs.a; - } -}; - -// Properties of types that this test relies on. -static_assert(sizeof(int8_t) == 1, ""); -static_assert(alignof(int8_t) == 1, ""); -static_assert(sizeof(int16_t) == 2, ""); -static_assert(alignof(int16_t) == 2, ""); -static_assert(sizeof(int32_t) == 4, ""); -static_assert(alignof(int32_t) == 4, ""); -static_assert(sizeof(Int64) == 8, ""); -static_assert(alignof(Int64) == 8, ""); -static_assert(sizeof(Int128) == 16, ""); -static_assert(alignof(Int128) == 8, ""); - -template <class Expected, class Actual> -void SameType() { - static_assert(std::is_same<Expected, Actual>(), ""); -} - -TEST(Layout, ElementType) { - { - using L = Layout<int32_t>; - SameType<int32_t, L::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial())::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>(); - } - { - using L = Layout<int32_t, int32_t>; - SameType<int32_t, L::ElementType<0>>(); - SameType<int32_t, L::ElementType<1>>(); - SameType<int32_t, decltype(L::Partial())::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial())::ElementType<1>>(); - SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>(); - } - { - using L = Layout<int8_t, int32_t, Int128>; - SameType<int8_t, L::ElementType<0>>(); - SameType<int32_t, L::ElementType<1>>(); - SameType<Int128, L::ElementType<2>>(); - SameType<int8_t, decltype(L::Partial())::ElementType<0>>(); - SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>(); - SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>(); - SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>(); - SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>(); - SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>(); - SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>(); - } -} - -TEST(Layout, ElementTypes) { - { - using L = Layout<int32_t>; - SameType<std::tuple<int32_t>, L::ElementTypes>(); - SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>(); - SameType<std::tuple<int32_t>, decltype(L::Partial(0))::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>(); - } - { - using L = Layout<int8_t, int32_t, Int128>; - SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>(); - SameType<std::tuple<int8_t, int32_t, Int128>, - decltype(L::Partial())::ElementTypes>(); - SameType<std::tuple<int8_t, int32_t, Int128>, - decltype(L::Partial(0))::ElementTypes>(); - SameType<std::tuple<int8_t, int32_t, Int128>, - decltype(L::Partial(0, 0))::ElementTypes>(); - SameType<std::tuple<int8_t, int32_t, Int128>, - decltype(L::Partial(0, 0, 0))::ElementTypes>(); - } -} - -TEST(Layout, OffsetByIndex) { - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial().Offset<0>()); - EXPECT_EQ(0, L::Partial(3).Offset<0>()); - EXPECT_EQ(0, L(3).Offset<0>()); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(0, L::Partial().Offset<0>()); - EXPECT_EQ(0, L::Partial(3).Offset<0>()); - EXPECT_EQ(12, L::Partial(3).Offset<1>()); - EXPECT_EQ(0, L::Partial(3, 5).Offset<0>()); - EXPECT_EQ(12, L::Partial(3, 5).Offset<1>()); - EXPECT_EQ(0, L(3, 5).Offset<0>()); - EXPECT_EQ(12, L(3, 5).Offset<1>()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(0, L::Partial().Offset<0>()); - EXPECT_EQ(0, L::Partial(0).Offset<0>()); - EXPECT_EQ(0, L::Partial(0).Offset<1>()); - EXPECT_EQ(0, L::Partial(1).Offset<0>()); - EXPECT_EQ(4, L::Partial(1).Offset<1>()); - EXPECT_EQ(0, L::Partial(5).Offset<0>()); - EXPECT_EQ(8, L::Partial(5).Offset<1>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<0>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<1>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<2>()); - EXPECT_EQ(0, L::Partial(1, 0).Offset<0>()); - EXPECT_EQ(4, L::Partial(1, 0).Offset<1>()); - EXPECT_EQ(8, L::Partial(1, 0).Offset<2>()); - EXPECT_EQ(0, L::Partial(5, 3).Offset<0>()); - EXPECT_EQ(8, L::Partial(5, 3).Offset<1>()); - EXPECT_EQ(24, L::Partial(5, 3).Offset<2>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>()); - EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>()); - EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>()); - EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>()); - EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>()); - EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>()); - EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>()); - EXPECT_EQ(0, L(5, 3, 1).Offset<0>()); - EXPECT_EQ(24, L(5, 3, 1).Offset<2>()); - EXPECT_EQ(8, L(5, 3, 1).Offset<1>()); - } -} - -TEST(Layout, OffsetByType) { - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial().Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(3).Offset<int32_t>()); - EXPECT_EQ(0, L(3).Offset<int32_t>()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(0, L::Partial().Offset<int8_t>()); - EXPECT_EQ(0, L::Partial(0).Offset<int8_t>()); - EXPECT_EQ(0, L::Partial(0).Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(1).Offset<int8_t>()); - EXPECT_EQ(4, L::Partial(1).Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(5).Offset<int8_t>()); - EXPECT_EQ(8, L::Partial(5).Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>()); - EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>()); - EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>()); - EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>()); - EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>()); - EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>()); - EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>()); - EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>()); - EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>()); - EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>()); - EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>()); - EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>()); - EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>()); - EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>()); - EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>()); - EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>()); - EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>()); - } -} - -TEST(Layout, Offsets) { - { - using L = Layout<int32_t>; - EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); - EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0)); - EXPECT_THAT(L(3).Offsets(), ElementsAre(0)); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); - EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12)); - EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12)); - EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12)); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); - EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4)); - EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8)); - EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0)); - EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8)); - EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24)); - EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0)); - EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8)); - EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); - EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); - } -} - -TEST(Layout, AllocSize) { - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).AllocSize()); - EXPECT_EQ(12, L::Partial(3).AllocSize()); - EXPECT_EQ(12, L(3).AllocSize()); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(32, L::Partial(3, 5).AllocSize()); - EXPECT_EQ(32, L(3, 5).AllocSize()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize()); - EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize()); - EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize()); - EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize()); - EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize()); - EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize()); - EXPECT_EQ(136, L(3, 5, 7).AllocSize()); - } -} - -TEST(Layout, SizeByIndex) { - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Size<0>()); - EXPECT_EQ(3, L::Partial(3).Size<0>()); - EXPECT_EQ(3, L(3).Size<0>()); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(0, L::Partial(0).Size<0>()); - EXPECT_EQ(3, L::Partial(3).Size<0>()); - EXPECT_EQ(3, L::Partial(3, 5).Size<0>()); - EXPECT_EQ(5, L::Partial(3, 5).Size<1>()); - EXPECT_EQ(3, L(3, 5).Size<0>()); - EXPECT_EQ(5, L(3, 5).Size<1>()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Size<0>()); - EXPECT_EQ(3, L::Partial(3, 5).Size<0>()); - EXPECT_EQ(5, L::Partial(3, 5).Size<1>()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>()); - EXPECT_EQ(3, L(3, 5, 7).Size<0>()); - EXPECT_EQ(5, L(3, 5, 7).Size<1>()); - EXPECT_EQ(7, L(3, 5, 7).Size<2>()); - } -} - -TEST(Layout, SizeByType) { - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Size<int32_t>()); - EXPECT_EQ(3, L::Partial(3).Size<int32_t>()); - EXPECT_EQ(3, L(3).Size<int32_t>()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Size<int8_t>()); - EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>()); - EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>()); - EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>()); - EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>()); - EXPECT_EQ(7, L(3, 5, 7).Size<Int128>()); - } -} - -TEST(Layout, Sizes) { - { - using L = Layout<int32_t>; - EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); - EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); - EXPECT_THAT(L(3).Sizes(), ElementsAre(3)); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); - EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); - EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5)); - EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5)); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); - EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); - EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5)); - EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); - EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); - } -} - -TEST(Layout, PointerByIndex) { - 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<0>(p)))); - EXPECT_EQ(0, - Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p)))); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, - Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p)))); - EXPECT_EQ(12, - Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p)))); - EXPECT_EQ( - 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p)))); - EXPECT_EQ( - 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p)))); - EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p)))); - } - { - 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 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(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(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 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(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(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)))); - 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)))); - EXPECT_EQ( - 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p)))); - EXPECT_EQ( - 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p)))); - EXPECT_EQ( - 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)))); - 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)))); - } -} - -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(3).Pointer<int32_t>(p)))); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ( - 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p)))); - EXPECT_EQ( - 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p)))); - EXPECT_EQ( - 0, - Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p)))); - EXPECT_EQ( - 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p)))); - EXPECT_EQ( - 4, - Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p)))); - EXPECT_EQ( - 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p)))); - EXPECT_EQ( - 8, - Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p)))); - EXPECT_EQ( - 0, - Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int32_t*>( - L::Partial(0, 0).Pointer<int32_t>(p)))); - EXPECT_EQ( - 0, - Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p)))); - EXPECT_EQ( - 0, - Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p)))); - EXPECT_EQ(4, Distance(p, Type<const int32_t*>( - L::Partial(1, 0).Pointer<int32_t>(p)))); - EXPECT_EQ( - 8, - Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p)))); - EXPECT_EQ( - 0, - Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p)))); - EXPECT_EQ(8, Distance(p, Type<const int32_t*>( - L::Partial(5, 3).Pointer<int32_t>(p)))); - EXPECT_EQ( - 24, - Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int8_t*>( - L::Partial(0, 0, 0).Pointer<int8_t>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int32_t*>( - L::Partial(0, 0, 0).Pointer<int32_t>(p)))); - EXPECT_EQ(0, Distance(p, Type<const Int128*>( - L::Partial(0, 0, 0).Pointer<Int128>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int8_t*>( - L::Partial(1, 0, 0).Pointer<int8_t>(p)))); - EXPECT_EQ(4, Distance(p, Type<const int32_t*>( - L::Partial(1, 0, 0).Pointer<int32_t>(p)))); - EXPECT_EQ(8, Distance(p, Type<const Int128*>( - L::Partial(1, 0, 0).Pointer<Int128>(p)))); - EXPECT_EQ(0, Distance(p, Type<const int8_t*>( - L::Partial(5, 3, 1).Pointer<int8_t>(p)))); - EXPECT_EQ(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(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)))); - } -} - -TEST(Layout, MutablePointerByIndex) { - alignas(max_align_t) unsigned char p[100]; - { - using L = Layout<int32_t>; - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p)))); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p)))); - EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p)))); - EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p)))); - EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p)))); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p)))); - EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p)))); - EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p)))); - EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p)))); - EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p)))); - EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p)))); - EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p)))); - 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<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(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(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)))); - } -} - -TEST(Layout, MutablePointerByType) { - alignas(max_align_t) unsigned char p[100]; - { - 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(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<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(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(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(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(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<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( - 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( - 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(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)))); - } -} - -TEST(Layout, Pointers) { - alignas(max_align_t) const unsigned char p[100] = {}; - using L = Layout<int8_t, int8_t, Int128>; - { - const auto x = L::Partial(); - EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)), - Type<std::tuple<const int8_t*>>(x.Pointers(p))); - } - { - const auto x = L::Partial(1); - EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), - (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p)))); - } - { - const auto x = L::Partial(1, 2); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( - x.Pointers(p)))); - } - { - const auto x = L::Partial(1, 2, 3); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( - x.Pointers(p)))); - } - { - const L x(1, 2, 3); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( - x.Pointers(p)))); - } -} - -TEST(Layout, MutablePointers) { - alignas(max_align_t) unsigned char p[100]; - using L = Layout<int8_t, int8_t, Int128>; - { - const auto x = L::Partial(); - EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)), - Type<std::tuple<int8_t*>>(x.Pointers(p))); - } - { - const auto x = L::Partial(1); - EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), - (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p)))); - } - { - const auto x = L::Partial(1, 2); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); - } - { - const auto x = L::Partial(1, 2, 3); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); - } - { - const L x(1, 2, 3); - EXPECT_EQ( - std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), - (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); - } -} - -TEST(Layout, SliceByIndexSize) { - alignas(max_align_t) const unsigned char p[100] = {}; - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size()); - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(3, L(3).Slice<0>(p).size()); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); - EXPECT_EQ(5, L(3, 5).Slice<1>(p).size()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size()); - EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size()); - EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size()); - EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size()); - } -} - -TEST(Layout, SliceByTypeSize) { - alignas(max_align_t) const unsigned char p[100] = {}; - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L(3).Slice<int32_t>(p).size()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size()); - EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size()); - EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size()); - } -} - -TEST(Layout, MutableSliceByIndexSize) { - alignas(max_align_t) unsigned char p[100]; - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size()); - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(3, L(3).Slice<0>(p).size()); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); - EXPECT_EQ(5, L(3, 5).Slice<1>(p).size()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size()); - EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size()); - EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size()); - EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size()); - } -} - -TEST(Layout, MutableSliceByTypeSize) { - alignas(max_align_t) unsigned char p[100]; - { - using L = Layout<int32_t>; - EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L(3).Slice<int32_t>(p).size()); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size()); - EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size()); - EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size()); - EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size()); - EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size()); - EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size()); - } -} - -TEST(Layout, SliceByIndexData) { - alignas(max_align_t) const unsigned char p[100] = {}; - { - using L = Layout<int32_t>; - EXPECT_EQ( - 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())); - } - { - using L = Layout<int32_t, int32_t>; - 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::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())); - } - { - 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())); - 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 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())); - EXPECT_EQ( - 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())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 4, - Distance( - p, - Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data())); - EXPECT_EQ( - 8, - Distance( - p, - Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data())); - EXPECT_EQ( - 24, - Distance( - p, - Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data())); - EXPECT_EQ( - 8, - Distance( - 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())); - 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())); - } -} - -TEST(Layout, SliceByTypeData) { - alignas(max_align_t) const unsigned char p[100] = {}; - { - using L = Layout<int32_t>; - EXPECT_EQ( - 0, - Distance( - 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())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data())); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, - Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>( - L::Partial(0, 0).Slice<int32_t>(p)) - .data())); - 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())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)) - .data())); - EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>( - L::Partial(5, 3).Slice<int32_t>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( - L::Partial(0, 0, 0).Slice<int8_t>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>( - L::Partial(0, 0, 0).Slice<int32_t>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>( - L::Partial(0, 0, 0).Slice<Int128>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( - L::Partial(1, 0, 0).Slice<int8_t>(p)) - .data())); - EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>( - L::Partial(1, 0, 0).Slice<int32_t>(p)) - .data())); - EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>( - L::Partial(1, 0, 0).Slice<Int128>(p)) - .data())); - EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( - L::Partial(5, 3, 1).Slice<int8_t>(p)) - .data())); - EXPECT_EQ(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( - 0, - 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())); - } -} - -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(3).Slice<0>(p)).data())); - } - { - using L = Layout<int32_t, int32_t>; - EXPECT_EQ( - 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data())); - EXPECT_EQ( - 12, - Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data())); - EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data())); - EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data())); - } - { - using L = Layout<int8_t, int32_t, Int128>; - EXPECT_EQ( - 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data())); - EXPECT_EQ( - 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data())); - EXPECT_EQ( - 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 4, - Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data())); - EXPECT_EQ( - 8, - Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data())); - EXPECT_EQ( - 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())); - 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())); - 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())); - } -} - -TEST(Layout, MutableSliceByTypeData) { - 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<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())); - } - { - 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())); - EXPECT_EQ( - 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())); - EXPECT_EQ( - 0, - 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())); - EXPECT_EQ( - 0, - 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())); - EXPECT_EQ( - 0, - 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())); - EXPECT_EQ( - 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())); - 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())); - EXPECT_EQ( - 4, - Distance( - 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())); - EXPECT_EQ( - 24, - Distance( - p, - Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data())); - 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())); - 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())); - } -} - -MATCHER_P(IsSameSlice, slice, "") { - return arg.size() == slice.size() && arg.data() == slice.data(); -} - -template <typename... M> -class TupleMatcher { - public: - explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {} - - template <typename Tuple> - bool MatchAndExplain(const Tuple& p, - testing::MatchResultListener* /* listener */) const { - static_assert(std::tuple_size<Tuple>::value == sizeof...(M), ""); - return MatchAndExplainImpl( - p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{}); - } - - // For the matcher concept. Left empty as we don't really need the diagnostics - // right now. - void DescribeTo(::std::ostream* os) const {} - void DescribeNegationTo(::std::ostream* os) const {} - - private: - template <typename Tuple, size_t... Is> - bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const { - // Using std::min as a simple variadic "and". - return std::min( - {true, testing::SafeMatcherCast< - const typename std::tuple_element<Is, Tuple>::type&>( - std::get<Is>(matchers_)) - .Matches(std::get<Is>(p))...}); - } - - std::tuple<M...> matchers_; -}; - -template <typename... M> -testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) { - return testing::MakePolymorphicMatcher( - TupleMatcher<M...>(std::move(matchers)...)); -} - -TEST(Layout, Slices) { - alignas(max_align_t) const unsigned char p[100] = {}; - using L = Layout<int8_t, int8_t, Int128>; - { - const auto x = L::Partial(); - EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple()); - } - { - const auto x = L::Partial(1); - EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)), - Tuple(IsSameSlice(x.Slice<0>(p)))); - } - { - const auto x = L::Partial(1, 2); - EXPECT_THAT( - (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))), - Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)))); - } - { - const auto x = L::Partial(1, 2, 3); - EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>, - Span<const 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<const int8_t>, Span<const int8_t>, - Span<const Int128>>>(x.Slices(p))), - Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), - IsSameSlice(x.Slice<2>(p)))); - } -} - -TEST(Layout, MutableSlices) { - alignas(max_align_t) unsigned char p[100] = {}; - using L = Layout<int8_t, int8_t, Int128>; - { - const auto x = L::Partial(); - EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple()); - } - { - const auto x = L::Partial(1); - EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)), - Tuple(IsSameSlice(x.Slice<0>(p)))); - } - { - const auto x = L::Partial(1, 2); - EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))), - Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)))); - } - { - 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)))); - } - { - 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)))); - } -} - -TEST(Layout, UnalignedTypes) { - constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3); - alignas(max_align_t) unsigned char p[x.AllocSize() + 1]; - EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4)); -} - -TEST(Layout, CustomAlignment) { - constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2); - alignas(max_align_t) unsigned char p[x.AllocSize()]; - EXPECT_EQ(10, x.AllocSize()); - EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8)); -} - -TEST(Layout, OverAligned) { - constexpr size_t M = alignof(max_align_t); - constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3); - alignas(2 * M) unsigned char p[x.AllocSize()]; - EXPECT_EQ(2 * M + 3, x.AllocSize()); - EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M)); -} - -TEST(Layout, Alignment) { - static_assert(Layout<int8_t>::Alignment() == 1, ""); - static_assert(Layout<int32_t>::Alignment() == 4, ""); - static_assert(Layout<Int64>::Alignment() == 8, ""); - static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, ""); - static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, ""); - static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, ""); - static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, ""); - static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, ""); - static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, ""); - static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, ""); -} - -TEST(Layout, ConstexprPartial) { - constexpr size_t M = alignof(max_align_t); - constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3); - static_assert(x.Partial(1).template Offset<1>() == 2 * M, ""); -} -// [from, to) -struct Region { - size_t from; - size_t to; -}; - -void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) { -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - for (size_t i = 0; i != n; ++i) { - EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i)); - } -#endif -} - -template <size_t N> -void ExpectPoisoned(const unsigned char (&buf)[N], - std::initializer_list<Region> reg) { - size_t prev = 0; - for (const Region& r : reg) { - ExpectRegionPoisoned(buf + prev, r.from - prev, false); - ExpectRegionPoisoned(buf + r.from, r.to - r.from, true); - prev = r.to; - } - ExpectRegionPoisoned(buf + prev, N - prev, false); -} - -TEST(Layout, PoisonPadding) { - using L = Layout<int8_t, Int64, int32_t, Int128>; - - constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize(); - { - constexpr auto x = L::Partial(); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {}); - } - { - constexpr auto x = L::Partial(1); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {{1, 8}}); - } - { - constexpr auto x = L::Partial(1, 2); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {{1, 8}}); - } - { - constexpr auto x = L::Partial(1, 2, 3); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {{1, 8}, {36, 40}}); - } - { - constexpr auto x = L::Partial(1, 2, 3, 4); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {{1, 8}, {36, 40}}); - } - { - constexpr L x(1, 2, 3, 4); - alignas(max_align_t) const unsigned char c[n] = {}; - x.PoisonPadding(c); - EXPECT_EQ(x.Slices(c), x.Slices(c)); - ExpectPoisoned(c, {{1, 8}, {36, 40}}); - } -} - -TEST(Layout, DebugString) { - { - constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(); - EXPECT_EQ("@0<signed char>(1)", x.DebugString()); - } - { - constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1); - EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString()); - } - { - constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2); - EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)", - x.DebugString()); - } - { - 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" + - Int128::Name() + "(16)", - x.DebugString()); - } - { - 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" + - Int128::Name() + "(16)[4]", - x.DebugString()); - } - { - constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4); - EXPECT_EQ( - "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " - "@16" + - Int128::Name() + "(16)[4]", - x.DebugString()); - } -} - -TEST(Layout, CharTypes) { - constexpr Layout<int32_t> x(1); - alignas(max_align_t) char c[x.AllocSize()] = {}; - alignas(max_align_t) unsigned char uc[x.AllocSize()] = {}; - alignas(max_align_t) signed char sc[x.AllocSize()] = {}; - alignas(max_align_t) const char cc[x.AllocSize()] = {}; - alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {}; - alignas(max_align_t) const signed char csc[x.AllocSize()] = {}; - - Type<int32_t*>(x.Pointer<0>(c)); - Type<int32_t*>(x.Pointer<0>(uc)); - Type<int32_t*>(x.Pointer<0>(sc)); - Type<const int32_t*>(x.Pointer<0>(cc)); - Type<const int32_t*>(x.Pointer<0>(cuc)); - Type<const int32_t*>(x.Pointer<0>(csc)); - - Type<int32_t*>(x.Pointer<int32_t>(c)); - Type<int32_t*>(x.Pointer<int32_t>(uc)); - Type<int32_t*>(x.Pointer<int32_t>(sc)); - Type<const int32_t*>(x.Pointer<int32_t>(cc)); - Type<const int32_t*>(x.Pointer<int32_t>(cuc)); - Type<const int32_t*>(x.Pointer<int32_t>(csc)); - - Type<std::tuple<int32_t*>>(x.Pointers(c)); - Type<std::tuple<int32_t*>>(x.Pointers(uc)); - Type<std::tuple<int32_t*>>(x.Pointers(sc)); - Type<std::tuple<const int32_t*>>(x.Pointers(cc)); - Type<std::tuple<const int32_t*>>(x.Pointers(cuc)); - Type<std::tuple<const int32_t*>>(x.Pointers(csc)); - - Type<Span<int32_t>>(x.Slice<0>(c)); - Type<Span<int32_t>>(x.Slice<0>(uc)); - Type<Span<int32_t>>(x.Slice<0>(sc)); - Type<Span<const int32_t>>(x.Slice<0>(cc)); - Type<Span<const int32_t>>(x.Slice<0>(cuc)); - Type<Span<const int32_t>>(x.Slice<0>(csc)); - - Type<std::tuple<Span<int32_t>>>(x.Slices(c)); - Type<std::tuple<Span<int32_t>>>(x.Slices(uc)); - Type<std::tuple<Span<int32_t>>>(x.Slices(sc)); - Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)); - Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc)); - Type<std::tuple<Span<const int32_t>>>(x.Slices(csc)); -} - -TEST(Layout, ConstElementType) { - constexpr Layout<const int32_t> x(1); - alignas(int32_t) char c[x.AllocSize()] = {}; - const char* cc = c; - const int32_t* p = reinterpret_cast<const int32_t*>(cc); - - EXPECT_EQ(alignof(int32_t), x.Alignment()); - - EXPECT_EQ(0, x.Offset<0>()); - EXPECT_EQ(0, x.Offset<const int32_t>()); - - EXPECT_THAT(x.Offsets(), ElementsAre(0)); - - EXPECT_EQ(1, x.Size<0>()); - EXPECT_EQ(1, x.Size<const int32_t>()); - - EXPECT_THAT(x.Sizes(), ElementsAre(1)); - - EXPECT_EQ(sizeof(int32_t), x.AllocSize()); - - EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c))); - EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc))); - - EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c))); - EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc))); - - EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p)); - EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p)); - - EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)), - IsSameSlice(Span<const int32_t>(p, 1))); - EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)), - IsSameSlice(Span<const int32_t>(p, 1))); - - EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)), - IsSameSlice(Span<const int32_t>(p, 1))); - EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)), - IsSameSlice(Span<const int32_t>(p, 1))); - - EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)), - Tuple(IsSameSlice(Span<const int32_t>(p, 1)))); - EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)), - Tuple(IsSameSlice(Span<const int32_t>(p, 1)))); -} - -namespace example { - -// Immutable move-only string with sizeof equal to sizeof(void*). The string -// size and the characters are kept in the same heap allocation. -class CompactString { - public: - CompactString(const char* s = "") { // NOLINT - const size_t size = strlen(s); - // size_t[1], followed by char[size + 1]. - // This statement doesn't allocate memory. - const L layout(1, size + 1); - // AllocSize() tells us how much memory we need to allocate for all our - // data. - p_.reset(new unsigned char[layout.AllocSize()]); - // If running under ASAN, mark the padding bytes, if any, to catch memory - // errors. - layout.PoisonPadding(p_.get()); - // Store the size in the allocation. - // Pointer<size_t>() is a synonym for Pointer<0>(). - *layout.Pointer<size_t>(p_.get()) = size; - // Store the characters in the allocation. - memcpy(layout.Pointer<char>(p_.get()), s, size + 1); - } - - size_t size() const { - // Equivalent to reinterpret_cast<size_t&>(*p). - return *L::Partial().Pointer<size_t>(p_.get()); - } - - const char* c_str() const { - // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)). - // The argument in Partial(1) specifies that we have size_t[1] in front of - // the characters. - return L::Partial(1).Pointer<char>(p_.get()); - } - - private: - // Our heap allocation contains a size_t followed by an array of chars. - using L = Layout<size_t, char>; - std::unique_ptr<unsigned char[]> p_; -}; - -TEST(CompactString, Works) { - CompactString s = "hello"; - EXPECT_EQ(5, s.size()); - EXPECT_STREQ("hello", s.c_str()); -} - -} // namespace example - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/node_hash_policy.h b/third_party/abseil_cpp/absl/container/internal/node_hash_policy.h deleted file mode 100644 index 4617162f0b32..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/node_hash_policy.h +++ /dev/null @@ -1,92 +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. -// -// Adapts a policy for nodes. -// -// The node policy should model: -// -// struct Policy { -// // Returns a new node allocated and constructed using the allocator, using -// // the specified arguments. -// template <class Alloc, class... Args> -// value_type* new_element(Alloc* alloc, Args&&... args) const; -// -// // Destroys and deallocates node using the allocator. -// template <class Alloc> -// void delete_element(Alloc* alloc, value_type* node) const; -// }; -// -// It may also optionally define `value()` and `apply()`. For documentation on -// these, see hash_policy_traits.h. - -#ifndef ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_ -#define ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_ - -#include <cassert> -#include <cstddef> -#include <memory> -#include <type_traits> -#include <utility> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class Reference, class Policy> -struct node_hash_policy { - static_assert(std::is_lvalue_reference<Reference>::value, ""); - - using slot_type = typename std::remove_cv< - typename std::remove_reference<Reference>::type>::type*; - - template <class Alloc, class... Args> - static void construct(Alloc* alloc, slot_type* slot, Args&&... args) { - *slot = Policy::new_element(alloc, std::forward<Args>(args)...); - } - - template <class Alloc> - static void destroy(Alloc* alloc, slot_type* slot) { - Policy::delete_element(alloc, *slot); - } - - template <class Alloc> - static void transfer(Alloc*, slot_type* new_slot, slot_type* old_slot) { - *new_slot = *old_slot; - } - - static size_t space_used(const slot_type* slot) { - if (slot == nullptr) return Policy::element_space_used(nullptr); - return Policy::element_space_used(*slot); - } - - static Reference element(slot_type* slot) { return **slot; } - - template <class T, class P = Policy> - static auto value(T* elem) -> decltype(P::value(elem)) { - return P::value(elem); - } - - template <class... Ts, class P = Policy> - static auto apply(Ts&&... ts) -> decltype(P::apply(std::forward<Ts>(ts)...)) { - return P::apply(std::forward<Ts>(ts)...); - } -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/node_hash_policy_test.cc b/third_party/abseil_cpp/absl/container/internal/node_hash_policy_test.cc deleted file mode 100644 index 84aabba96830..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/node_hash_policy_test.cc +++ /dev/null @@ -1,69 +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/node_hash_policy.h" - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_policy_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::testing::Pointee; - -struct Policy : node_hash_policy<int&, Policy> { - using key_type = int; - using init_type = int; - - template <class Alloc> - static int* new_element(Alloc* alloc, int value) { - return new int(value); - } - - template <class Alloc> - static void delete_element(Alloc* alloc, int* elem) { - delete elem; - } -}; - -using NodePolicy = hash_policy_traits<Policy>; - -struct NodeTest : ::testing::Test { - std::allocator<int> alloc; - int n = 53; - int* a = &n; -}; - -TEST_F(NodeTest, ConstructDestroy) { - NodePolicy::construct(&alloc, &a, 42); - EXPECT_THAT(a, Pointee(42)); - NodePolicy::destroy(&alloc, &a); -} - -TEST_F(NodeTest, transfer) { - int s = 42; - int* b = &s; - NodePolicy::transfer(&alloc, &a, &b); - EXPECT_EQ(&s, a); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 0a02757ddfb4..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/raw_hash_map.h +++ /dev/null @@ -1,197 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_ -#define ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_ - -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/throw_delegate.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class Policy, class Hash, class Eq, class Alloc> -class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> { - // P is Policy. It's passed as a template argument to support maps that have - // incomplete types as values, as in unordered_map<K, IncompleteType>. - // MappedReference<> may be a non-reference type. - template <class P> - using MappedReference = decltype(P::value( - std::addressof(std::declval<typename raw_hash_map::reference>()))); - - // MappedConstReference<> may be a non-reference type. - template <class P> - using MappedConstReference = decltype(P::value( - std::addressof(std::declval<typename raw_hash_map::const_reference>()))); - - using KeyArgImpl = - KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>; - - public: - using key_type = typename Policy::key_type; - using mapped_type = typename Policy::mapped_type; - template <class K> - using key_arg = typename KeyArgImpl::template type<K, key_type>; - - static_assert(!std::is_reference<key_type>::value, ""); - // 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; - using const_iterator = typename raw_hash_map::raw_hash_set::const_iterator; - - raw_hash_map() {} - using raw_hash_map::raw_hash_set::raw_hash_set; - - // The last two template parameters ensure that both arguments are rvalues - // (lvalue arguments are handled by the overloads below). This is necessary - // for supporting bitfield arguments. - // - // union { int n : 1; }; - // flat_hash_map<int, int> m; - // m.insert_or_assign(n, n); - template <class K = key_type, class V = mapped_type, K* = nullptr, - V* = nullptr> - std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, V&& v) { - return insert_or_assign_impl(std::forward<K>(k), std::forward<V>(v)); - } - - template <class K = key_type, class V = mapped_type, K* = nullptr> - std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, const V& v) { - return insert_or_assign_impl(std::forward<K>(k), v); - } - - template <class K = key_type, class V = mapped_type, V* = nullptr> - std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, V&& v) { - return insert_or_assign_impl(k, std::forward<V>(v)); - } - - template <class K = key_type, class V = mapped_type> - std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, const V& v) { - return insert_or_assign_impl(k, v); - } - - template <class K = key_type, class V = mapped_type, K* = nullptr, - V* = nullptr> - iterator insert_or_assign(const_iterator, key_arg<K>&& k, V&& v) { - return insert_or_assign(std::forward<K>(k), std::forward<V>(v)).first; - } - - template <class K = key_type, class V = mapped_type, K* = nullptr> - iterator insert_or_assign(const_iterator, key_arg<K>&& k, const V& v) { - return insert_or_assign(std::forward<K>(k), v).first; - } - - template <class K = key_type, class V = mapped_type, V* = nullptr> - iterator insert_or_assign(const_iterator, const key_arg<K>& k, V&& v) { - return insert_or_assign(k, std::forward<V>(v)).first; - } - - template <class K = key_type, class V = mapped_type> - iterator insert_or_assign(const_iterator, const key_arg<K>& k, const V& v) { - return insert_or_assign(k, v).first; - } - - // All `try_emplace()` overloads make the same guarantees regarding rvalue - // arguments as `std::unordered_map::try_emplace()`, namely that these - // functions will not move from rvalue arguments if insertions do not happen. - template <class K = key_type, class... Args, - typename std::enable_if< - !std::is_convertible<K, const_iterator>::value, int>::type = 0, - K* = nullptr> - 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 <class K = key_type, class... Args, - typename std::enable_if< - !std::is_convertible<K, const_iterator>::value, int>::type = 0> - std::pair<iterator, bool> try_emplace(const key_arg<K>& k, Args&&... args) { - return try_emplace_impl(k, std::forward<Args>(args)...); - } - - template <class K = key_type, class... Args, K* = nullptr> - iterator try_emplace(const_iterator, key_arg<K>&& k, Args&&... args) { - return try_emplace(std::forward<K>(k), std::forward<Args>(args)...).first; - } - - template <class K = key_type, class... Args> - iterator try_emplace(const_iterator, const key_arg<K>& k, Args&&... args) { - return try_emplace(k, std::forward<Args>(args)...).first; - } - - template <class K = key_type, class P = Policy> - MappedReference<P> at(const key_arg<K>& key) { - auto it = this->find(key); - if (it == this->end()) { - base_internal::ThrowStdOutOfRange( - "absl::container_internal::raw_hash_map<>::at"); - } - return Policy::value(&*it); - } - - template <class K = key_type, class P = Policy> - MappedConstReference<P> at(const key_arg<K>& key) const { - auto it = this->find(key); - if (it == this->end()) { - base_internal::ThrowStdOutOfRange( - "absl::container_internal::raw_hash_map<>::at"); - } - return Policy::value(&*it); - } - - template <class K = key_type, class P = Policy, K* = nullptr> - MappedReference<P> operator[](key_arg<K>&& key) { - return Policy::value(&*try_emplace(std::forward<K>(key)).first); - } - - template <class K = key_type, class P = Policy> - MappedReference<P> operator[](const key_arg<K>& key) { - return Policy::value(&*try_emplace(key).first); - } - - private: - template <class K, class V> - std::pair<iterator, bool> insert_or_assign_impl(K&& k, V&& v) { - auto res = this->find_or_prepare_insert(k); - if (res.second) - this->emplace_at(res.first, std::forward<K>(k), std::forward<V>(v)); - else - Policy::value(&*this->iterator_at(res.first)) = std::forward<V>(v); - return {this->iterator_at(res.first), res.second}; - } - - template <class K = key_type, class... Args> - std::pair<iterator, bool> try_emplace_impl(K&& k, Args&&... args) { - auto res = this->find_or_prepare_insert(k); - if (res.second) - this->emplace_at(res.first, std::piecewise_construct, - std::forward_as_tuple(std::forward<K>(k)), - std::forward_as_tuple(std::forward<Args>(args)...)); - return {this->iterator_at(res.first), res.second}; - } -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_ 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 deleted file mode 100644 index bfef071f29e6..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/raw_hash_set.cc +++ /dev/null @@ -1,61 +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 <atomic> -#include <cstddef> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -constexpr size_t Group::kWidth; - -// Returns "random" seed. -inline size_t RandomSeed() { -#ifdef ABSL_HAVE_THREAD_LOCAL - static thread_local size_t counter = 0; - size_t value = ++counter; -#else // ABSL_HAVE_THREAD_LOCAL - static std::atomic<size_t> counter(0); - size_t value = counter.fetch_add(1, std::memory_order_relaxed); -#endif // ABSL_HAVE_THREAD_LOCAL - return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter)); -} - -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] == kSentinel); - assert(IsValidCapacity(capacity)); - for (ctrl_t* pos = ctrl; pos != ctrl + capacity + 1; pos += Group::kWidth) { - Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos); - } - // Copy the cloned ctrl bytes. - std::memcpy(ctrl + capacity + 1, ctrl, Group::kWidth); - ctrl[capacity] = kSentinel; -} - - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil_cpp/absl/container/internal/raw_hash_set.h deleted file mode 100644 index 02158c4e0886..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/raw_hash_set.h +++ /dev/null @@ -1,1903 +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. -// -// An open-addressing -// hashtable with quadratic probing. -// -// This is a low level hashtable on top of which different interfaces can be -// implemented, like flat_hash_set, node_hash_set, string_hash_set, etc. -// -// The table interface is similar to that of std::unordered_set. Notable -// differences are that most member functions support heterogeneous keys when -// BOTH the hash and eq functions are marked as transparent. They do so by -// providing a typedef called `is_transparent`. -// -// When heterogeneous lookup is enabled, functions that take key_type act as if -// they have an overload set like: -// -// iterator find(const key_type& key); -// template <class K> -// iterator find(const K& key); -// -// size_type erase(const key_type& key); -// template <class K> -// size_type erase(const K& key); -// -// std::pair<iterator, iterator> equal_range(const key_type& key); -// template <class K> -// std::pair<iterator, iterator> equal_range(const K& key); -// -// When heterogeneous lookup is disabled, only the explicit `key_type` overloads -// exist. -// -// find() also supports passing the hash explicitly: -// -// iterator find(const key_type& key, size_t hash); -// template <class U> -// iterator find(const U& key, size_t hash); -// -// In addition the pointer to element and iterator stability guarantees are -// weaker: all iterators and pointers are invalidated after a new element is -// inserted. -// -// IMPLEMENTATION DETAILS -// -// The table stores elements inline in a slot array. In addition to the slot -// array the table maintains some control state per slot. The extra state is one -// byte per slot and stores empty or deleted marks, or alternatively 7 bits from -// the hash of an occupied slot. The table is split into logical groups of -// slots, like so: -// -// Group 1 Group 2 Group 3 -// +---------------+---------------+---------------+ -// | | | | | | | | | | | | | | | | | | | | | | | | | -// +---------------+---------------+---------------+ -// -// On lookup the hash is split into two parts: -// - H2: 7 bits (those stored in the control bytes) -// - H1: the rest of the bits -// The groups are probed using H1. For each group the slots are matched to H2 in -// parallel. Because H2 is 7 bits (128 states) and the number of slots per group -// is low (8 or 16) in almost all cases a match in H2 is also a lookup hit. -// -// On insert, once the right group is found (as in lookup), its slots are -// filled in order. -// -// On erase a slot is cleared. In case the group did not have any empty slots -// before the erase, the erased slot is marked as deleted. -// -// Groups without empty slots (but maybe with deleted slots) extend the probe -// sequence. The probing algorithm is quadratic. Given N the number of groups, -// the probing function for the i'th probe is: -// -// P(0) = H1 % N -// -// P(i) = (P(i - 1) + i) % N -// -// This probing function guarantees that after N probes, all the groups of the -// table will be probed exactly once. - -#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ -#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ - -#include <algorithm> -#include <cmath> -#include <cstdint> -#include <cstring> -#include <iterator> -#include <limits> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/bits.h" -#include "absl/base/internal/endian.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" -#include "absl/container/internal/common.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/hash_policy_traits.h" -#include "absl/container/internal/hashtable_debug_hooks.h" -#include "absl/container/internal/hashtablez_sampler.h" -#include "absl/container/internal/have_sse.h" -#include "absl/container/internal/layout.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/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: - probe_seq(size_t hash, size_t mask) { - assert(((mask + 1) & mask) == 0 && "not a mask"); - mask_ = mask; - offset_ = hash & mask_; - } - size_t offset() const { return offset_; } - size_t offset(size_t i) const { return (offset_ + i) & mask_; } - - void next() { - index_ += Width; - offset_ += index_; - offset_ &= mask_; - } - // 0-based probe index. The i-th probe in the probe sequence. - size_t index() const { return index_; } - - private: - size_t mask_; - size_t offset_; - size_t index_ = 0; -}; - -template <class ContainerKey, class Hash, class Eq> -struct RequireUsableKey { - template <class PassedKey, class... Args> - std::pair< - decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())), - decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(), - std::declval<const PassedKey&>()))>* - operator()(const PassedKey&, const Args&...) const; -}; - -template <class E, class Policy, class Hash, class Eq, class... Ts> -struct IsDecomposable : std::false_type {}; - -template <class Policy, class Hash, class Eq, class... Ts> -struct IsDecomposable< - absl::void_t<decltype( - Policy::apply(RequireUsableKey<typename Policy::key_type, Hash, Eq>(), - std::declval<Ts>()...))>, - Policy, Hash, Eq, Ts...> : std::true_type {}; - -// TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it. -template <class T> -constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) { - 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> -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 -// indexes of the set bits of a bitmask. When Shift=0 (platforms with SSE), -// this is a true bitmask. On non-SSE, platforms the arithematic used to -// emulate the SSE behavior works in bytes (Shift=3) and leaves each bytes as -// either 0x00 or 0x80. -// -// For example: -// for (int i : BitMask<uint32_t, 16>(0x5)) -> yields 0, 2 -// for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3 -template <class T, int SignificantBits, int Shift = 0> -class BitMask { - static_assert(std::is_unsigned<T>::value, ""); - static_assert(Shift == 0 || Shift == 3, ""); - - public: - // These are useful for unit tests (gunit). - using value_type = int; - using iterator = BitMask; - using const_iterator = BitMask; - - explicit BitMask(T mask) : mask_(mask) {} - BitMask& operator++() { - mask_ &= (mask_ - 1); - return *this; - } - explicit operator bool() const { return mask_ != 0; } - int operator*() const { return LowestBitSet(); } - int LowestBitSet() const { - return container_internal::TrailingZeros(mask_) >> 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); } - - int TrailingZeros() const { - return container_internal::TrailingZeros(mask_) >> Shift; - } - - int LeadingZeros() const { - constexpr int total_significant_bits = SignificantBits << Shift; - constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits; - return container_internal::LeadingZeros(mask_ << extra_bits) >> Shift; - } - - private: - friend bool operator==(const BitMask& a, const BitMask& b) { - return a.mask_ == b.mask_; - } - friend bool operator!=(const BitMask& a, const BitMask& b) { - return a.mask_ != b.mask_; - } - - 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. -enum Ctrl : ctrl_t { - kEmpty = -128, // 0b10000000 - kDeleted = -2, // 0b11111110 - kSentinel = -1, // 0b11111111 -}; -static_assert( - kEmpty & kDeleted & kSentinel & 0x80, - "Special markers need to have the MSB to make checking for them efficient"); -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(~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(). -inline ctrl_t* EmptyGroup() { - 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, ctrl_t* ctrl); - -// Returns a hash seed. -// -// The seed consists of the ctrl_ pointer, which adds enough entropy to ensure -// non-determinism of iteration order in most cases. -inline size_t HashSeed(const ctrl_t* ctrl) { - // The low bits of the pointer have little or no entropy because of - // alignment. We shift the pointer to try to use higher entropy bits. A - // good number seems to be 12 bits, because that aligns with page size. - return reinterpret_cast<uintptr_t>(ctrl) >> 12; -} - -inline size_t H1(size_t hash, const ctrl_t* ctrl) { - return (hash >> 7) ^ HashSeed(ctrl); -} -inline ctrl_t H2(size_t hash) { return hash & 0x7F; } - -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 - -// https://github.com/abseil/abseil-cpp/issues/209 -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853 -// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char -// Work around this by using the portable implementation of Group -// when using -funsigned-char under GCC. -inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) { -#if defined(__GNUC__) && !defined(__clang__) - if (std::is_unsigned<char>::value) { - const __m128i mask = _mm_set1_epi8(0x80); - const __m128i diff = _mm_subs_epi8(b, a); - return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask); - } -#endif - return _mm_cmpgt_epi8(a, b); -} - -struct GroupSse2Impl { - static constexpr size_t kWidth = 16; // the number of slots per group - - explicit GroupSse2Impl(const ctrl_t* pos) { - ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos)); - } - - // Returns a bitmask representing the positions of slots that match hash. - BitMask<uint32_t, kWidth> Match(h2_t hash) const { - auto match = _mm_set1_epi8(hash); - return BitMask<uint32_t, kWidth>( - _mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))); - } - - // 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 kEmpty is -128. - return BitMask<uint32_t, kWidth>( - _mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))); -#else - 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(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(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 - auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs); -#else - auto zero = _mm_setzero_si128(); - auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl); - auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126)); -#endif - _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res); - } - - __m128i ctrl; -}; -#endif // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 - -struct GroupPortableImpl { - static constexpr size_t kWidth = 8; - - explicit GroupPortableImpl(const ctrl_t* pos) - : ctrl(little_endian::Load64(pos)) {} - - BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const { - // For the technique, see: - // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord - // (Determine if a word has a byte equal to n). - // - // Caveat: there are false positives but: - // - they only occur if there is a real match - // - they never occur on kEmpty, kDeleted, kSentinel - // - they will be handled gracefully by subsequent checks in code - // - // Example: - // v = 0x1716151413121110 - // hash = 0x12 - // retval = (v - lsbs) & ~v & msbs = 0x0000000080800000 - constexpr uint64_t msbs = 0x8080808080808080ULL; - constexpr uint64_t lsbs = 0x0101010101010101ULL; - auto x = ctrl ^ (lsbs * hash); - return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & msbs); - } - - BitMask<uint64_t, kWidth, 3> MatchEmpty() const { - constexpr uint64_t msbs = 0x8080808080808080ULL; - return BitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 6)) & msbs); - } - - BitMask<uint64_t, kWidth, 3> MatchEmptyOrDeleted() const { - constexpr uint64_t msbs = 0x8080808080808080ULL; - return BitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 7)) & msbs); - } - - uint32_t CountLeadingEmptyOrDeleted() const { - constexpr uint64_t gaps = 0x00FEFEFEFEFEFEFEULL; - return (TrailingZeros(((~ctrl & (ctrl >> 7)) | gaps) + 1) + 7) >> 3; - } - - void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const { - constexpr uint64_t msbs = 0x8080808080808080ULL; - constexpr uint64_t lsbs = 0x0101010101010101ULL; - auto x = ctrl & msbs; - auto res = (~x + (x >> 7)) & ~lsbs; - little_endian::Store64(dst, res); - } - - uint64_t ctrl; -}; - -#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 -using Group = GroupSse2Impl; -#else -using Group = GroupPortableImpl; -#endif - -template <class Policy, class Hash, class Eq, class Alloc> -class raw_hash_set; - -inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; } - -// PRECONDITION: -// IsValidCapacity(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); - -// 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{} >> LeadingZeros(n) : 1; -} - -// 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` - if (Group::kWidth == 8 && capacity == 7) { - // x-x/8 does not work when x==7. - return 6; - } - return capacity - capacity / 8; -} -// From desired "growth" to a lowerbound of the necessary capacity. -// 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) { - // x+(x-1)/7 does not work when x==7. - return 8; - } - return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7); -} - -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 kEmpty values that do not -// represent a real slot. This is important to take into account on -// find_first_non_full(), where we never try ShouldInsertBackwards() for -// small tables. -inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; } - -inline probe_seq<Group::kWidth> probe(ctrl_t* ctrl, size_t hash, - size_t capacity) { - return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity); -} - -// Probes the raw_hash_set with the probe sequence for hash and returns the -// pointer to the first empty or deleted slot. -// NOTE: this function must work with tables having both kEmpty and kDelete -// in one group. Such tables appears during drop_deletes_without_resize. -// -// This function is very useful when insertions happen and: -// - the input is already a set -// - there are enough slots -// - the element with the hash is not in the table -inline FindInfo find_first_non_full(ctrl_t* ctrl, size_t hash, - size_t capacity) { - auto seq = probe(ctrl, hash, capacity); - while (true) { - Group g{ctrl + seq.offset()}; - auto mask = g.MatchEmptyOrDeleted(); - if (mask) { -#if !defined(NDEBUG) - // We want to add entropy even when ASLR is not enabled. - // In debug build we will randomly insert in either the front or back of - // the group. - // TODO(kfm,sbenza): revisit after we do unconditional mixing - if (!is_small(capacity) && ShouldInsertBackwards(hash, ctrl)) { - return {seq.offset(mask.HighestBitSet()), seq.index()}; - } -#endif - return {seq.offset(mask.LowestBitSet()), seq.index()}; - } - seq.next(); - assert(seq.index() < capacity && "full table!"); - } -} - -// 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). -// -// Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The -// functor should accept a key and return size_t as hash. For best performance -// it is important that the hash function provides high entropy across all bits -// of the hash. -// -// Eq: a (possibly polymorphic) functor that compares two keys for equality. It -// should accept two (of possibly different type) keys and return a bool: true -// 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 -// the storage of the hashtable will be allocated and the elements will be -// constructed and destroyed. -template <class Policy, class Hash, class Eq, class Alloc> -class raw_hash_set { - using PolicyTraits = hash_policy_traits<Policy>; - using KeyArgImpl = - KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>; - - public: - using init_type = typename PolicyTraits::init_type; - using key_type = typename PolicyTraits::key_type; - // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user - // code fixes! - using slot_type = typename PolicyTraits::slot_type; - using allocator_type = Alloc; - using size_type = size_t; - using difference_type = ptrdiff_t; - using hasher = Hash; - using key_equal = Eq; - using policy_type = Policy; - using value_type = typename PolicyTraits::value_type; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = typename absl::allocator_traits< - allocator_type>::template rebind_traits<value_type>::pointer; - using const_pointer = typename absl::allocator_traits< - allocator_type>::template rebind_traits<value_type>::const_pointer; - - // Alias used for heterogeneous lookup functions. - // `key_arg<K>` evaluates to `K` when the functors are transparent and to - // `key_type` otherwise. It permits template argument deduction on `K` for the - // transparent case. - template <class K> - using key_arg = typename KeyArgImpl::template type<K, key_type>; - - private: - // Give an early error when key_type is not hashable/eq. - 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>; - using SlotAllocTraits = typename absl::allocator_traits< - allocator_type>::template rebind_traits<slot_type>; - - static_assert(std::is_lvalue_reference<reference>::value, - "Policy::element() must return a reference"); - - template <typename T> - struct SameAsElementReference - : std::is_same<typename std::remove_cv< - typename std::remove_reference<reference>::type>::type, - typename std::remove_cv< - typename std::remove_reference<T>::type>::type> {}; - - // An enabler for insert(T&&): T must be convertible to init_type or be the - // same as [cv] value_type [ref]. - // Note: we separate SameAsElementReference into its own type to avoid using - // reference unless we need to. MSVC doesn't seem to like it in some - // cases. - template <class T> - using RequiresInsertable = typename std::enable_if< - absl::disjunction<std::is_convertible<T, init_type>, - SameAsElementReference<T>>::value, - int>::type; - - // RequiresNotInit is a workaround for gcc prior to 7.1. - // See https://godbolt.org/g/Y4xsUh. - template <class T> - using RequiresNotInit = - typename std::enable_if<!std::is_same<T, init_type>::value, int>::type; - - template <class... Ts> - using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>; - - public: - static_assert(std::is_same<pointer, value_type*>::value, - "Allocators with custom pointer types are not supported"); - static_assert(std::is_same<const_pointer, const value_type*>::value, - "Allocators with custom pointer types are not supported"); - - class iterator { - friend class raw_hash_set; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = typename raw_hash_set::value_type; - using reference = - absl::conditional_t<PolicyTraits::constant_iterators::value, - const value_type&, value_type&>; - using pointer = absl::remove_reference_t<reference>*; - using difference_type = typename raw_hash_set::difference_type; - - iterator() {} - - // PRECONDITION: not an end() iterator. - reference operator*() const { - AssertIsFull(ctrl_); - return PolicyTraits::element(slot_); - } - - // PRECONDITION: not an end() iterator. - pointer operator->() const { return &operator*(); } - - // PRECONDITION: not an end() iterator. - iterator& operator++() { - AssertIsFull(ctrl_); - ++ctrl_; - ++slot_; - skip_empty_or_deleted(); - return *this; - } - // PRECONDITION: not an end() iterator. - iterator operator++(int) { - auto tmp = *this; - ++*this; - return tmp; - } - - friend bool operator==(const iterator& a, const iterator& b) { - AssertIsValid(a.ctrl_); - AssertIsValid(b.ctrl_); - return a.ctrl_ == b.ctrl_; - } - friend bool operator!=(const iterator& a, const iterator& b) { - return !(a == b); - } - - 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); - } - - void skip_empty_or_deleted() { - while (IsEmptyOrDeleted(*ctrl_)) { - uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted(); - ctrl_ += shift; - slot_ += shift; - } - if (ABSL_PREDICT_FALSE(*ctrl_ == kSentinel)) ctrl_ = nullptr; - } - - ctrl_t* ctrl_ = nullptr; - // To avoid uninitialized member warnings, put slot_ in an anonymous union. - // The member is not initialized on singleton and end iterators. - union { - slot_type* slot_; - }; - }; - - class const_iterator { - friend class raw_hash_set; - - public: - using iterator_category = typename iterator::iterator_category; - using value_type = typename raw_hash_set::value_type; - using reference = typename raw_hash_set::const_reference; - using pointer = typename raw_hash_set::const_pointer; - using difference_type = typename raw_hash_set::difference_type; - - const_iterator() {} - // Implicit construction from iterator. - const_iterator(iterator i) : inner_(std::move(i)) {} - - reference operator*() const { return *inner_; } - pointer operator->() const { return inner_.operator->(); } - - const_iterator& operator++() { - ++inner_; - return *this; - } - const_iterator operator++(int) { return inner_++; } - - friend bool operator==(const const_iterator& a, const const_iterator& b) { - return a.inner_ == b.inner_; - } - friend bool operator!=(const const_iterator& a, const const_iterator& b) { - return !(a == b); - } - - private: - const_iterator(const ctrl_t* ctrl, const slot_type* slot) - : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot)) {} - - iterator inner_; - }; - - using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>; - using insert_return_type = InsertReturnType<iterator, node_type>; - - raw_hash_set() noexcept( - std::is_nothrow_default_constructible<hasher>::value&& - std::is_nothrow_default_constructible<key_equal>::value&& - std::is_nothrow_default_constructible<allocator_type>::value) {} - - explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(), - const key_equal& eq = key_equal(), - const allocator_type& alloc = allocator_type()) - : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) { - if (bucket_count) { - capacity_ = NormalizeCapacity(bucket_count); - initialize_slots(); - } - } - - raw_hash_set(size_t bucket_count, const hasher& hash, - const allocator_type& alloc) - : raw_hash_set(bucket_count, hash, key_equal(), alloc) {} - - raw_hash_set(size_t bucket_count, const allocator_type& alloc) - : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {} - - explicit raw_hash_set(const allocator_type& alloc) - : raw_hash_set(0, hasher(), key_equal(), alloc) {} - - template <class InputIter> - 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(bucket_count, hash, eq, alloc) { - insert(first, last); - } - - template <class InputIter> - raw_hash_set(InputIter first, InputIter last, size_t bucket_count, - const hasher& hash, const allocator_type& alloc) - : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {} - - template <class InputIter> - raw_hash_set(InputIter first, InputIter last, size_t bucket_count, - const allocator_type& alloc) - : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {} - - template <class InputIter> - raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc) - : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {} - - // Instead of accepting std::initializer_list<value_type> as the first - // argument like std::unordered_set<value_type> does, we have two overloads - // that accept std::initializer_list<T> and std::initializer_list<init_type>. - // This is advantageous for performance. - // - // // Turns {"abc", "def"} into std::initializer_list<std::string>, then - // // copies the strings into the set. - // std::unordered_set<std::string> s = {"abc", "def"}; - // - // // Turns {"abc", "def"} into std::initializer_list<const char*>, then - // // copies the strings into the set. - // absl::flat_hash_set<std::string> s = {"abc", "def"}; - // - // The same trick is used in insert(). - // - // The enabler is necessary to prevent this constructor from triggering where - // the copy constructor is meant to be called. - // - // absl::flat_hash_set<int> a, b{a}; - // - // RequiresNotInit<T> is a workaround for gcc prior to 7.1. - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> - raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0, - const hasher& hash = hasher(), const key_equal& eq = key_equal(), - const allocator_type& alloc = allocator_type()) - : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {} - - raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0, - const hasher& hash = hasher(), const key_equal& eq = key_equal(), - const allocator_type& alloc = allocator_type()) - : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {} - - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> - raw_hash_set(std::initializer_list<T> init, size_t bucket_count, - const hasher& hash, const allocator_type& alloc) - : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {} - - raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count, - const hasher& hash, const allocator_type& alloc) - : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {} - - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> - raw_hash_set(std::initializer_list<T> init, size_t bucket_count, - const allocator_type& alloc) - : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {} - - raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count, - const allocator_type& alloc) - : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {} - - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> - raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc) - : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {} - - raw_hash_set(std::initializer_list<init_type> init, - const allocator_type& alloc) - : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {} - - raw_hash_set(const raw_hash_set& that) - : raw_hash_set(that, AllocTraits::select_on_container_copy_construction( - that.alloc_ref())) {} - - raw_hash_set(const raw_hash_set& that, const allocator_type& a) - : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) { - reserve(that.size()); - // Because the table is guaranteed to be empty, we can do something faster - // 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_); - set_ctrl(target.offset, H2(hash)); - emplace_at(target.offset, v); - infoz_.RecordInsert(hash, target.probe_length); - } - size_ = that.size(); - growth_left() -= that.size(); - } - - raw_hash_set(raw_hash_set&& that) noexcept( - std::is_nothrow_copy_constructible<hasher>::value&& - std::is_nothrow_copy_constructible<key_equal>::value&& - std::is_nothrow_copy_constructible<allocator_type>::value) - : ctrl_(absl::exchange(that.ctrl_, EmptyGroup())), - slots_(absl::exchange(that.slots_, nullptr)), - size_(absl::exchange(that.size_, 0)), - capacity_(absl::exchange(that.capacity_, 0)), - 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_(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, that.hash_ref(), that.eq_ref(), a) { - if (a == that.alloc_ref()) { - std::swap(ctrl_, that.ctrl_); - std::swap(slots_, that.slots_); - std::swap(size_, that.size_); - std::swap(capacity_, that.capacity_); - std::swap(growth_left(), that.growth_left()); - std::swap(infoz_, that.infoz_); - } else { - reserve(that.size()); - // Note: this will copy elements of dense_set and unordered_set instead of - // moving them. This can be fixed if it ever becomes an issue. - for (auto& elem : that) insert(std::move(elem)); - } - } - - raw_hash_set& operator=(const raw_hash_set& that) { - raw_hash_set tmp(that, - AllocTraits::propagate_on_container_copy_assignment::value - ? that.alloc_ref() - : alloc_ref()); - swap(tmp); - return *this; - } - - raw_hash_set& operator=(raw_hash_set&& that) noexcept( - absl::allocator_traits<allocator_type>::is_always_equal::value&& - std::is_nothrow_move_assignable<hasher>::value&& - std::is_nothrow_move_assignable<key_equal>::value) { - // TODO(sbenza): We should only use the operations from the noexcept clause - // to make sure we actually adhere to that contract. - return move_assign( - std::move(that), - typename AllocTraits::propagate_on_container_move_assignment()); - } - - ~raw_hash_set() { destroy_slots(); } - - iterator begin() { - auto it = iterator_at(0); - it.skip_empty_or_deleted(); - return it; - } - iterator end() { return {}; } - - const_iterator begin() const { - return const_cast<raw_hash_set*>(this)->begin(); - } - const_iterator end() const { return {}; } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - bool empty() const { return !size(); } - size_t size() const { return size_; } - size_t capacity() const { return capacity_; } - size_t max_size() const { return (std::numeric_limits<size_t>::max)(); } - - ABSL_ATTRIBUTE_REINITIALIZES void clear() { - // Iterating over this container is O(bucket_count()). When bucket_count() - // is much greater than size(), iteration becomes prohibitively expensive. - // For clear() it is more important to reuse the allocated array when the - // container is small because allocation takes comparatively long time - // compared to destruction of the elements of the container. So we pick the - // largest bucket_count() threshold for which iteration is still fast and - // past that we simply deallocate the array. - if (capacity_ > 127) { - destroy_slots(); - } else if (capacity_) { - for (size_t i = 0; i != capacity_; ++i) { - if (IsFull(ctrl_[i])) { - PolicyTraits::destroy(&alloc_ref(), slots_ + i); - } - } - size_ = 0; - reset_ctrl(); - reset_growth_left(); - } - assert(empty()); - infoz_.RecordStorageChanged(0, capacity_); - } - - // This overload kicks in when the argument is an rvalue of insertable and - // decomposable type other than init_type. - // - // flat_hash_map<std::string, int> m; - // m.insert(std::make_pair("abc", 42)); - // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc - // bug. - template <class T, RequiresInsertable<T> = 0, - class T2 = T, - typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0, - T* = nullptr> - std::pair<iterator, bool> insert(T&& value) { - return emplace(std::forward<T>(value)); - } - - // This overload kicks in when the argument is a bitfield or an lvalue of - // insertable and decomposable type. - // - // union { int n : 1; }; - // flat_hash_set<int> s; - // s.insert(n); - // - // flat_hash_set<std::string> s; - // const char* p = "hello"; - // s.insert(p); - // - // TODO(romanp): Once we stop supporting gcc 5.1 and below, replace - // RequiresInsertable<T> with RequiresInsertable<const T&>. - // We are hitting this bug: https://godbolt.org/g/1Vht4f. - template < - class T, RequiresInsertable<T> = 0, - typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0> - std::pair<iterator, bool> insert(const T& value) { - return emplace(value); - } - - // This overload kicks in when the argument is an rvalue of init_type. Its - // purpose is to handle brace-init-list arguments. - // - // flat_hash_map<std::string, int> s; - // s.insert({"abc", 42}); - std::pair<iterator, bool> insert(init_type&& value) { - return emplace(std::move(value)); - } - - // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc - // bug. - template <class T, RequiresInsertable<T> = 0, class T2 = T, - typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0, - T* = nullptr> - iterator insert(const_iterator, T&& value) { - return insert(std::forward<T>(value)).first; - } - - // TODO(romanp): Once we stop supporting gcc 5.1 and below, replace - // RequiresInsertable<T> with RequiresInsertable<const T&>. - // We are hitting this bug: https://godbolt.org/g/1Vht4f. - template < - class T, RequiresInsertable<T> = 0, - typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0> - iterator insert(const_iterator, const T& value) { - return insert(value).first; - } - - iterator insert(const_iterator, init_type&& value) { - return insert(std::move(value)).first; - } - - template <class InputIt> - void insert(InputIt first, InputIt last) { - for (; first != last; ++first) insert(*first); - } - - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0> - void insert(std::initializer_list<T> ilist) { - insert(ilist.begin(), ilist.end()); - } - - void insert(std::initializer_list<init_type> ilist) { - insert(ilist.begin(), ilist.end()); - } - - insert_return_type insert(node_type&& node) { - if (!node) return {end(), false, node_type()}; - const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node)); - auto res = PolicyTraits::apply( - InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))}, - elem); - if (res.second) { - CommonAccess::Reset(&node); - return {res.first, true, node_type()}; - } else { - return {res.first, false, std::move(node)}; - } - } - - iterator insert(const_iterator, node_type&& node) { - auto res = insert(std::move(node)); - node = std::move(res.node); - return res.position; - } - - // This overload kicks in if we can deduce the key from args. This enables us - // to avoid constructing value_type if an entry with the same key already - // exists. - // - // For example: - // - // flat_hash_map<std::string, std::string> m = {{"abc", "def"}}; - // // Creates no std::string copies and makes no heap allocations. - // m.emplace("abc", "xyz"); - template <class... Args, typename std::enable_if< - IsDecomposable<Args...>::value, int>::type = 0> - std::pair<iterator, bool> emplace(Args&&... args) { - return PolicyTraits::apply(EmplaceDecomposable{*this}, - std::forward<Args>(args)...); - } - - // This overload kicks in if we cannot deduce the key from args. It constructs - // value_type unconditionally and then either moves it into the table or - // destroys. - template <class... Args, typename std::enable_if< - !IsDecomposable<Args...>::value, int>::type = 0> - std::pair<iterator, bool> emplace(Args&&... args) { - alignas(slot_type) unsigned char raw[sizeof(slot_type)]; - slot_type* slot = reinterpret_cast<slot_type*>(&raw); - - PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); - const auto& elem = PolicyTraits::element(slot); - return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem); - } - - template <class... Args> - iterator emplace_hint(const_iterator, Args&&... args) { - return emplace(std::forward<Args>(args)...).first; - } - - // Extension API: support for lazy emplace. - // - // Looks up key in the table. If found, returns the iterator to the element. - // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`. - // - // `f` must abide by several restrictions: - // - it MUST call `raw_hash_set::constructor` with arguments as if a - // `raw_hash_set::value_type` is constructed, - // - it MUST NOT access the container before the call to - // `raw_hash_set::constructor`, and - // - it MUST NOT erase the lazily emplaced element. - // Doing any of these is undefined behavior. - // - // For example: - // - // std::unordered_set<ArenaString> s; - // // Makes ArenaStr even if "abc" is in the map. - // s.insert(ArenaString(&arena, "abc")); - // - // flat_hash_set<ArenaStr> s; - // // Makes ArenaStr only if "abc" is not in the map. - // s.lazy_emplace("abc", [&](const constructor& ctor) { - // ctor(&arena, "abc"); - // }); - // - // WARNING: This API is currently experimental. If there is a way to implement - // the same thing with the rest of the API, prefer that. - class constructor { - friend class raw_hash_set; - - public: - template <class... Args> - void operator()(Args&&... args) const { - assert(*slot_); - PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...); - *slot_ = nullptr; - } - - private: - constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {} - - allocator_type* alloc_; - slot_type** slot_; - }; - - template <class K = key_type, class F> - iterator lazy_emplace(const key_arg<K>& key, F&& f) { - auto res = find_or_prepare_insert(key); - if (res.second) { - slot_type* slot = slots_ + res.first; - std::forward<F>(f)(constructor(&alloc_ref(), &slot)); - assert(!slot); - } - return iterator_at(res.first); - } - - // Extension API: support for heterogeneous keys. - // - // std::unordered_set<std::string> s; - // // Turns "abc" into std::string. - // s.erase("abc"); - // - // flat_hash_set<std::string> s; - // // Uses "abc" directly without copying it into std::string. - // s.erase("abc"); - template <class K = key_type> - size_type erase(const key_arg<K>& key) { - auto it = find(key); - if (it == end()) return 0; - erase(it); - return 1; - } - - // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`, - // this method returns void to reduce algorithmic complexity to O(1). The - // iterator is invalidated, so any increment should be done before calling - // erase. In order to erase while iterating across a map, use the following - // idiom (which also works for standard containers): - // - // for (auto it = m.begin(), end = m.end(); it != end;) { - // // `erase()` will invalidate `it`, so advance `it` first. - // auto copy_it = it++; - // if (<pred>) { - // m.erase(copy_it); - // } - // } - void erase(const_iterator cit) { erase(cit.inner_); } - - // 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_); - PolicyTraits::destroy(&alloc_ref(), it.slot_); - erase_meta_only(it); - } - - iterator erase(const_iterator first, const_iterator last) { - while (first != last) { - erase(first++); - } - return last.inner_; - } - - // Moves elements from `src` into `this`. - // If the element already exists in `this`, it is left unmodified in `src`. - template <typename H, typename E> - void merge(raw_hash_set<Policy, H, E, Alloc>& src) { // NOLINT - assert(this != &src); - for (auto it = src.begin(), e = src.end(); it != e;) { - auto next = std::next(it); - if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)}, - PolicyTraits::element(it.slot_)) - .second) { - src.erase_meta_only(it); - } - it = next; - } - } - - template <typename H, typename E> - void merge(raw_hash_set<Policy, H, E, Alloc>&& src) { - merge(src); - } - - node_type extract(const_iterator position) { - AssertIsFull(position.inner_.ctrl_); - auto node = - CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_); - erase_meta_only(position); - return node; - } - - template < - class K = key_type, - typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0> - node_type extract(const key_arg<K>& key) { - auto it = find(key); - return it == end() ? node_type() : extract(const_iterator{it}); - } - - void swap(raw_hash_set& that) noexcept( - IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() && - IsNoThrowSwappable<allocator_type>( - typename AllocTraits::propagate_on_container_swap{})) { - using std::swap; - swap(ctrl_, that.ctrl_); - swap(slots_, that.slots_); - swap(size_, that.size_); - swap(capacity_, that.capacity_); - swap(growth_left(), that.growth_left()); - swap(hash_ref(), that.hash_ref()); - swap(eq_ref(), that.eq_ref()); - swap(infoz_, that.infoz_); - SwapAlloc(alloc_ref(), that.alloc_ref(), - typename AllocTraits::propagate_on_container_swap{}); - } - - void rehash(size_t n) { - if (n == 0 && capacity_ == 0) return; - if (n == 0 && size_ == 0) { - destroy_slots(); - infoz_.RecordStorageChanged(0, 0); - 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); - } - } - - void reserve(size_t n) { - size_t m = GrowthToLowerboundCapacity(n); - if (m > capacity_) { - resize(NormalizeCapacity(m)); - } - } - - // Extension API: support for heterogeneous keys. - // - // std::unordered_set<std::string> s; - // // Turns "abc" into std::string. - // s.count("abc"); - // - // ch_set<std::string> s; - // // Uses "abc" directly without copying it into std::string. - // s.count("abc"); - template <class K = key_type> - size_t count(const key_arg<K>& key) const { - return find(key) == end() ? 0 : 1; - } - - // Issues CPU prefetch instructions for the memory needed to find or insert - // a key. Like all lookup functions, this support heterogeneous keys. - // - // NOTE: This is a very low level operation and should not be used without - // specific benchmarks indicating its importance. - template <class K = key_type> - void prefetch(const key_arg<K>& key) const { - (void)key; -#if defined(__GNUC__) - auto seq = probe(ctrl_, hash_ref()(key), capacity_); - __builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset())); - __builtin_prefetch(static_cast<const void*>(slots_ + seq.offset())); -#endif // __GNUC__ - } - - // The API of find() has two extensions. - // - // 1. The hash can be passed by the user. It must be equal to the hash of the - // key. - // - // 2. The type of the key argument doesn't have to be key_type. This is so - // 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_); - while (true) { - Group g{ctrl_ + seq.offset()}; - for (int i : g.Match(H2(hash))) { - if (ABSL_PREDICT_TRUE(PolicyTraits::apply( - EqualElement<K>{key, eq_ref()}, - PolicyTraits::element(slots_ + seq.offset(i))))) - return iterator_at(seq.offset(i)); - } - 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) { - return find(key, hash_ref()(key)); - } - - template <class K = key_type> - const_iterator find(const key_arg<K>& key, size_t hash) const { - return const_cast<raw_hash_set*>(this)->find(key, hash); - } - template <class K = key_type> - const_iterator find(const key_arg<K>& key) const { - return find(key, hash_ref()(key)); - } - - template <class K = key_type> - bool contains(const key_arg<K>& key) const { - return find(key) != end(); - } - - template <class K = key_type> - std::pair<iterator, iterator> equal_range(const key_arg<K>& key) { - auto it = find(key); - if (it != end()) return {it, std::next(it)}; - return {it, it}; - } - template <class K = key_type> - std::pair<const_iterator, const_iterator> equal_range( - const key_arg<K>& key) const { - auto it = find(key); - if (it != end()) return {it, std::next(it)}; - return {it, it}; - } - - size_t bucket_count() const { return capacity_; } - float load_factor() const { - return capacity_ ? static_cast<double>(size()) / capacity_ : 0.0; - } - float max_load_factor() const { return 1.0f; } - void max_load_factor(float) { - // Does nothing. - } - - hasher hash_function() const { return hash_ref(); } - key_equal key_eq() const { return eq_ref(); } - allocator_type get_allocator() const { return alloc_ref(); } - - friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) { - if (a.size() != b.size()) return false; - const raw_hash_set* outer = &a; - const raw_hash_set* inner = &b; - if (outer->capacity() > inner->capacity()) std::swap(outer, inner); - for (const value_type& elem : *outer) - if (!inner->has_element(elem)) return false; - return true; - } - - friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) { - return !(a == b); - } - - friend void swap(raw_hash_set& a, - raw_hash_set& b) noexcept(noexcept(a.swap(b))) { - a.swap(b); - } - - private: - template <class Container, typename Enabler> - friend struct absl::container_internal::hashtable_debug_internal:: - HashtableDebugAccess; - - struct FindElement { - template <class K, class... Args> - const_iterator operator()(const K& key, Args&&...) const { - return s.find(key); - } - const raw_hash_set& s; - }; - - struct HashElement { - template <class K, class... Args> - size_t operator()(const K& key, Args&&...) const { - return h(key); - } - const hasher& h; - }; - - template <class K1> - struct EqualElement { - template <class K2, class... Args> - bool operator()(const K2& lhs, Args&&...) const { - return eq(lhs, rhs); - } - const K1& rhs; - const key_equal& eq; - }; - - struct EmplaceDecomposable { - template <class K, class... Args> - std::pair<iterator, bool> operator()(const K& key, Args&&... args) const { - auto res = s.find_or_prepare_insert(key); - if (res.second) { - s.emplace_at(res.first, std::forward<Args>(args)...); - } - return {s.iterator_at(res.first), res.second}; - } - raw_hash_set& s; - }; - - template <bool do_destroy> - struct InsertSlot { - template <class K, class... Args> - std::pair<iterator, bool> operator()(const K& key, Args&&...) && { - auto res = s.find_or_prepare_insert(key); - if (res.second) { - PolicyTraits::transfer(&s.alloc_ref(), s.slots_ + res.first, &slot); - } else if (do_destroy) { - PolicyTraits::destroy(&s.alloc_ref(), &slot); - } - return {s.iterator_at(res.first), res.second}; - } - raw_hash_set& s; - // Constructed slot. Either moved into place or destroyed. - slot_type&& slot; - }; - - // "erases" the object from the container, except that it doesn't actually - // destroy the object. It only updates all the metadata of the class. - // This can be used in conjunction with Policy::transfer to move the object to - // another place. - void erase_meta_only(const_iterator it) { - assert(IsFull(*it.inner_.ctrl_) && "erasing a dangling iterator"); - --size_; - const size_t index = it.inner_.ctrl_ - ctrl_; - const size_t index_before = (index - Group::kWidth) & capacity_; - const auto empty_after = Group(it.inner_.ctrl_).MatchEmpty(); - const auto empty_before = Group(ctrl_ + index_before).MatchEmpty(); - - // We count how many consecutive non empties we have to the right and to the - // left of `it`. If the sum is >= kWidth then there is at least one probe - // window that might have seen a full group. - bool was_never_full = - empty_before && empty_after && - static_cast<size_t>(empty_after.TrailingZeros() + - empty_before.LeadingZeros()) < Group::kWidth; - - set_ctrl(index, was_never_full ? kEmpty : kDeleted); - growth_left() += was_never_full; - infoz_.RecordErase(); - } - - void initialize_slots() { - assert(capacity_); - // Folks with custom allocators often make unwarranted assumptions about the - // behavior of their classes vis-a-vis trivial destructability and what - // calls they will or wont make. Avoid sampling for people with custom - // allocators to get us out of this mess. This is not a hard guarantee but - // a workaround while we plan the exact guarantee we want to provide. - // - // People are often sloppy with the exact type of their allocator (sometimes - // it has an extra const or is missing the pair, but rebinds made it work - // anyway). To avoid the ambiguity, we work off SlotAlloc which we have - // bound more carefully. - if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value && - slots_ == nullptr) { - infoz_ = Sample(); - } - - auto layout = MakeLayout(capacity_); - char* mem = static_cast<char*>( - Allocate<Layout::Alignment()>(&alloc_ref(), layout.AllocSize())); - ctrl_ = reinterpret_cast<ctrl_t*>(layout.template Pointer<0>(mem)); - slots_ = layout.template Pointer<1>(mem); - reset_ctrl(); - reset_growth_left(); - infoz_.RecordStorageChanged(size_, capacity_); - } - - void destroy_slots() { - if (!capacity_) return; - for (size_t i = 0; i != capacity_; ++i) { - if (IsFull(ctrl_[i])) { - 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<Layout::Alignment()>(&alloc_ref(), ctrl_, layout.AllocSize()); - ctrl_ = EmptyGroup(); - slots_ = nullptr; - size_ = 0; - capacity_ = 0; - growth_left() = 0; - } - - void resize(size_t new_capacity) { - assert(IsValidCapacity(new_capacity)); - auto* old_ctrl = ctrl_; - auto* old_slots = slots_; - const size_t old_capacity = capacity_; - capacity_ = new_capacity; - initialize_slots(); - - size_t total_probe_length = 0; - for (size_t i = 0; i != old_capacity; ++i) { - if (IsFull(old_ctrl[i])) { - size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, - PolicyTraits::element(old_slots + i)); - auto target = find_first_non_full(ctrl_, hash, capacity_); - size_t new_i = target.offset; - total_probe_length += target.probe_length; - set_ctrl(new_i, H2(hash)); - PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i); - } - } - if (old_capacity) { - SanitizerUnpoisonMemoryRegion(old_slots, - sizeof(slot_type) * old_capacity); - auto layout = MakeLayout(old_capacity); - Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl, - layout.AllocSize()); - } - infoz_.RecordRehash(total_probe_length); - } - - void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE { - assert(IsValidCapacity(capacity_)); - assert(!is_small(capacity_)); - // Algorithm: - // - mark all DELETED slots as EMPTY - // - mark all FULL slots as DELETED - // - for each slot marked as DELETED - // hash = Hash(element) - // target = find_first_non_full(hash) - // if target is in the same group - // mark slot as FULL - // else if target is EMPTY - // transfer element to target - // mark slot as EMPTY - // mark target as FULL - // else if target is DELETED - // swap current element with target element - // mark target as FULL - // repeat procedure for current slot with moved from element (target) - ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_); - alignas(slot_type) unsigned char raw[sizeof(slot_type)]; - size_t total_probe_length = 0; - slot_type* slot = reinterpret_cast<slot_type*>(&raw); - for (size_t i = 0; i != capacity_; ++i) { - if (!IsDeleted(ctrl_[i])) continue; - size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, - PolicyTraits::element(slots_ + i)); - auto target = find_first_non_full(ctrl_, hash, capacity_); - size_t new_i = target.offset; - total_probe_length += target.probe_length; - - // Verify if the old and new i fall within the same group wrt the hash. - // If they do, we don't need to move the object as it falls already in the - // best probe we can. - const auto probe_index = [&](size_t pos) { - return ((pos - probe(ctrl_, hash, capacity_).offset()) & capacity_) / - Group::kWidth; - }; - - // Element doesn't move. - if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) { - set_ctrl(i, H2(hash)); - continue; - } - if (IsEmpty(ctrl_[new_i])) { - // Transfer element to the empty spot. - // set_ctrl poisons/unpoisons the slots so we have to call it at the - // right time. - set_ctrl(new_i, H2(hash)); - PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slots_ + i); - set_ctrl(i, kEmpty); - } else { - assert(IsDeleted(ctrl_[new_i])); - 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); - PolicyTraits::transfer(&alloc_ref(), slots_ + i, slots_ + new_i); - PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slot); - --i; // repeat - } - } - reset_growth_left(); - infoz_.RecordRehash(total_probe_length); - } - - void rehash_and_grow_if_necessary() { - if (capacity_ == 0) { - resize(1); - } else if (size() <= CapacityToGrowth(capacity()) / 2) { - // Squash DELETED without growing if there is enough capacity. - drop_deletes_without_resize(); - } else { - // Otherwise grow the container. - resize(capacity_ * 2 + 1); - } - } - - bool has_element(const value_type& elem) const { - size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem); - auto seq = probe(ctrl_, hash, capacity_); - while (true) { - Group g{ctrl_ + seq.offset()}; - for (int i : g.Match(H2(hash))) { - if (ABSL_PREDICT_TRUE(PolicyTraits::element(slots_ + seq.offset(i)) == - elem)) - return true; - } - if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return false; - seq.next(); - assert(seq.index() < capacity_ && "full table!"); - } - return false; - } - - // 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)); - swap(tmp); - return *this; - } - raw_hash_set& move_assign(raw_hash_set&& that, std::false_type) { - raw_hash_set tmp(std::move(that), alloc_ref()); - swap(tmp); - return *this; - } - - protected: - template <class K> - std::pair<size_t, bool> find_or_prepare_insert(const K& key) { - auto hash = hash_ref()(key); - auto seq = probe(ctrl_, hash, capacity_); - while (true) { - Group g{ctrl_ + seq.offset()}; - for (int i : g.Match(H2(hash))) { - if (ABSL_PREDICT_TRUE(PolicyTraits::apply( - EqualElement<K>{key, eq_ref()}, - PolicyTraits::element(slots_ + seq.offset(i))))) - return {seq.offset(i), false}; - } - 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_); - if (ABSL_PREDICT_FALSE(growth_left() == 0 && - !IsDeleted(ctrl_[target.offset]))) { - rehash_and_grow_if_necessary(); - target = find_first_non_full(ctrl_, hash, capacity_); - } - ++size_; - growth_left() -= IsEmpty(ctrl_[target.offset]); - set_ctrl(target.offset, H2(hash)); - infoz_.RecordInsert(hash, target.probe_length); - return target.offset; - } - - // Constructs the value in the space pointed by the iterator. This only works - // after an unsuccessful find_or_prepare_insert() and before any other - // modifications happen in the raw_hash_set. - // - // PRECONDITION: i is an index returned from find_or_prepare_insert(k), where - // k is the key decomposed from `forward<Args>(args)...`, and the bool - // returned by find_or_prepare_insert(k) was true. - // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...). - template <class... Args> - void emplace_at(size_t i, Args&&... args) { - PolicyTraits::construct(&alloc_ref(), slots_ + i, - std::forward<Args>(args)...); - - assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) == - iterator_at(i) && - "constructed value does not match the lookup key"); - } - - iterator iterator_at(size_t i) { return {ctrl_ + i, slots_ + i}; } - const_iterator iterator_at(size_t i) const { return {ctrl_ + i, slots_ + i}; } - - private: - friend struct RawHashSetTestOnlyAccess; - - // 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_; - } - - // 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_); - - if (IsFull(h)) { - SanitizerUnpoisonObject(slots_ + i); - } else { - SanitizerPoisonObject(slots_ + i); - } - - ctrl_[i] = h; - ctrl_[((i - Group::kWidth) & capacity_) + 1 + - ((Group::kWidth - 1) & capacity_)] = h; - } - - size_t& growth_left() { return settings_.template get<0>(); } - - hasher& hash_ref() { return settings_.template get<1>(); } - const hasher& hash_ref() const { return settings_.template get<1>(); } - key_equal& eq_ref() { return settings_.template get<2>(); } - const key_equal& eq_ref() const { return settings_.template get<2>(); } - allocator_type& alloc_ref() { return settings_.template get<3>(); } - const allocator_type& alloc_ref() const { - 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) * 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, hasher{}, key_equal{}, allocator_type{}}; -}; - -// Erases all elements that satisfy the predicate `pred` from the container `c`. -template <typename P, typename H, typename E, typename A, typename Predicate> -void EraseIf(Predicate pred, raw_hash_set<P, H, E, A>* c) { - for (auto it = c->begin(), last = c->end(); it != last;) { - auto copy_it = it++; - if (pred(*copy_it)) { - c->erase(copy_it); - } - } -} - -namespace hashtable_debug_internal { -template <typename Set> -struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> { - using Traits = typename Set::PolicyTraits; - using Slot = typename Traits::slot_type; - - static size_t GetNumProbes(const Set& 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_); - while (true) { - container_internal::Group g{set.ctrl_ + seq.offset()}; - for (int i : g.Match(container_internal::H2(hash))) { - if (Traits::apply( - typename Set::template EqualElement<typename Set::key_type>{ - key, set.eq_ref()}, - Traits::element(set.slots_ + seq.offset(i)))) - return num_probes; - ++num_probes; - } - if (g.MatchEmpty()) return num_probes; - seq.next(); - ++num_probes; - } - } - - static size_t AllocatedByteSize(const Set& c) { - size_t capacity = c.capacity_; - if (capacity == 0) return 0; - 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{}) { - m += per_slot * c.size(); - } else { - for (size_t i = 0; i != capacity; ++i) { - if (container_internal::IsFull(c.ctrl_[i])) { - m += Traits::space_used(c.slots_ + i); - } - } - } - return m; - } - - static size_t LowerBoundAllocatedByteSize(size_t size) { - size_t capacity = GrowthToLowerboundCapacity(size); - if (capacity == 0) return 0; - 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; - } - return m; - } -}; - -} // namespace hashtable_debug_internal -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ 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 deleted file mode 100644 index e73f53fd637b..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/raw_hash_set_allocator_test.cc +++ /dev/null @@ -1,505 +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 <limits> -#include <scoped_allocator> - -#include "gtest/gtest.h" -#include "absl/container/internal/raw_hash_set.h" -#include "absl/container/internal/tracked.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -enum AllocSpec { - kPropagateOnCopy = 1, - kPropagateOnMove = 2, - kPropagateOnSwap = 4, -}; - -struct AllocState { - size_t num_allocs = 0; - std::set<void*> owned; -}; - -template <class T, - int Spec = kPropagateOnCopy | kPropagateOnMove | kPropagateOnSwap> -class CheckedAlloc { - public: - template <class, int> - friend class CheckedAlloc; - - using value_type = T; - - CheckedAlloc() {} - explicit CheckedAlloc(size_t id) : id_(id) {} - CheckedAlloc(const CheckedAlloc&) = default; - CheckedAlloc& operator=(const CheckedAlloc&) = default; - - template <class U> - CheckedAlloc(const CheckedAlloc<U, Spec>& that) - : id_(that.id_), state_(that.state_) {} - - template <class U> - struct rebind { - using other = CheckedAlloc<U, Spec>; - }; - - using propagate_on_container_copy_assignment = - std::integral_constant<bool, (Spec & kPropagateOnCopy) != 0>; - - using propagate_on_container_move_assignment = - std::integral_constant<bool, (Spec & kPropagateOnMove) != 0>; - - using propagate_on_container_swap = - std::integral_constant<bool, (Spec & kPropagateOnSwap) != 0>; - - CheckedAlloc select_on_container_copy_construction() const { - if (Spec & kPropagateOnCopy) return *this; - return {}; - } - - T* allocate(size_t n) { - T* ptr = std::allocator<T>().allocate(n); - track_alloc(ptr); - return ptr; - } - void deallocate(T* ptr, size_t n) { - memset(ptr, 0, n * sizeof(T)); // The freed memory must be unpoisoned. - track_dealloc(ptr); - return std::allocator<T>().deallocate(ptr, n); - } - - friend bool operator==(const CheckedAlloc& a, const CheckedAlloc& b) { - return a.id_ == b.id_; - } - friend bool operator!=(const CheckedAlloc& a, const CheckedAlloc& b) { - return !(a == b); - } - - size_t num_allocs() const { return state_->num_allocs; } - - void swap(CheckedAlloc& that) { - using std::swap; - swap(id_, that.id_); - swap(state_, that.state_); - } - - friend void swap(CheckedAlloc& a, CheckedAlloc& b) { a.swap(b); } - - friend std::ostream& operator<<(std::ostream& o, const CheckedAlloc& a) { - return o << "alloc(" << a.id_ << ")"; - } - - private: - void track_alloc(void* ptr) { - AllocState* state = state_.get(); - ++state->num_allocs; - if (!state->owned.insert(ptr).second) - ADD_FAILURE() << *this << " got previously allocated memory: " << ptr; - } - void track_dealloc(void* ptr) { - if (state_->owned.erase(ptr) != 1) - ADD_FAILURE() << *this - << " deleting memory owned by another allocator: " << ptr; - } - - size_t id_ = std::numeric_limits<size_t>::max(); - - std::shared_ptr<AllocState> state_ = std::make_shared<AllocState>(); -}; - -struct Identity { - int32_t operator()(int32_t v) const { return v; } -}; - -struct Policy { - using slot_type = Tracked<int32_t>; - using init_type = Tracked<int32_t>; - using key_type = int32_t; - - 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, 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)); - destroy(alloc, old_slot); - } - - template <class F> - static auto apply(F&& f, int32_t v) -> decltype(std::forward<F>(f)(v, v)) { - return std::forward<F>(f)(v, v); - } - - template <class F> - static auto apply(F&& f, const slot_type& v) - -> decltype(std::forward<F>(f)(v.val(), v)) { - return std::forward<F>(f)(v.val(), v); - } - - template <class F> - static auto apply(F&& f, slot_type&& v) - -> decltype(std::forward<F>(f)(v.val(), std::move(v))) { - return std::forward<F>(f)(v.val(), std::move(v)); - } - - static slot_type& element(slot_type* slot) { return *slot; } -}; - -template <int Spec> -struct PropagateTest : public ::testing::Test { - using Alloc = CheckedAlloc<Tracked<int32_t>, Spec>; - - using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, Alloc>; - - PropagateTest() { - EXPECT_EQ(a1, t1.get_allocator()); - EXPECT_NE(a2, t1.get_allocator()); - } - - Alloc a1 = Alloc(1); - Table t1 = Table(0, a1); - Alloc a2 = Alloc(2); -}; - -using PropagateOnAll = - PropagateTest<kPropagateOnCopy | kPropagateOnMove | kPropagateOnSwap>; -using NoPropagateOnCopy = PropagateTest<kPropagateOnMove | kPropagateOnSwap>; -using NoPropagateOnMove = PropagateTest<kPropagateOnCopy | kPropagateOnSwap>; - -TEST_F(PropagateOnAll, Empty) { EXPECT_EQ(0, a1.num_allocs()); } - -TEST_F(PropagateOnAll, InsertAllocates) { - auto it = t1.insert(0).first; - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, InsertDecomposes) { - auto it = t1.insert(0).first; - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); - - EXPECT_FALSE(t1.insert(0).second); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, RehashMoves) { - auto it = t1.insert(0).first; - EXPECT_EQ(0, it->num_moves()); - t1.rehash(2 * t1.capacity()); - EXPECT_EQ(2, a1.num_allocs()); - it = t1.find(0); - EXPECT_EQ(1, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, CopyConstructor) { - auto it = t1.insert(0).first; - Table u(t1); - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(NoPropagateOnCopy, CopyConstructor) { - auto it = t1.insert(0).first; - Table u(t1); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, u.get_allocator().num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(PropagateOnAll, CopyConstructorWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(t1, a1); - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(NoPropagateOnCopy, CopyConstructorWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(t1, a1); - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(PropagateOnAll, CopyConstructorWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(t1, a2); - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(NoPropagateOnCopy, CopyConstructorWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(t1, a2); - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(PropagateOnAll, MoveConstructor) { - auto it = t1.insert(0).first; - Table u(std::move(t1)); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(NoPropagateOnMove, MoveConstructor) { - auto it = t1.insert(0).first; - Table u(std::move(t1)); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, MoveConstructorWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(std::move(t1), a1); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(NoPropagateOnMove, MoveConstructorWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(std::move(t1), a1); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, MoveConstructorWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(std::move(t1), a2); - it = u.find(0); - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(1, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(NoPropagateOnMove, MoveConstructorWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(std::move(t1), a2); - it = u.find(0); - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(1, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, CopyAssignmentWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(0, a1); - u = t1; - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(NoPropagateOnCopy, CopyAssignmentWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(0, a1); - u = t1; - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(PropagateOnAll, CopyAssignmentWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(0, a2); - u = t1; - EXPECT_EQ(a1, u.get_allocator()); - EXPECT_EQ(2, a1.num_allocs()); - EXPECT_EQ(0, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(NoPropagateOnCopy, CopyAssignmentWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(0, a2); - u = t1; - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(1, it->num_copies()); -} - -TEST_F(PropagateOnAll, MoveAssignmentWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(0, a1); - u = std::move(t1); - EXPECT_EQ(a1, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(NoPropagateOnMove, MoveAssignmentWithSameAlloc) { - auto it = t1.insert(0).first; - Table u(0, a1); - u = std::move(t1); - EXPECT_EQ(a1, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, MoveAssignmentWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(0, a2); - u = std::move(t1); - EXPECT_EQ(a1, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(NoPropagateOnMove, MoveAssignmentWithDifferentAlloc) { - auto it = t1.insert(0).first; - Table u(0, a2); - u = std::move(t1); - it = u.find(0); - EXPECT_EQ(a2, u.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(1, a2.num_allocs()); - EXPECT_EQ(1, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -TEST_F(PropagateOnAll, Swap) { - auto it = t1.insert(0).first; - Table u(0, a2); - u.swap(t1); - EXPECT_EQ(a1, u.get_allocator()); - EXPECT_EQ(a2, t1.get_allocator()); - EXPECT_EQ(1, a1.num_allocs()); - EXPECT_EQ(0, a2.num_allocs()); - EXPECT_EQ(0, it->num_moves()); - EXPECT_EQ(0, it->num_copies()); -} - -// This allocator is similar to std::pmr::polymorphic_allocator. -// Note the disabled assignment. -template <class T> -class PAlloc { - template <class> - friend class PAlloc; - - public: - // types - using value_type = T; - - // traits - using propagate_on_container_swap = std::false_type; - - PAlloc() noexcept = default; - explicit PAlloc(size_t id) noexcept : id_(id) {} - PAlloc(const PAlloc&) noexcept = default; - PAlloc& operator=(const PAlloc&) noexcept = delete; - - template <class U> - PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {} // NOLINT - - template <class U> - struct rebind { - using other = PAlloc<U>; - }; - - constexpr PAlloc select_on_container_copy_construction() const { return {}; } - - // public member functions - T* allocate(size_t) { return new T; } - void deallocate(T* p, size_t) { delete p; } - - friend bool operator==(const PAlloc& a, const PAlloc& b) { - return a.id_ == b.id_; - } - friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); } - - private: - size_t id_ = std::numeric_limits<size_t>::max(); -}; - -// This doesn't compile with GCC 5.4 and 5.5 due to a bug in noexcept handing. -#if !defined(__GNUC__) || __GNUC__ != 5 || (__GNUC_MINOR__ != 4 && \ - __GNUC_MINOR__ != 5) -TEST(NoPropagateOn, Swap) { - using PA = PAlloc<char>; - using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>; - - Table t1(PA{1}), t2(PA{2}); - swap(t1, t2); - EXPECT_EQ(t1.get_allocator(), PA(1)); - EXPECT_EQ(t2.get_allocator(), PA(2)); -} -#endif - -TEST(NoPropagateOn, CopyConstruct) { - using PA = PAlloc<char>; - using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>; - - Table t1(PA{1}), t2(t1); - EXPECT_EQ(t1.get_allocator(), PA(1)); - EXPECT_EQ(t2.get_allocator(), PA()); -} - -TEST(NoPropagateOn, Assignment) { - using PA = PAlloc<char>; - using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>; - - Table t1(PA{1}), t2(PA{2}); - t1 = t2; - EXPECT_EQ(t1.get_allocator(), PA(1)); - EXPECT_EQ(t2.get_allocator(), PA(2)); -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/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 deleted file mode 100644 index 33d2773de302..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/raw_hash_set_test.cc +++ /dev/null @@ -1,1893 +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 <cmath> -#include <cstdint> -#include <deque> -#include <functional> -#include <memory> -#include <numeric> -#include <random> -#include <string> - -#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" -#include "absl/container/internal/hash_function_defaults.h" -#include "absl/container/internal/hash_policy_testing.h" -#include "absl/container/internal/hashtable_debug.h" -#include "absl/strings/string_view.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 { - -using ::testing::DoubleNear; -using ::testing::ElementsAre; -using ::testing::Ge; -using ::testing::Lt; -using ::testing::Optional; -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -TEST(Util, NormalizeCapacity) { - EXPECT_EQ(1, NormalizeCapacity(0)); - EXPECT_EQ(1, NormalizeCapacity(1)); - EXPECT_EQ(3, NormalizeCapacity(2)); - EXPECT_EQ(3, NormalizeCapacity(3)); - EXPECT_EQ(7, NormalizeCapacity(4)); - EXPECT_EQ(7, NormalizeCapacity(7)); - EXPECT_EQ(15, NormalizeCapacity(8)); - EXPECT_EQ(15, NormalizeCapacity(15)); - EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1)); - EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2)); -} - -TEST(Util, GrowthAndCapacity) { - // Verify that GrowthToCapacity gives the minimum capacity that has enough - // growth. - for (size_t growth = 0; growth < 10000; ++growth) { - SCOPED_TRACE(growth); - size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth)); - // The capacity is large enough for `growth` - EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth)); - if (growth != 0 && capacity > 1) { - // There is no smaller capacity that works. - EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)); - } - } - - for (size_t capacity = Group::kWidth - 1; capacity < 10000; - capacity = 2 * capacity + 1) { - SCOPED_TRACE(capacity); - size_t growth = CapacityToGrowth(capacity); - EXPECT_THAT(growth, Lt(capacity)); - EXPECT_LE(GrowthToLowerboundCapacity(growth), capacity); - EXPECT_EQ(NormalizeCapacity(GrowthToLowerboundCapacity(growth)), capacity); - } -} - -TEST(Util, probe_seq) { - probe_seq<16> seq(0, 127); - auto gen = [&]() { - size_t res = seq.offset(); - seq.next(); - return res; - }; - std::vector<size_t> offsets(8); - std::generate_n(offsets.begin(), 8, gen); - EXPECT_THAT(offsets, ElementsAre(0, 16, 48, 96, 32, 112, 80, 64)); - seq = probe_seq<16>(128, 127); - std::generate_n(offsets.begin(), 8, gen); - EXPECT_THAT(offsets, ElementsAre(0, 16, 48, 96, 32, 112, 80, 64)); -} - -TEST(BitMask, Smoke) { - EXPECT_FALSE((BitMask<uint8_t, 8>(0))); - EXPECT_TRUE((BitMask<uint8_t, 8>(5))); - - EXPECT_THAT((BitMask<uint8_t, 8>(0)), ElementsAre()); - EXPECT_THAT((BitMask<uint8_t, 8>(0x1)), ElementsAre(0)); - EXPECT_THAT((BitMask<uint8_t, 8>(0x2)), ElementsAre(1)); - EXPECT_THAT((BitMask<uint8_t, 8>(0x3)), ElementsAre(0, 1)); - EXPECT_THAT((BitMask<uint8_t, 8>(0x4)), ElementsAre(2)); - EXPECT_THAT((BitMask<uint8_t, 8>(0x5)), ElementsAre(0, 2)); - EXPECT_THAT((BitMask<uint8_t, 8>(0x55)), ElementsAre(0, 2, 4, 6)); - EXPECT_THAT((BitMask<uint8_t, 8>(0xAA)), ElementsAre(1, 3, 5, 7)); -} - -TEST(BitMask, WithShift) { - // See the non-SSE version of Group for details on what this math is for. - uint64_t ctrl = 0x1716151413121110; - uint64_t hash = 0x12; - constexpr uint64_t msbs = 0x8080808080808080ULL; - constexpr uint64_t lsbs = 0x0101010101010101ULL; - auto x = ctrl ^ (lsbs * hash); - uint64_t mask = (x - lsbs) & ~x & msbs; - EXPECT_EQ(0x0000000080800000, mask); - - BitMask<uint64_t, 8, 3> b(mask); - EXPECT_EQ(*b, 2); -} - -TEST(BitMask, LeadingTrailing) { - EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3); - EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6); - - EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15); - EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0); - - EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0); - EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15); - - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3); - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1); - - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).LeadingZeros()), 7); - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).TrailingZeros()), 0); - - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).LeadingZeros()), 0); - EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).TrailingZeros()), 7); -} - -TEST(Group, EmptyGroup) { - for (h2_t h = 0; h != 128; ++h) EXPECT_FALSE(Group{EmptyGroup()}.Match(h)); -} - -TEST(Group, Match) { - if (Group::kWidth == 16) { - 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[] = {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)); - } else { - FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth; - } -} - -TEST(Group, MatchEmpty) { - if (Group::kWidth == 16) { - 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[] = {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; - } -} - -TEST(Group, MatchEmptyOrDeleted) { - if (Group::kWidth == 16) { - 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[] = {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; - } -} - -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] = 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], kSentinel); - for (size_t i = 0; i < kCapacity + 1 + kGroupWidth; ++i) { - ctrl_t expected = pattern[i % (kCapacity + 1) % pattern.size()]; - if (i == kCapacity) expected = kSentinel; - if (expected == kDeleted) expected = kEmpty; - if (IsFull(expected)) expected = kDeleted; - EXPECT_EQ(ctrl[i], expected) - << i << " " << int{pattern[i % pattern.size()]}; - } -} - -TEST(Group, CountLeadingEmptyOrDeleted) { - 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); - EXPECT_EQ(Group::kWidth, Group{e.data()}.CountLeadingEmptyOrDeleted()); - for (ctrl_t full : full_examples) { - for (size_t i = 0; i != Group::kWidth; ++i) { - std::vector<ctrl_t> f(Group::kWidth, empty); - f[i] = full; - EXPECT_EQ(i, Group{f.data()}.CountLeadingEmptyOrDeleted()); - } - std::vector<ctrl_t> f(Group::kWidth, empty); - f[Group::kWidth * 2 / 3] = full; - f[Group::kWidth / 2] = full; - EXPECT_EQ( - Group::kWidth / 2, Group{f.data()}.CountLeadingEmptyOrDeleted()); - } - } -} - -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 : absl::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; - using Base::Base; -}; - -template <typename T> -struct CustomAlloc : std::allocator<T> { - CustomAlloc() {} - - template <typename U> - CustomAlloc(const CustomAlloc<U>& other) {} - - template<class U> struct rebind { - using other = CustomAlloc<U>; - }; -}; - -struct CustomAllocIntTable - : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>, - std::equal_to<int64_t>, CustomAlloc<int64_t>> { - using Base = typename CustomAllocIntTable::raw_hash_set; - using Base::Base; -}; - -struct BadFastHash { - template <class T> - size_t operator()(const T&) const { - return 0; - } -}; - -struct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int>, - std::allocator<int>> { - using Base = typename BadTable::raw_hash_set; - BadTable() {} - using Base::Base; -}; - -TEST(Table, EmptyFunctorOptimization) { - static_assert(std::is_empty<std::equal_to<absl::string_view>>::value, ""); - static_assert(std::is_empty<std::allocator<int>>::value, ""); - - struct MockTable { - void* ctrl; - void* slots; - size_t size; - size_t capacity; - size_t growth_left; - void* infoz; - }; - struct StatelessHash { - size_t operator()(absl::string_view) const { return 0; } - }; - struct StatefulHash : StatelessHash { - size_t dummy; - }; - - EXPECT_EQ( - sizeof(MockTable), - sizeof( - raw_hash_set<StringPolicy, StatelessHash, - std::equal_to<absl::string_view>, std::allocator<int>>)); - - EXPECT_EQ( - sizeof(MockTable) + sizeof(StatefulHash), - sizeof( - raw_hash_set<StringPolicy, StatefulHash, - std::equal_to<absl::string_view>, std::allocator<int>>)); -} - -TEST(Table, Empty) { - IntTable t; - EXPECT_EQ(0, t.size()); - EXPECT_TRUE(t.empty()); -} - -TEST(Table, LookupEmpty) { - IntTable t; - auto it = t.find(0); - EXPECT_TRUE(it == t.end()); -} - -TEST(Table, Insert1) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - auto res = t.emplace(0); - EXPECT_TRUE(res.second); - EXPECT_THAT(*res.first, 0); - EXPECT_EQ(1, t.size()); - EXPECT_THAT(*t.find(0), 0); -} - -TEST(Table, Insert2) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - auto res = t.emplace(0); - EXPECT_TRUE(res.second); - EXPECT_THAT(*res.first, 0); - EXPECT_EQ(1, t.size()); - EXPECT_TRUE(t.find(1) == t.end()); - res = t.emplace(1); - EXPECT_TRUE(res.second); - EXPECT_THAT(*res.first, 1); - EXPECT_EQ(2, t.size()); - EXPECT_THAT(*t.find(0), 0); - EXPECT_THAT(*t.find(1), 1); -} - -TEST(Table, InsertCollision) { - BadTable t; - EXPECT_TRUE(t.find(1) == t.end()); - auto res = t.emplace(1); - EXPECT_TRUE(res.second); - EXPECT_THAT(*res.first, 1); - EXPECT_EQ(1, t.size()); - - EXPECT_TRUE(t.find(2) == t.end()); - res = t.emplace(2); - EXPECT_THAT(*res.first, 2); - EXPECT_TRUE(res.second); - EXPECT_EQ(2, t.size()); - - EXPECT_THAT(*t.find(1), 1); - EXPECT_THAT(*t.find(2), 2); -} - -// Test that we do not add existent element in case we need to search through -// many groups with deleted elements -TEST(Table, InsertCollisionAndFindAfterDelete) { - BadTable t; // all elements go to the same group. - // Have at least 2 groups with Group::kWidth collisions - // plus some extra collisions in the last group. - constexpr size_t kNumInserts = Group::kWidth * 2 + 5; - for (size_t i = 0; i < kNumInserts; ++i) { - auto res = t.emplace(i); - EXPECT_TRUE(res.second); - EXPECT_THAT(*res.first, i); - EXPECT_EQ(i + 1, t.size()); - } - - // Remove elements one by one and check - // that we still can find all other elements. - for (size_t i = 0; i < kNumInserts; ++i) { - EXPECT_EQ(1, t.erase(i)) << i; - for (size_t j = i + 1; j < kNumInserts; ++j) { - EXPECT_THAT(*t.find(j), j); - auto res = t.emplace(j); - EXPECT_FALSE(res.second) << i << " " << j; - EXPECT_THAT(*res.first, j); - EXPECT_EQ(kNumInserts - i - 1, t.size()); - } - } - EXPECT_TRUE(t.empty()); -} - -TEST(Table, LazyEmplace) { - StringTable t; - bool called = false; - auto it = t.lazy_emplace("abc", [&](const StringTable::constructor& f) { - called = true; - f("abc", "ABC"); - }); - EXPECT_TRUE(called); - EXPECT_THAT(*it, Pair("abc", "ABC")); - called = false; - it = t.lazy_emplace("abc", [&](const StringTable::constructor& f) { - called = true; - f("abc", "DEF"); - }); - EXPECT_FALSE(called); - EXPECT_THAT(*it, Pair("abc", "ABC")); -} - -TEST(Table, ContainsEmpty) { - IntTable t; - - EXPECT_FALSE(t.contains(0)); -} - -TEST(Table, Contains1) { - IntTable t; - - EXPECT_TRUE(t.insert(0).second); - EXPECT_TRUE(t.contains(0)); - EXPECT_FALSE(t.contains(1)); - - EXPECT_EQ(1, t.erase(0)); - EXPECT_FALSE(t.contains(0)); -} - -TEST(Table, Contains2) { - IntTable t; - - EXPECT_TRUE(t.insert(0).second); - EXPECT_TRUE(t.contains(0)); - EXPECT_FALSE(t.contains(1)); - - t.clear(); - EXPECT_FALSE(t.contains(0)); -} - -int decompose_constructed; -struct DecomposeType { - DecomposeType(int i) : i(i) { // NOLINT - ++decompose_constructed; - } - - explicit DecomposeType(const char* d) : DecomposeType(*d) {} - - int i; -}; - -struct DecomposeHash { - using is_transparent = void; - 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()(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 { - using slot_type = DecomposeType; - using key_type = DecomposeType; - using init_type = DecomposeType; - - template <typename T> - static void construct(void*, DecomposeType* slot, T&& v) { - *slot = DecomposeType(std::forward<T>(v)); - } - static void destroy(void*, DecomposeType*) {} - static DecomposeType& element(slot_type* slot) { return *slot; } - - template <class F, class T> - static auto apply(F&& f, const T& x) -> decltype(std::forward<F>(f)(x, x)) { - return std::forward<F>(f)(x, x); - } -}; - -template <typename Hash, typename Eq> -void TestDecompose(bool construct_three) { - DecomposeType elem{0}; - const int one = 1; - const char* three_p = "3"; - const auto& three = three_p; - - raw_hash_set<DecomposePolicy, Hash, Eq, std::allocator<int>> set1; - - decompose_constructed = 0; - int expected_constructed = 0; - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.insert(elem); - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.insert(1); - EXPECT_EQ(++expected_constructed, decompose_constructed); - set1.emplace("3"); - EXPECT_EQ(++expected_constructed, decompose_constructed); - EXPECT_EQ(expected_constructed, decompose_constructed); - - { // insert(T&&) - set1.insert(1); - EXPECT_EQ(expected_constructed, decompose_constructed); - } - - { // insert(const T&) - set1.insert(one); - EXPECT_EQ(expected_constructed, decompose_constructed); - } - - { // insert(hint, T&&) - set1.insert(set1.begin(), 1); - EXPECT_EQ(expected_constructed, decompose_constructed); - } - - { // insert(hint, const T&) - set1.insert(set1.begin(), one); - EXPECT_EQ(expected_constructed, decompose_constructed); - } - - { // emplace(...) - set1.emplace(1); - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace("3"); - expected_constructed += construct_three; - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace(one); - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace(three); - expected_constructed += construct_three; - EXPECT_EQ(expected_constructed, decompose_constructed); - } - - { // emplace_hint(...) - set1.emplace_hint(set1.begin(), 1); - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace_hint(set1.begin(), "3"); - expected_constructed += construct_three; - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace_hint(set1.begin(), one); - EXPECT_EQ(expected_constructed, decompose_constructed); - set1.emplace_hint(set1.begin(), three); - expected_constructed += construct_three; - EXPECT_EQ(expected_constructed, decompose_constructed); - } -} - -TEST(Table, Decompose) { - TestDecompose<DecomposeHash, DecomposeEq>(false); - - struct TransparentHashIntOverload { - size_t operator()(DecomposeType a) const { return a.i; } - size_t operator()(int a) const { return a; } - }; - struct TransparentEqIntOverload { - bool operator()(DecomposeType a, DecomposeType b) const { - return a.i == b.i; - } - bool operator()(DecomposeType a, int b) const { return a.i == b; } - }; - TestDecompose<TransparentHashIntOverload, DecomposeEq>(true); - TestDecompose<TransparentHashIntOverload, TransparentEqIntOverload>(true); - TestDecompose<DecomposeHash, TransparentEqIntOverload>(true); -} - -// Returns the largest m such that a table with m elements has the same number -// of buckets as a table with n elements. -size_t MaxDensitySize(size_t n) { - IntTable t; - t.reserve(n); - for (size_t i = 0; i != n; ++i) t.emplace(i); - const size_t c = t.bucket_count(); - while (c == t.bucket_count()) t.emplace(n++); - return t.size() - 1; -} - -struct Modulo1000Hash { - size_t operator()(int x) const { return x % 1000; } -}; - -struct Modulo1000HashTable - : public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<int>, - std::allocator<int>> {}; - -// Test that rehash with no resize happen in case of many deleted slots. -TEST(Table, RehashWithNoResize) { - Modulo1000HashTable t; - // Adding the same length (and the same hash) strings - // to have at least kMinFullGroups groups - // with Group::kWidth collisions. Then fill up to MaxDensitySize; - const size_t kMinFullGroups = 7; - std::vector<int> keys; - for (size_t i = 0; i < MaxDensitySize(Group::kWidth * kMinFullGroups); ++i) { - int k = i * 1000; - t.emplace(k); - keys.push_back(k); - } - 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 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) { - EXPECT_EQ(1, t.erase(keys[i])) << i; - } - keys.erase(keys.begin() + erase_begin, keys.begin() + erase_end); - - auto last_key = keys.back(); - size_t last_key_num_probes = GetHashtableDebugNumProbes(t, last_key); - - // Make sure that we have to make a lot of probes for last key. - ASSERT_GT(last_key_num_probes, kMinFullGroups); - - int x = 1; - // Insert and erase one element, before inplace rehash happen. - while (last_key_num_probes == GetHashtableDebugNumProbes(t, last_key)) { - t.emplace(x); - ASSERT_EQ(capacity, t.capacity()); - // All elements should be there. - ASSERT_TRUE(t.find(x) != t.end()) << x; - for (const auto& k : keys) { - ASSERT_TRUE(t.find(k) != t.end()) << k; - } - t.erase(x); - ++x; - } -} - -TEST(Table, InsertEraseStressTest) { - IntTable t; - const size_t kMinElementCount = 250; - std::deque<int> keys; - size_t i = 0; - for (; i < MaxDensitySize(kMinElementCount); ++i) { - t.emplace(i); - keys.push_back(i); - } - const size_t kNumIterations = 1000000; - for (; i < kNumIterations; ++i) { - ASSERT_EQ(1, t.erase(keys.front())); - keys.pop_front(); - t.emplace(i); - keys.push_back(i); - } -} - -TEST(Table, InsertOverloads) { - StringTable t; - // These should all trigger the insert(init_type) overload. - t.insert({{}, {}}); - t.insert({"ABC", {}}); - t.insert({"DEF", "!!!"}); - - EXPECT_THAT(t, UnorderedElementsAre(Pair("", ""), Pair("ABC", ""), - Pair("DEF", "!!!"))); -} - -TEST(Table, LargeTable) { - IntTable t; - for (int64_t i = 0; i != 100000; ++i) t.emplace(i << 40); - for (int64_t i = 0; i != 100000; ++i) ASSERT_EQ(i << 40, *t.find(i << 40)); -} - -// Timeout if copy is quadratic as it was in Rust. -TEST(Table, EnsureNonQuadraticAsInRust) { - static const size_t kLargeSize = 1 << 15; - - IntTable t; - for (size_t i = 0; i != kLargeSize; ++i) { - t.insert(i); - } - - // If this is quadratic, the test will timeout. - IntTable t2; - for (const auto& entry : t) t2.insert(entry); -} - -TEST(Table, ClearBug) { - IntTable t; - constexpr size_t capacity = container_internal::Group::kWidth - 1; - constexpr size_t max_size = capacity / 2 + 1; - for (size_t i = 0; i < max_size; ++i) { - t.insert(i); - } - ASSERT_EQ(capacity, t.capacity()); - intptr_t original = reinterpret_cast<intptr_t>(&*t.find(2)); - t.clear(); - ASSERT_EQ(capacity, t.capacity()); - for (size_t i = 0; i < max_size; ++i) { - t.insert(i); - } - ASSERT_EQ(capacity, t.capacity()); - intptr_t second = reinterpret_cast<intptr_t>(&*t.find(2)); - // We are checking that original and second are close enough to each other - // that they are probably still in the same group. This is not strictly - // guaranteed. - EXPECT_LT(std::abs(original - second), - capacity * sizeof(IntTable::value_type)); -} - -TEST(Table, Erase) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - auto res = t.emplace(0); - EXPECT_TRUE(res.second); - EXPECT_EQ(1, t.size()); - t.erase(res.first); - EXPECT_EQ(0, t.size()); - EXPECT_TRUE(t.find(0) == t.end()); -} - -TEST(Table, EraseMaintainsValidIterator) { - IntTable t; - const int kNumElements = 100; - for (int i = 0; i < kNumElements; i ++) { - EXPECT_TRUE(t.emplace(i).second); - } - EXPECT_EQ(t.size(), kNumElements); - - int num_erase_calls = 0; - auto it = t.begin(); - while (it != t.end()) { - t.erase(it++); - num_erase_calls++; - } - - EXPECT_TRUE(t.empty()); - EXPECT_EQ(num_erase_calls, kNumElements); -} - -// Collect N bad keys by following algorithm: -// 1. Create an empty table and reserve it to 2 * N. -// 2. Insert N random elements. -// 3. Take first Group::kWidth - 1 to bad_keys array. -// 4. Clear the table without resize. -// 5. Go to point 2 while N keys not collected -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> { - for (size_t i = b; i != e; ++i) { - t->emplace(i); - } - std::vector<int64_t> res; - res.reserve(kGroupSize); - auto it = t->begin(); - for (size_t i = b; i != e && i != b + kGroupSize; ++i, ++it) { - res.push_back(*it); - } - return res; - }; - - std::vector<int64_t> bad_keys; - bad_keys.reserve(N); - IntTable t; - t.reserve(N * 2); - - for (size_t b = 0; bad_keys.size() < N; b += N) { - auto keys = topk_range(b, b + N, &t); - bad_keys.insert(bad_keys.end(), keys.begin(), keys.end()); - t.erase(t.begin(), t.end()); - EXPECT_TRUE(t.empty()); - } - return bad_keys; -} - -struct ProbeStats { - // Number of elements with specific probe length over all tested tables. - std::vector<size_t> all_probes_histogram; - // Ratios total_probe_length/size for every tested table. - std::vector<double> single_table_ratios; - - friend ProbeStats operator+(const ProbeStats& a, const ProbeStats& b) { - ProbeStats res = a; - res.all_probes_histogram.resize(std::max(res.all_probes_histogram.size(), - b.all_probes_histogram.size())); - std::transform(b.all_probes_histogram.begin(), b.all_probes_histogram.end(), - res.all_probes_histogram.begin(), - res.all_probes_histogram.begin(), std::plus<size_t>()); - res.single_table_ratios.insert(res.single_table_ratios.end(), - b.single_table_ratios.begin(), - b.single_table_ratios.end()); - return res; - } - - // Average ratio total_probe_length/size over tables. - double AvgRatio() const { - return std::accumulate(single_table_ratios.begin(), - single_table_ratios.end(), 0.0) / - single_table_ratios.size(); - } - - // Maximum ratio total_probe_length/size over tables. - double MaxRatio() const { - return *std::max_element(single_table_ratios.begin(), - single_table_ratios.end()); - } - - // Percentile ratio total_probe_length/size over tables. - double PercentileRatio(double Percentile = 0.95) const { - auto r = single_table_ratios; - auto mid = r.begin() + static_cast<size_t>(r.size() * Percentile); - if (mid != r.end()) { - std::nth_element(r.begin(), mid, r.end()); - return *mid; - } else { - return MaxRatio(); - } - } - - // Maximum probe length over all elements and all tables. - size_t MaxProbe() const { return all_probes_histogram.size(); } - - // Fraction of elements with specified probe length. - std::vector<double> ProbeNormalizedHistogram() const { - double total_elements = std::accumulate(all_probes_histogram.begin(), - all_probes_histogram.end(), 0ull); - std::vector<double> res; - for (size_t p : all_probes_histogram) { - res.push_back(p / total_elements); - } - return res; - } - - size_t PercentileProbe(double Percentile = 0.99) const { - size_t idx = 0; - for (double p : ProbeNormalizedHistogram()) { - if (Percentile > p) { - Percentile -= p; - ++idx; - } else { - return idx; - } - } - return idx; - } - - friend std::ostream& operator<<(std::ostream& out, const ProbeStats& s) { - out << "{AvgRatio:" << s.AvgRatio() << ", MaxRatio:" << s.MaxRatio() - << ", PercentileRatio:" << s.PercentileRatio() - << ", MaxProbe:" << s.MaxProbe() << ", Probes=["; - for (double p : s.ProbeNormalizedHistogram()) { - out << p << ","; - } - out << "]}"; - - return out; - } -}; - -struct ExpectedStats { - double avg_ratio; - double max_ratio; - std::vector<std::pair<double, double>> pecentile_ratios; - std::vector<std::pair<double, double>> pecentile_probes; - - friend std::ostream& operator<<(std::ostream& out, const ExpectedStats& s) { - out << "{AvgRatio:" << s.avg_ratio << ", MaxRatio:" << s.max_ratio - << ", PercentileRatios: ["; - for (auto el : s.pecentile_ratios) { - out << el.first << ":" << el.second << ", "; - } - out << "], PercentileProbes: ["; - for (auto el : s.pecentile_probes) { - out << el.first << ":" << el.second << ", "; - } - out << "]}"; - - return out; - } -}; - -void VerifyStats(size_t size, const ExpectedStats& exp, - const ProbeStats& stats) { - EXPECT_LT(stats.AvgRatio(), exp.avg_ratio) << size << " " << stats; - EXPECT_LT(stats.MaxRatio(), exp.max_ratio) << size << " " << stats; - for (auto pr : exp.pecentile_ratios) { - EXPECT_LE(stats.PercentileRatio(pr.first), pr.second) - << size << " " << pr.first << " " << stats; - } - - for (auto pr : exp.pecentile_probes) { - EXPECT_LE(stats.PercentileProbe(pr.first), pr.second) - << size << " " << pr.first << " " << stats; - } -} - -using ProbeStatsPerSize = std::map<size_t, ProbeStats>; - -// Collect total ProbeStats on num_iters iterations of the following algorithm: -// 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) { - const size_t reserve_size = keys.size() * 2; - - ProbeStats stats; - - int64_t seed = 0x71b1a19b907d6e33; - while (num_iters--) { - seed = static_cast<int64_t>(static_cast<uint64_t>(seed) * 17 + 13); - IntTable t1; - t1.reserve(reserve_size); - for (const auto& key : keys) { - t1.emplace(key ^ seed); - } - - auto probe_histogram = GetHashtableDebugNumProbesHistogram(t1); - stats.all_probes_histogram.resize( - std::max(stats.all_probes_histogram.size(), probe_histogram.size())); - std::transform(probe_histogram.begin(), probe_histogram.end(), - stats.all_probes_histogram.begin(), - stats.all_probes_histogram.begin(), std::plus<size_t>()); - - size_t total_probe_seq_length = 0; - for (size_t i = 0; i < probe_histogram.size(); ++i) { - total_probe_seq_length += i * probe_histogram[i]; - } - stats.single_table_ratios.push_back(total_probe_seq_length * 1.0 / - keys.size()); - t1.erase(t1.begin(), t1.end()); - } - return stats; -} - -ExpectedStats XorSeedExpectedStats() { - constexpr bool kRandomizesInserts = -#ifdef NDEBUG - false; -#else // NDEBUG - true; -#endif // NDEBUG - - // The effective load factor is larger in non-opt mode because we insert - // elements out of order. - switch (container_internal::Group::kWidth) { - case 8: - if (kRandomizesInserts) { - return {0.05, - 1.0, - {{0.95, 0.5}}, - {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}}; - } else { - return {0.05, - 2.0, - {{0.95, 0.1}}, - {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}}; - } - case 16: - if (kRandomizesInserts) { - return {0.1, - 1.0, - {{0.95, 0.1}}, - {{0.95, 0}, {0.99, 1}, {0.999, 8}, {0.9999, 15}}}; - } else { - return {0.05, - 1.0, - {{0.95, 0.05}}, - {{0.95, 0}, {0.99, 1}, {0.999, 4}, {0.9999, 10}}}; - } - } - ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); - return {}; -} - -TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) { - ProbeStatsPerSize stats; - std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10}; - for (size_t size : sizes) { - stats[size] = - CollectProbeStatsOnKeysXoredWithSeed(CollectBadMergeKeys(size), 200); - } - auto expected = XorSeedExpectedStats(); - for (size_t size : sizes) { - auto& stat = stats[size]; - VerifyStats(size, expected, stat); - } -} - -// Collect total ProbeStats on num_iters iterations of the following algorithm: -// 1. Create new table -// 2. Select 10% of keys and insert 10 elements key * 17 + j * 13 -// 3. Collect ProbeStats from final table -ProbeStats CollectProbeStatsOnLinearlyTransformedKeys( - const std::vector<int64_t>& keys, size_t num_iters) { - ProbeStats stats; - - std::random_device rd; - std::mt19937 rng(rd()); - auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; }; - std::uniform_int_distribution<size_t> dist(0, keys.size()-1); - while (num_iters--) { - IntTable t1; - size_t num_keys = keys.size() / 10; - size_t start = dist(rng); - for (size_t i = 0; i != num_keys; ++i) { - for (size_t j = 0; j != 10; ++j) { - t1.emplace(linear_transform(keys[(i + start) % keys.size()], j)); - } - } - - auto probe_histogram = GetHashtableDebugNumProbesHistogram(t1); - stats.all_probes_histogram.resize( - std::max(stats.all_probes_histogram.size(), probe_histogram.size())); - std::transform(probe_histogram.begin(), probe_histogram.end(), - stats.all_probes_histogram.begin(), - stats.all_probes_histogram.begin(), std::plus<size_t>()); - - size_t total_probe_seq_length = 0; - for (size_t i = 0; i < probe_histogram.size(); ++i) { - total_probe_seq_length += i * probe_histogram[i]; - } - stats.single_table_ratios.push_back(total_probe_seq_length * 1.0 / - t1.size()); - t1.erase(t1.begin(), t1.end()); - } - return stats; -} - -ExpectedStats LinearTransformExpectedStats() { - constexpr bool kRandomizesInserts = -#ifdef NDEBUG - false; -#else // NDEBUG - true; -#endif // NDEBUG - - // The effective load factor is larger in non-opt mode because we insert - // elements out of order. - switch (container_internal::Group::kWidth) { - case 8: - if (kRandomizesInserts) { - return {0.1, - 0.5, - {{0.95, 0.3}}, - {{0.95, 0}, {0.99, 1}, {0.999, 8}, {0.9999, 15}}}; - } else { - return {0.15, - 0.5, - {{0.95, 0.3}}, - {{0.95, 0}, {0.99, 3}, {0.999, 15}, {0.9999, 25}}}; - } - case 16: - if (kRandomizesInserts) { - return {0.1, - 0.4, - {{0.95, 0.3}}, - {{0.95, 0}, {0.99, 1}, {0.999, 8}, {0.9999, 15}}}; - } else { - return {0.05, - 0.2, - {{0.95, 0.1}}, - {{0.95, 0}, {0.99, 1}, {0.999, 6}, {0.9999, 10}}}; - } - } - ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); - return {}; -} - -TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) { - ProbeStatsPerSize stats; - std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10}; - for (size_t size : sizes) { - stats[size] = CollectProbeStatsOnLinearlyTransformedKeys( - CollectBadMergeKeys(size), 300); - } - auto expected = LinearTransformExpectedStats(); - for (size_t size : sizes) { - auto& stat = stats[size]; - VerifyStats(size, expected, stat); - } -} - -TEST(Table, EraseCollision) { - BadTable t; - - // 1 2 3 - t.emplace(1); - t.emplace(2); - t.emplace(3); - EXPECT_THAT(*t.find(1), 1); - EXPECT_THAT(*t.find(2), 2); - EXPECT_THAT(*t.find(3), 3); - EXPECT_EQ(3, t.size()); - - // 1 DELETED 3 - t.erase(t.find(2)); - EXPECT_THAT(*t.find(1), 1); - EXPECT_TRUE(t.find(2) == t.end()); - EXPECT_THAT(*t.find(3), 3); - EXPECT_EQ(2, t.size()); - - // DELETED DELETED 3 - t.erase(t.find(1)); - EXPECT_TRUE(t.find(1) == t.end()); - EXPECT_TRUE(t.find(2) == t.end()); - EXPECT_THAT(*t.find(3), 3); - EXPECT_EQ(1, t.size()); - - // DELETED DELETED DELETED - t.erase(t.find(3)); - EXPECT_TRUE(t.find(1) == t.end()); - EXPECT_TRUE(t.find(2) == t.end()); - EXPECT_TRUE(t.find(3) == t.end()); - EXPECT_EQ(0, t.size()); -} - -TEST(Table, EraseInsertProbing) { - BadTable t(100); - - // 1 2 3 4 - t.emplace(1); - t.emplace(2); - t.emplace(3); - t.emplace(4); - - // 1 DELETED 3 DELETED - t.erase(t.find(2)); - t.erase(t.find(4)); - - // 1 10 3 11 12 - t.emplace(10); - t.emplace(11); - t.emplace(12); - - EXPECT_EQ(5, t.size()); - EXPECT_THAT(t, UnorderedElementsAre(1, 10, 3, 11, 12)); -} - -TEST(Table, Clear) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - t.clear(); - EXPECT_TRUE(t.find(0) == t.end()); - auto res = t.emplace(0); - EXPECT_TRUE(res.second); - EXPECT_EQ(1, t.size()); - t.clear(); - EXPECT_EQ(0, t.size()); - EXPECT_TRUE(t.find(0) == t.end()); -} - -TEST(Table, Swap) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - auto res = t.emplace(0); - EXPECT_TRUE(res.second); - EXPECT_EQ(1, t.size()); - IntTable u; - t.swap(u); - EXPECT_EQ(0, t.size()); - EXPECT_EQ(1, u.size()); - EXPECT_TRUE(t.find(0) == t.end()); - EXPECT_THAT(*u.find(0), 0); -} - -TEST(Table, Rehash) { - IntTable t; - EXPECT_TRUE(t.find(0) == t.end()); - t.emplace(0); - t.emplace(1); - EXPECT_EQ(2, t.size()); - t.rehash(128); - EXPECT_EQ(2, t.size()); - EXPECT_THAT(*t.find(0), 0); - EXPECT_THAT(*t.find(1), 1); -} - -TEST(Table, RehashDoesNotRehashWhenNotNecessary) { - IntTable t; - t.emplace(0); - t.emplace(1); - auto* p = &*t.find(0); - t.rehash(1); - EXPECT_EQ(p, &*t.find(0)); -} - -TEST(Table, RehashZeroDoesNotAllocateOnEmptyTable) { - IntTable t; - t.rehash(0); - EXPECT_EQ(0, t.bucket_count()); -} - -TEST(Table, RehashZeroDeallocatesEmptyTable) { - IntTable t; - t.emplace(0); - t.clear(); - EXPECT_NE(0, t.bucket_count()); - t.rehash(0); - EXPECT_EQ(0, t.bucket_count()); -} - -TEST(Table, RehashZeroForcesRehash) { - IntTable t; - t.emplace(0); - t.emplace(1); - auto* p = &*t.find(0); - t.rehash(0); - EXPECT_NE(p, &*t.find(0)); -} - -TEST(Table, ConstructFromInitList) { - using P = std::pair<std::string, std::string>; - struct Q { - operator P() const { return {}; } - }; - StringTable t = {P(), Q(), {}, {{}, {}}}; -} - -TEST(Table, CopyConstruct) { - IntTable t; - t.emplace(0); - EXPECT_EQ(1, t.size()); - { - IntTable u(t); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find(0), 0); - } - { - IntTable u{t}; - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find(0), 0); - } - { - IntTable u = t; - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find(0), 0); - } -} - -TEST(Table, CopyConstructWithAlloc) { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - StringTable u(t, Alloc<std::pair<std::string, std::string>>()); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); -} - -struct ExplicitAllocIntTable - : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>, - std::equal_to<int64_t>, Alloc<int64_t>> { - ExplicitAllocIntTable() {} -}; - -TEST(Table, AllocWithExplicitCtor) { - ExplicitAllocIntTable t; - EXPECT_EQ(0, t.size()); -} - -TEST(Table, MoveConstruct) { - { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - - StringTable u(std::move(t)); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); - } - { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - - StringTable u{std::move(t)}; - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); - } - { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - - StringTable u = std::move(t); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); - } -} - -TEST(Table, MoveConstructWithAlloc) { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - StringTable u(std::move(t), Alloc<std::pair<std::string, std::string>>()); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); -} - -TEST(Table, CopyAssign) { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - StringTable u; - u = t; - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); -} - -TEST(Table, CopySelfAssign) { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - t = *&t; - EXPECT_EQ(1, t.size()); - EXPECT_THAT(*t.find("a"), Pair("a", "b")); -} - -TEST(Table, MoveAssign) { - StringTable t; - t.emplace("a", "b"); - EXPECT_EQ(1, t.size()); - StringTable u; - u = std::move(t); - EXPECT_EQ(1, u.size()); - EXPECT_THAT(*u.find("a"), Pair("a", "b")); -} - -TEST(Table, Equality) { - StringTable t; - std::vector<std::pair<std::string, std::string>> v = {{"a", "b"}, - {"aa", "bb"}}; - t.insert(std::begin(v), std::end(v)); - StringTable u = t; - EXPECT_EQ(u, t); -} - -TEST(Table, Equality2) { - StringTable t; - std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"}, - {"aa", "bb"}}; - t.insert(std::begin(v1), std::end(v1)); - StringTable u; - std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, - {"aa", "aa"}}; - u.insert(std::begin(v2), std::end(v2)); - EXPECT_NE(u, t); -} - -TEST(Table, Equality3) { - StringTable t; - std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"}, - {"bb", "bb"}}; - t.insert(std::begin(v1), std::end(v1)); - StringTable u; - std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, - {"aa", "aa"}}; - u.insert(std::begin(v2), std::end(v2)); - EXPECT_NE(u, t); -} - -TEST(Table, NumDeletedRegression) { - IntTable t; - t.emplace(0); - t.erase(t.find(0)); - // construct over a deleted slot. - t.emplace(0); - t.clear(); -} - -TEST(Table, FindFullDeletedRegression) { - IntTable t; - for (int i = 0; i < 1000; ++i) { - t.emplace(i); - t.erase(t.find(i)); - } - EXPECT_EQ(0, t.size()); -} - -TEST(Table, ReplacingDeletedSlotDoesNotRehash) { - size_t n; - { - // Compute n such that n is the maximum number of elements before rehash. - IntTable t; - t.emplace(0); - size_t c = t.bucket_count(); - for (n = 1; c == t.bucket_count(); ++n) t.emplace(n); - --n; - } - IntTable t; - t.rehash(n); - const size_t c = t.bucket_count(); - for (size_t i = 0; i != n; ++i) t.emplace(i); - EXPECT_EQ(c, t.bucket_count()) << "rehashing threshold = " << n; - t.erase(0); - t.emplace(0); - EXPECT_EQ(c, t.bucket_count()) << "rehashing threshold = " << n; -} - -TEST(Table, NoThrowMoveConstruct) { - ASSERT_TRUE( - std::is_nothrow_copy_constructible<absl::Hash<absl::string_view>>::value); - ASSERT_TRUE(std::is_nothrow_copy_constructible< - std::equal_to<absl::string_view>>::value); - ASSERT_TRUE(std::is_nothrow_copy_constructible<std::allocator<int>>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<StringTable>::value); -} - -TEST(Table, NoThrowMoveAssign) { - ASSERT_TRUE( - std::is_nothrow_move_assignable<absl::Hash<absl::string_view>>::value); - ASSERT_TRUE( - std::is_nothrow_move_assignable<std::equal_to<absl::string_view>>::value); - ASSERT_TRUE(std::is_nothrow_move_assignable<std::allocator<int>>::value); - ASSERT_TRUE( - absl::allocator_traits<std::allocator<int>>::is_always_equal::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<StringTable>::value); -} - -TEST(Table, NoThrowSwappable) { - ASSERT_TRUE( - container_internal::IsNoThrowSwappable<absl::Hash<absl::string_view>>()); - ASSERT_TRUE(container_internal::IsNoThrowSwappable< - std::equal_to<absl::string_view>>()); - ASSERT_TRUE(container_internal::IsNoThrowSwappable<std::allocator<int>>()); - EXPECT_TRUE(container_internal::IsNoThrowSwappable<StringTable>()); -} - -TEST(Table, HeterogeneousLookup) { - struct Hash { - size_t operator()(int64_t i) const { return i; } - size_t operator()(double i) const { - ADD_FAILURE(); - return i; - } - }; - struct Eq { - bool operator()(int64_t a, int64_t b) const { return a == b; } - bool operator()(double a, int64_t b) const { - ADD_FAILURE(); - return a == b; - } - bool operator()(int64_t a, double b) const { - ADD_FAILURE(); - return a == b; - } - bool operator()(double a, double b) const { - ADD_FAILURE(); - return a == b; - } - }; - - struct THash { - using is_transparent = void; - size_t operator()(int64_t i) const { return i; } - size_t operator()(double i) const { return i; } - }; - struct TEq { - using is_transparent = void; - bool operator()(int64_t a, int64_t b) const { return a == b; } - bool operator()(double a, int64_t b) const { return a == b; } - bool operator()(int64_t a, double b) const { return a == b; } - bool operator()(double a, double b) const { return a == b; } - }; - - raw_hash_set<IntPolicy, Hash, Eq, Alloc<int64_t>> s{0, 1, 2}; - // It will convert to int64_t before the query. - EXPECT_EQ(1, *s.find(double{1.1})); - - raw_hash_set<IntPolicy, THash, TEq, Alloc<int64_t>> ts{0, 1, 2}; - // It will try to use the double, and fail to find the object. - EXPECT_TRUE(ts.find(1.1) == ts.end()); -} - -template <class Table> -using CallFind = decltype(std::declval<Table&>().find(17)); - -template <class Table> -using CallErase = decltype(std::declval<Table&>().erase(17)); - -template <class Table> -using CallExtract = decltype(std::declval<Table&>().extract(17)); - -template <class Table> -using CallPrefetch = decltype(std::declval<Table&>().prefetch(17)); - -template <class Table> -using CallCount = decltype(std::declval<Table&>().count(17)); - -template <template <typename> class C, class Table, class = void> -struct VerifyResultOf : std::false_type {}; - -template <template <typename> class C, class Table> -struct VerifyResultOf<C, Table, absl::void_t<C<Table>>> : std::true_type {}; - -TEST(Table, HeterogeneousLookupOverloads) { - using NonTransparentTable = - raw_hash_set<StringPolicy, absl::Hash<absl::string_view>, - std::equal_to<absl::string_view>, std::allocator<int>>; - - EXPECT_FALSE((VerifyResultOf<CallFind, NonTransparentTable>())); - EXPECT_FALSE((VerifyResultOf<CallErase, NonTransparentTable>())); - EXPECT_FALSE((VerifyResultOf<CallExtract, NonTransparentTable>())); - EXPECT_FALSE((VerifyResultOf<CallPrefetch, NonTransparentTable>())); - EXPECT_FALSE((VerifyResultOf<CallCount, NonTransparentTable>())); - - using TransparentTable = raw_hash_set< - StringPolicy, - absl::container_internal::hash_default_hash<absl::string_view>, - absl::container_internal::hash_default_eq<absl::string_view>, - std::allocator<int>>; - - EXPECT_TRUE((VerifyResultOf<CallFind, TransparentTable>())); - EXPECT_TRUE((VerifyResultOf<CallErase, TransparentTable>())); - EXPECT_TRUE((VerifyResultOf<CallExtract, TransparentTable>())); - EXPECT_TRUE((VerifyResultOf<CallPrefetch, TransparentTable>())); - EXPECT_TRUE((VerifyResultOf<CallCount, TransparentTable>())); -} - -// TODO(alkis): Expand iterator tests. -TEST(Iterator, IsDefaultConstructible) { - StringTable::iterator i; - EXPECT_TRUE(i == StringTable::iterator()); -} - -TEST(ConstIterator, IsDefaultConstructible) { - StringTable::const_iterator i; - EXPECT_TRUE(i == StringTable::const_iterator()); -} - -TEST(Iterator, ConvertsToConstIterator) { - StringTable::iterator i; - EXPECT_TRUE(i == StringTable::const_iterator()); -} - -TEST(Iterator, Iterates) { - IntTable t; - for (size_t i = 3; i != 6; ++i) EXPECT_TRUE(t.emplace(i).second); - EXPECT_THAT(t, UnorderedElementsAre(3, 4, 5)); -} - -TEST(Table, Merge) { - StringTable t1, t2; - t1.emplace("0", "-0"); - t1.emplace("1", "-1"); - t2.emplace("0", "~0"); - t2.emplace("2", "~2"); - - EXPECT_THAT(t1, UnorderedElementsAre(Pair("0", "-0"), Pair("1", "-1"))); - EXPECT_THAT(t2, UnorderedElementsAre(Pair("0", "~0"), Pair("2", "~2"))); - - t1.merge(t2); - EXPECT_THAT(t1, UnorderedElementsAre(Pair("0", "-0"), Pair("1", "-1"), - Pair("2", "~2"))); - EXPECT_THAT(t2, UnorderedElementsAre(Pair("0", "~0"))); -} - -TEST(Nodes, EmptyNodeType) { - using node_type = StringTable::node_type; - node_type n; - EXPECT_FALSE(n); - EXPECT_TRUE(n.empty()); - - EXPECT_TRUE((std::is_same<node_type::allocator_type, - StringTable::allocator_type>::value)); -} - -TEST(Nodes, ExtractInsert) { - constexpr char k0[] = "Very long string zero."; - constexpr char k1[] = "Very long string one."; - constexpr char k2[] = "Very long string two."; - StringTable t = {{k0, ""}, {k1, ""}, {k2, ""}}; - EXPECT_THAT(t, - UnorderedElementsAre(Pair(k0, ""), Pair(k1, ""), Pair(k2, ""))); - - auto node = t.extract(k0); - EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, ""), Pair(k2, ""))); - EXPECT_TRUE(node); - EXPECT_FALSE(node.empty()); - - StringTable t2; - StringTable::insert_return_type res = t2.insert(std::move(node)); - EXPECT_TRUE(res.inserted); - EXPECT_THAT(*res.position, Pair(k0, "")); - EXPECT_FALSE(res.node); - EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, ""))); - - // Not there. - EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, ""), Pair(k2, ""))); - node = t.extract("Not there!"); - EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, ""), Pair(k2, ""))); - EXPECT_FALSE(node); - - // Inserting nothing. - res = t2.insert(std::move(node)); - EXPECT_FALSE(res.inserted); - EXPECT_EQ(res.position, t2.end()); - EXPECT_FALSE(res.node); - EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, ""))); - - t.emplace(k0, "1"); - node = t.extract(k0); - - // Insert duplicate. - res = t2.insert(std::move(node)); - EXPECT_FALSE(res.inserted); - EXPECT_THAT(*res.position, Pair(k0, "")); - EXPECT_TRUE(res.node); - 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()); - return t; -} - -std::vector<int> OrderOfIteration(const IntTable& t) { - return {t.begin(), t.end()}; -} - -// These IterationOrderChanges tests depend on non-deterministic behavior. -// We are injecting non-determinism from the pointer of the table, but do so in -// a way that only the page matters. We have to retry enough times to make sure -// we are touching different memory pages to cause the ordering to change. -// We also need to keep the old tables around to avoid getting the same memory -// blocks over and over. -TEST(Table, IterationOrderChangesByInstance) { - for (size_t size : {2, 6, 12, 20}) { - const auto reference_table = MakeSimpleTable(size); - const auto reference = OrderOfIteration(reference_table); - - std::vector<IntTable> tables; - bool found_difference = false; - for (int i = 0; !found_difference && i < 5000; ++i) { - tables.push_back(MakeSimpleTable(size)); - found_difference = OrderOfIteration(tables.back()) != reference; - } - if (!found_difference) { - FAIL() - << "Iteration order remained the same across many attempts with size " - << size; - } - } -} - -TEST(Table, IterationOrderChangesOnRehash) { - std::vector<IntTable> garbage; - for (int i = 0; i < 5000; ++i) { - auto t = MakeSimpleTable(20); - const auto reference = OrderOfIteration(t); - // Force rehash to the same size. - t.rehash(0); - auto trial = OrderOfIteration(t); - if (trial != reference) { - // We are done. - return; - } - garbage.push_back(std::move(t)); - } - FAIL() << "Iteration order remained the same across many attempts."; -} - -// Verify that pointers are invalidated as soon as a second element is inserted. -// This prevents dependency on pointer stability on small tables. -TEST(Table, UnstablePointers) { - IntTable table; - - const auto addr = [&](int i) { - return reinterpret_cast<uintptr_t>(&*table.find(i)); - }; - - table.insert(0); - const uintptr_t old_ptr = addr(0); - - // This causes a rehash. - table.insert(1); - - EXPECT_NE(old_ptr, addr(0)); -} - -// Confirm that we assert if we try to erase() end(). -TEST(TableDeathTest, EraseOfEndAsserts) { - // Use an assert with side-effects to figure out if they are actually enabled. - bool assert_enabled = false; - assert([&]() { - assert_enabled = true; - return true; - }()); - if (!assert_enabled) return; - - IntTable t; - // Extra simple "regexp" as regexp support is highly varied across platforms. - constexpr char kDeathMsg[] = "Invalid operation on iterator"; - EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg); -} - -#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) -TEST(RawHashSamplerTest, Sample) { - // Enable the feature even if the prod default is off. - SetHashtablezEnabled(true); - SetHashtablezSampleParameter(100); - - auto& sampler = HashtablezSampler::Global(); - size_t start_size = 0; - start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; }); - - std::vector<IntTable> tables; - for (int i = 0; i < 1000000; ++i) { - tables.emplace_back(); - tables.back().insert(1); - } - size_t end_size = 0; - end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; }); - - EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()), - 0.01, 0.005); -} -#endif // ABSL_INTERNAL_HASHTABLEZ_SAMPLE - -TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) { - // Enable the feature even if the prod default is off. - SetHashtablezEnabled(true); - SetHashtablezSampleParameter(100); - - auto& sampler = HashtablezSampler::Global(); - size_t start_size = 0; - start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; }); - - std::vector<CustomAllocIntTable> tables; - for (int i = 0; i < 1000000; ++i) { - tables.emplace_back(); - tables.back().insert(1); - } - size_t end_size = 0; - end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; }); - - EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()), - 0.00, 0.001); -} - -#ifdef ABSL_HAVE_ADDRESS_SANITIZER -TEST(Sanitizer, PoisoningUnused) { - IntTable t; - t.reserve(5); - // Insert something to force an allocation. - int64_t& v1 = *t.insert(0).first; - - // Make sure there is something to test. - ASSERT_GT(t.capacity(), 1); - - int64_t* slots = RawHashSetTestOnlyAccess::GetSlots(t); - for (size_t i = 0; i < t.capacity(); ++i) { - EXPECT_EQ(slots + i != &v1, __asan_address_is_poisoned(slots + i)); - } -} - -TEST(Sanitizer, PoisoningOnErase) { - IntTable t; - int64_t& v = *t.insert(0).first; - - EXPECT_FALSE(__asan_address_is_poisoned(&v)); - t.erase(0); - EXPECT_TRUE(__asan_address_is_poisoned(&v)); -} -#endif // ABSL_HAVE_ADDRESS_SANITIZER - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.cc b/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.cc deleted file mode 100644 index f9947f0475d2..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.cc +++ /dev/null @@ -1,29 +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/container/internal/test_instance_tracker.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace test_internal { -int BaseCountedInstance::num_instances_ = 0; -int BaseCountedInstance::num_live_instances_ = 0; -int BaseCountedInstance::num_moves_ = 0; -int BaseCountedInstance::num_copies_ = 0; -int BaseCountedInstance::num_swaps_ = 0; -int BaseCountedInstance::num_comparisons_ = 0; - -} // namespace test_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.h b/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.h deleted file mode 100644 index 5ff6fd714e2b..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker.h +++ /dev/null @@ -1,274 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_ -#define ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_ - -#include <cstdlib> -#include <ostream> - -#include "absl/types/compare.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace test_internal { - -// A type that counts number of occurrences of the type, the live occurrences of -// the type, as well as the number of copies, moves, swaps, and comparisons that -// have occurred on the type. This is used as a base class for the copyable, -// copyable+movable, and movable types below that are used in actual tests. Use -// InstanceTracker in tests to track the number of instances. -class BaseCountedInstance { - public: - explicit BaseCountedInstance(int x) : value_(x) { - ++num_instances_; - ++num_live_instances_; - } - BaseCountedInstance(const BaseCountedInstance& x) - : value_(x.value_), is_live_(x.is_live_) { - ++num_instances_; - if (is_live_) ++num_live_instances_; - ++num_copies_; - } - BaseCountedInstance(BaseCountedInstance&& x) - : value_(x.value_), is_live_(x.is_live_) { - x.is_live_ = false; - ++num_instances_; - ++num_moves_; - } - ~BaseCountedInstance() { - --num_instances_; - if (is_live_) --num_live_instances_; - } - - BaseCountedInstance& operator=(const BaseCountedInstance& x) { - value_ = x.value_; - if (is_live_) --num_live_instances_; - is_live_ = x.is_live_; - if (is_live_) ++num_live_instances_; - ++num_copies_; - return *this; - } - BaseCountedInstance& operator=(BaseCountedInstance&& x) { - value_ = x.value_; - if (is_live_) --num_live_instances_; - is_live_ = x.is_live_; - x.is_live_ = false; - ++num_moves_; - return *this; - } - - bool operator==(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ == x.value_; - } - - bool operator!=(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ != x.value_; - } - - bool operator<(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ < x.value_; - } - - bool operator>(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ > x.value_; - } - - bool operator<=(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ <= x.value_; - } - - bool operator>=(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ >= x.value_; - } - - absl::weak_ordering compare(const BaseCountedInstance& x) const { - ++num_comparisons_; - return value_ < x.value_ - ? absl::weak_ordering::less - : value_ == x.value_ ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; - } - - int value() const { - if (!is_live_) std::abort(); - return value_; - } - - friend std::ostream& operator<<(std::ostream& o, - const BaseCountedInstance& v) { - return o << "[value:" << v.value() << "]"; - } - - // Implementation of efficient swap() that counts swaps. - static void SwapImpl( - BaseCountedInstance& lhs, // NOLINT(runtime/references) - BaseCountedInstance& rhs) { // NOLINT(runtime/references) - using std::swap; - swap(lhs.value_, rhs.value_); - swap(lhs.is_live_, rhs.is_live_); - ++BaseCountedInstance::num_swaps_; - } - - private: - friend class InstanceTracker; - - int value_; - - // Indicates if the value is live, ie it hasn't been moved away from. - bool is_live_ = true; - - // Number of instances. - static int num_instances_; - - // Number of live instances (those that have not been moved away from.) - static int num_live_instances_; - - // Number of times that BaseCountedInstance objects were moved. - static int num_moves_; - - // Number of times that BaseCountedInstance objects were copied. - static int num_copies_; - - // Number of times that BaseCountedInstance objects were swapped. - static int num_swaps_; - - // Number of times that BaseCountedInstance objects were compared. - static int num_comparisons_; -}; - -// Helper to track the BaseCountedInstance instance counters. Expects that the -// number of instances and live_instances are the same when it is constructed -// and when it is destructed. -class InstanceTracker { - public: - InstanceTracker() - : start_instances_(BaseCountedInstance::num_instances_), - start_live_instances_(BaseCountedInstance::num_live_instances_) { - ResetCopiesMovesSwaps(); - } - ~InstanceTracker() { - if (instances() != 0) std::abort(); - if (live_instances() != 0) std::abort(); - } - - // Returns the number of BaseCountedInstance instances both containing valid - // values and those moved away from compared to when the InstanceTracker was - // constructed - int instances() const { - return BaseCountedInstance::num_instances_ - start_instances_; - } - - // Returns the number of live BaseCountedInstance instances compared to when - // the InstanceTracker was constructed - int live_instances() const { - return BaseCountedInstance::num_live_instances_ - start_live_instances_; - } - - // Returns the number of moves on BaseCountedInstance objects since - // construction or since the last call to ResetCopiesMovesSwaps(). - int moves() const { return BaseCountedInstance::num_moves_ - start_moves_; } - - // Returns the number of copies on BaseCountedInstance objects since - // construction or the last call to ResetCopiesMovesSwaps(). - int copies() const { - return BaseCountedInstance::num_copies_ - start_copies_; - } - - // Returns the number of swaps on BaseCountedInstance objects since - // construction or the last call to ResetCopiesMovesSwaps(). - int swaps() const { return BaseCountedInstance::num_swaps_ - start_swaps_; } - - // Returns the number of comparisons on BaseCountedInstance objects since - // construction or the last call to ResetCopiesMovesSwaps(). - int comparisons() const { - return BaseCountedInstance::num_comparisons_ - start_comparisons_; - } - - // Resets the base values for moves, copies, comparisons, and swaps to the - // current values, so that subsequent Get*() calls for moves, copies, - // comparisons, and swaps will compare to the situation at the point of this - // call. - void ResetCopiesMovesSwaps() { - start_moves_ = BaseCountedInstance::num_moves_; - start_copies_ = BaseCountedInstance::num_copies_; - start_swaps_ = BaseCountedInstance::num_swaps_; - start_comparisons_ = BaseCountedInstance::num_comparisons_; - } - - private: - int start_instances_; - int start_live_instances_; - int start_moves_; - int start_copies_; - int start_swaps_; - int start_comparisons_; -}; - -// Copyable, not movable. -class CopyableOnlyInstance : public BaseCountedInstance { - public: - explicit CopyableOnlyInstance(int x) : BaseCountedInstance(x) {} - CopyableOnlyInstance(const CopyableOnlyInstance& rhs) = default; - CopyableOnlyInstance& operator=(const CopyableOnlyInstance& rhs) = default; - - friend void swap(CopyableOnlyInstance& lhs, CopyableOnlyInstance& rhs) { - BaseCountedInstance::SwapImpl(lhs, rhs); - } - - static bool supports_move() { return false; } -}; - -// Copyable and movable. -class CopyableMovableInstance : public BaseCountedInstance { - public: - explicit CopyableMovableInstance(int x) : BaseCountedInstance(x) {} - CopyableMovableInstance(const CopyableMovableInstance& rhs) = default; - CopyableMovableInstance(CopyableMovableInstance&& rhs) = default; - CopyableMovableInstance& operator=(const CopyableMovableInstance& rhs) = - default; - CopyableMovableInstance& operator=(CopyableMovableInstance&& rhs) = default; - - friend void swap(CopyableMovableInstance& lhs, CopyableMovableInstance& rhs) { - BaseCountedInstance::SwapImpl(lhs, rhs); - } - - static bool supports_move() { return true; } -}; - -// Only movable, not default-constructible. -class MovableOnlyInstance : public BaseCountedInstance { - public: - explicit MovableOnlyInstance(int x) : BaseCountedInstance(x) {} - MovableOnlyInstance(MovableOnlyInstance&& other) = default; - MovableOnlyInstance& operator=(MovableOnlyInstance&& other) = default; - - friend void swap(MovableOnlyInstance& lhs, MovableOnlyInstance& rhs) { - BaseCountedInstance::SwapImpl(lhs, rhs); - } - - static bool supports_move() { return true; } -}; - -} // namespace test_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker_test.cc b/third_party/abseil_cpp/absl/container/internal/test_instance_tracker_test.cc deleted file mode 100644 index 1c6a4fa7150d..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/test_instance_tracker_test.cc +++ /dev/null @@ -1,184 +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/container/internal/test_instance_tracker.h" - -#include "gtest/gtest.h" - -namespace { - -using absl::test_internal::CopyableMovableInstance; -using absl::test_internal::CopyableOnlyInstance; -using absl::test_internal::InstanceTracker; -using absl::test_internal::MovableOnlyInstance; - -TEST(TestInstanceTracker, CopyableMovable) { - InstanceTracker tracker; - CopyableMovableInstance src(1); - EXPECT_EQ(1, src.value()) << src; - CopyableMovableInstance copy(src); - CopyableMovableInstance move(std::move(src)); - EXPECT_EQ(1, tracker.copies()); - EXPECT_EQ(1, tracker.moves()); - EXPECT_EQ(0, tracker.swaps()); - EXPECT_EQ(3, tracker.instances()); - EXPECT_EQ(2, tracker.live_instances()); - tracker.ResetCopiesMovesSwaps(); - - CopyableMovableInstance copy_assign(1); - copy_assign = copy; - CopyableMovableInstance move_assign(1); - move_assign = std::move(move); - EXPECT_EQ(1, tracker.copies()); - EXPECT_EQ(1, tracker.moves()); - EXPECT_EQ(0, tracker.swaps()); - EXPECT_EQ(5, tracker.instances()); - EXPECT_EQ(3, tracker.live_instances()); - tracker.ResetCopiesMovesSwaps(); - - { - using std::swap; - swap(move_assign, copy); - swap(copy, move_assign); - EXPECT_EQ(2, tracker.swaps()); - EXPECT_EQ(0, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - EXPECT_EQ(5, tracker.instances()); - EXPECT_EQ(3, tracker.live_instances()); - } -} - -TEST(TestInstanceTracker, CopyableOnly) { - InstanceTracker tracker; - CopyableOnlyInstance src(1); - EXPECT_EQ(1, src.value()) << src; - CopyableOnlyInstance copy(src); - CopyableOnlyInstance copy2(std::move(src)); // NOLINT - EXPECT_EQ(2, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - EXPECT_EQ(3, tracker.instances()); - EXPECT_EQ(3, tracker.live_instances()); - tracker.ResetCopiesMovesSwaps(); - - CopyableOnlyInstance copy_assign(1); - copy_assign = copy; - CopyableOnlyInstance copy_assign2(1); - copy_assign2 = std::move(copy2); // NOLINT - EXPECT_EQ(2, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - EXPECT_EQ(5, tracker.instances()); - EXPECT_EQ(5, tracker.live_instances()); - tracker.ResetCopiesMovesSwaps(); - - { - using std::swap; - swap(src, copy); - swap(copy, src); - EXPECT_EQ(2, tracker.swaps()); - EXPECT_EQ(0, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - EXPECT_EQ(5, tracker.instances()); - EXPECT_EQ(5, tracker.live_instances()); - } -} - -TEST(TestInstanceTracker, MovableOnly) { - InstanceTracker tracker; - MovableOnlyInstance src(1); - EXPECT_EQ(1, src.value()) << src; - MovableOnlyInstance move(std::move(src)); - MovableOnlyInstance move_assign(2); - move_assign = std::move(move); - EXPECT_EQ(3, tracker.instances()); - EXPECT_EQ(1, tracker.live_instances()); - EXPECT_EQ(2, tracker.moves()); - EXPECT_EQ(0, tracker.copies()); - tracker.ResetCopiesMovesSwaps(); - - { - using std::swap; - MovableOnlyInstance other(2); - swap(move_assign, other); - swap(other, move_assign); - EXPECT_EQ(2, tracker.swaps()); - EXPECT_EQ(0, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - EXPECT_EQ(4, tracker.instances()); - EXPECT_EQ(2, tracker.live_instances()); - } -} - -TEST(TestInstanceTracker, ExistingInstances) { - CopyableMovableInstance uncounted_instance(1); - CopyableMovableInstance uncounted_live_instance( - std::move(uncounted_instance)); - InstanceTracker tracker; - EXPECT_EQ(0, tracker.instances()); - EXPECT_EQ(0, tracker.live_instances()); - EXPECT_EQ(0, tracker.copies()); - { - CopyableMovableInstance instance1(1); - EXPECT_EQ(1, tracker.instances()); - EXPECT_EQ(1, tracker.live_instances()); - EXPECT_EQ(0, tracker.copies()); - EXPECT_EQ(0, tracker.moves()); - { - InstanceTracker tracker2; - CopyableMovableInstance instance2(instance1); - CopyableMovableInstance instance3(std::move(instance2)); - EXPECT_EQ(3, tracker.instances()); - EXPECT_EQ(2, tracker.live_instances()); - EXPECT_EQ(1, tracker.copies()); - EXPECT_EQ(1, tracker.moves()); - EXPECT_EQ(2, tracker2.instances()); - EXPECT_EQ(1, tracker2.live_instances()); - EXPECT_EQ(1, tracker2.copies()); - EXPECT_EQ(1, tracker2.moves()); - } - EXPECT_EQ(1, tracker.instances()); - EXPECT_EQ(1, tracker.live_instances()); - EXPECT_EQ(1, tracker.copies()); - EXPECT_EQ(1, tracker.moves()); - } - EXPECT_EQ(0, tracker.instances()); - EXPECT_EQ(0, tracker.live_instances()); - EXPECT_EQ(1, tracker.copies()); - EXPECT_EQ(1, tracker.moves()); -} - -TEST(TestInstanceTracker, Comparisons) { - InstanceTracker tracker; - MovableOnlyInstance one(1), two(2); - - EXPECT_EQ(0, tracker.comparisons()); - EXPECT_FALSE(one == two); - EXPECT_EQ(1, tracker.comparisons()); - EXPECT_TRUE(one != two); - EXPECT_EQ(2, tracker.comparisons()); - EXPECT_TRUE(one < two); - EXPECT_EQ(3, tracker.comparisons()); - EXPECT_FALSE(one > two); - EXPECT_EQ(4, tracker.comparisons()); - EXPECT_TRUE(one <= two); - EXPECT_EQ(5, tracker.comparisons()); - EXPECT_FALSE(one >= two); - EXPECT_EQ(6, tracker.comparisons()); - EXPECT_TRUE(one.compare(two) < 0); // NOLINT - EXPECT_EQ(7, tracker.comparisons()); - - tracker.ResetCopiesMovesSwaps(); - EXPECT_EQ(0, tracker.comparisons()); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/container/internal/tracked.h b/third_party/abseil_cpp/absl/container/internal/tracked.h deleted file mode 100644 index 29f5829f7199..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/tracked.h +++ /dev/null @@ -1,83 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_TRACKED_H_ -#define ABSL_CONTAINER_INTERNAL_TRACKED_H_ - -#include <stddef.h> - -#include <memory> -#include <utility> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// A class that tracks its copies and moves so that it can be queried in tests. -template <class T> -class Tracked { - public: - Tracked() {} - // NOLINTNEXTLINE(runtime/explicit) - Tracked(const T& val) : val_(val) {} - Tracked(const Tracked& that) - : val_(that.val_), - num_moves_(that.num_moves_), - num_copies_(that.num_copies_) { - ++(*num_copies_); - } - Tracked(Tracked&& that) - : val_(std::move(that.val_)), - num_moves_(std::move(that.num_moves_)), - num_copies_(std::move(that.num_copies_)) { - ++(*num_moves_); - } - Tracked& operator=(const Tracked& that) { - val_ = that.val_; - num_moves_ = that.num_moves_; - num_copies_ = that.num_copies_; - ++(*num_copies_); - } - Tracked& operator=(Tracked&& that) { - val_ = std::move(that.val_); - num_moves_ = std::move(that.num_moves_); - num_copies_ = std::move(that.num_copies_); - ++(*num_moves_); - } - - const T& val() const { return val_; } - - friend bool operator==(const Tracked& a, const Tracked& b) { - return a.val_ == b.val_; - } - friend bool operator!=(const Tracked& a, const Tracked& b) { - return !(a == b); - } - - size_t num_copies() { return *num_copies_; } - size_t num_moves() { return *num_moves_; } - - private: - T val_; - std::shared_ptr<size_t> num_moves_ = std::make_shared<size_t>(0); - std::shared_ptr<size_t> num_copies_ = std::make_shared<size_t>(0); -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_TRACKED_H_ diff --git a/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 deleted file mode 100644 index 76ee95e6abc5..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_map_constructor_test.h +++ /dev/null @@ -1,489 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_ - -#include <algorithm> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordMap> -class ConstructorTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ConstructorTest); - -TYPED_TEST_P(ConstructorTest, NoArgs) { - TypeParam m; - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); -} - -TYPED_TEST_P(ConstructorTest, BucketCount) { - TypeParam m(123); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHash) { - using H = typename TypeParam::hasher; - H hasher; - TypeParam m(123, hasher); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashEqual) { - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - H hasher; - E equal; - TypeParam m(123, hasher, equal); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) { - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -template <typename T> -struct is_std_unordered_map : std::false_type {}; - -template <typename... T> -struct is_std_unordered_map<std::unordered_map<T...>> : std::true_type {}; - -#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17) -using has_cxx14_std_apis = std::true_type; -#else -using has_cxx14_std_apis = std::false_type; -#endif - -template <typename T> -using expect_cxx14_apis = - absl::disjunction<absl::negation<is_std_unordered_map<T>>, - has_cxx14_std_apis>; - -template <typename TypeParam> -void BucketCountAllocTest(std::false_type) {} - -template <typename TypeParam> -void BucketCountAllocTest(std::true_type) { - using A = typename TypeParam::allocator_type; - A alloc(0); - TypeParam m(123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountAlloc) { - BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void BucketCountHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void BucketCountHashAllocTest(std::true_type) { - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - TypeParam m(123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) { - BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS -using has_alloc_std_constructors = std::true_type; -#else -using has_alloc_std_constructors = std::false_type; -#endif - -template <typename T> -using expect_alloc_constructors = - absl::disjunction<absl::negation<is_std_unordered_map<T>>, - has_alloc_std_constructors>; - -template <typename TypeParam> -void AllocTest(std::false_type) {} - -template <typename TypeParam> -void AllocTest(std::true_type) { - using A = typename TypeParam::allocator_type; - A alloc(0); - TypeParam m(alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(m, ::testing::UnorderedElementsAre()); -} - -TYPED_TEST_P(ConstructorTest, Alloc) { - AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -template <typename TypeParam> -void InputIteratorBucketAllocTest(std::false_type) {} - -template <typename TypeParam> -void InputIteratorBucketAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using A = typename TypeParam::allocator_type; - A alloc(0); - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end(), 123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) { - InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void InputIteratorBucketHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void InputIteratorBucketHashAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end(), 123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) { - InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, CopyConstructor) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam n(m); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -template <typename TypeParam> -void CopyConstructorAllocTest(std::false_type) {} - -template <typename TypeParam> -void CopyConstructorAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam n(m, A(11)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_NE(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) { - CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -// TODO(alkis): Test non-propagating allocators on copy constructors. - -TYPED_TEST_P(ConstructorTest, MoveConstructor) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam t(m); - TypeParam n(std::move(t)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -template <typename TypeParam> -void MoveConstructorAllocTest(std::false_type) {} - -template <typename TypeParam> -void MoveConstructorAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam t(m); - TypeParam n(std::move(t), A(1)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_NE(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) { - MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -// TODO(alkis): Test non-propagating allocators on move constructors. - -TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(values, 123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -template <typename TypeParam> -void InitializerListBucketAllocTest(std::false_type) {} - -template <typename TypeParam> -void InitializerListBucketAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using A = typename TypeParam::allocator_type; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - A alloc(0); - TypeParam m(values, 123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) { - InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void InitializerListBucketHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void InitializerListBucketHashAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m(values, 123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) { - InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, Assignment) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc); - TypeParam n; - n = m; - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m, n); -} - -// TODO(alkis): Test [non-]propagating allocators on move/copy assignments -// (it depends on traits). - -TYPED_TEST_P(ConstructorTest, MoveAssignment) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc); - TypeParam t(m); - TypeParam n; - n = std::move(t); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m; - m = values; - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}); - TypeParam n({gen()}); - n = m; - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}); - TypeParam t(m); - TypeParam n({gen()}); - n = std::move(t); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m; - m = values; - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m(values); - m = *&m; // Avoid -Wself-assign - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); -} - -// We cannot test self move as standard states that it leaves standard -// containers in unspecified state (and in practice in causes memory-leak -// according to heap-checker!). - -REGISTER_TYPED_TEST_CASE_P( - ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual, - BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc, - InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc, - InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc, - MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc, - InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment, - MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting, - MoveAssignmentOverwritesExisting, - AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_map_lookup_test.h b/third_party/abseil_cpp/absl/container/internal/unordered_map_lookup_test.h deleted file mode 100644 index e76421e508fe..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_map_lookup_test.h +++ /dev/null @@ -1,117 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_ - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordMap> -class LookupTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(LookupTest); - -TYPED_TEST_P(LookupTest, At) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - for (const auto& p : values) { - const auto& val = m.at(p.first); - EXPECT_EQ(p.second, val) << ::testing::PrintToString(p.first); - } -} - -TYPED_TEST_P(LookupTest, OperatorBracket) { - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& p : values) { - auto& val = m[p.first]; - EXPECT_EQ(V(), val) << ::testing::PrintToString(p.first); - val = p.second; - } - for (const auto& p : values) - EXPECT_EQ(p.second, m[p.first]) << ::testing::PrintToString(p.first); -} - -TYPED_TEST_P(LookupTest, Count) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& p : values) - EXPECT_EQ(0, m.count(p.first)) << ::testing::PrintToString(p.first); - m.insert(values.begin(), values.end()); - for (const auto& p : values) - EXPECT_EQ(1, m.count(p.first)) << ::testing::PrintToString(p.first); -} - -TYPED_TEST_P(LookupTest, Find) { - using std::get; - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& p : values) - EXPECT_TRUE(m.end() == m.find(p.first)) - << ::testing::PrintToString(p.first); - m.insert(values.begin(), values.end()); - for (const auto& p : values) { - auto it = m.find(p.first); - EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(p.first); - EXPECT_EQ(p.second, get<1>(*it)) << ::testing::PrintToString(p.first); - } -} - -TYPED_TEST_P(LookupTest, EqualRange) { - using std::get; - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& p : values) { - auto r = m.equal_range(p.first); - ASSERT_EQ(0, std::distance(r.first, r.second)); - } - m.insert(values.begin(), values.end()); - for (const auto& p : values) { - auto r = m.equal_range(p.first); - ASSERT_EQ(1, std::distance(r.first, r.second)); - EXPECT_EQ(p.second, get<1>(*r.first)) << ::testing::PrintToString(p.first); - } -} - -REGISTER_TYPED_TEST_CASE_P(LookupTest, At, OperatorBracket, Count, Find, - EqualRange); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_map_members_test.h b/third_party/abseil_cpp/absl/container/internal/unordered_map_members_test.h deleted file mode 100644 index 7d48cdb890bb..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_map_members_test.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_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_ - -#include <type_traits> -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordMap> -class MembersTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(MembersTest); - -template <typename T> -void UseType() {} - -TYPED_TEST_P(MembersTest, Typedefs) { - EXPECT_TRUE((std::is_same<std::pair<const typename TypeParam::key_type, - typename TypeParam::mapped_type>, - typename TypeParam::value_type>())); - EXPECT_TRUE((absl::conjunction< - absl::negation<std::is_signed<typename TypeParam::size_type>>, - std::is_integral<typename TypeParam::size_type>>())); - EXPECT_TRUE((absl::conjunction< - std::is_signed<typename TypeParam::difference_type>, - std::is_integral<typename TypeParam::difference_type>>())); - EXPECT_TRUE((std::is_convertible< - decltype(std::declval<const typename TypeParam::hasher&>()( - std::declval<const typename TypeParam::key_type&>())), - size_t>())); - EXPECT_TRUE((std::is_convertible< - decltype(std::declval<const typename TypeParam::key_equal&>()( - std::declval<const typename TypeParam::key_type&>(), - std::declval<const typename TypeParam::key_type&>())), - bool>())); - EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type, - typename TypeParam::value_type>())); - EXPECT_TRUE((std::is_same<typename TypeParam::value_type&, - typename TypeParam::reference>())); - EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&, - typename TypeParam::const_reference>())); - EXPECT_TRUE((std::is_same<typename std::allocator_traits< - typename TypeParam::allocator_type>::pointer, - typename TypeParam::pointer>())); - EXPECT_TRUE( - (std::is_same<typename std::allocator_traits< - typename TypeParam::allocator_type>::const_pointer, - typename TypeParam::const_pointer>())); -} - -TYPED_TEST_P(MembersTest, SimpleFunctions) { - EXPECT_GT(TypeParam().max_size(), 0); -} - -TYPED_TEST_P(MembersTest, BeginEnd) { - TypeParam t = {typename TypeParam::value_type{}}; - EXPECT_EQ(t.begin(), t.cbegin()); - EXPECT_EQ(t.end(), t.cend()); - EXPECT_NE(t.begin(), t.end()); - EXPECT_NE(t.cbegin(), t.cend()); -} - -REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_ diff --git a/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 deleted file mode 100644 index 8c9ca779a424..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_map_modifiers_test.h +++ /dev/null @@ -1,318 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_ - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordMap> -class ModifiersTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ModifiersTest); - -TYPED_TEST_P(ModifiersTest, Clear) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - m.clear(); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAre()); - EXPECT_TRUE(m.empty()); -} - -TYPED_TEST_P(ModifiersTest, Insert) { - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - auto p = m.insert(val); - EXPECT_TRUE(p.second); - EXPECT_EQ(val, *p.first); - T val2 = {val.first, hash_internal::Generator<V>()()}; - p = m.insert(val2); - EXPECT_FALSE(p.second); - EXPECT_EQ(val, *p.first); -} - -TYPED_TEST_P(ModifiersTest, InsertHint) { - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - auto it = m.insert(m.end(), val); - EXPECT_TRUE(it != m.end()); - EXPECT_EQ(val, *it); - T val2 = {val.first, hash_internal::Generator<V>()()}; - it = m.insert(it, val2); - EXPECT_TRUE(it != m.end()); - EXPECT_EQ(val, *it); -} - -TYPED_TEST_P(ModifiersTest, InsertRange) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - m.insert(values.begin(), values.end()); - ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ModifiersTest, InsertOrAssign) { -#ifdef UNORDERED_MAP_CXX17 - using std::get; - using K = typename TypeParam::key_type; - using V = typename TypeParam::mapped_type; - K k = hash_internal::Generator<K>()(); - V val = hash_internal::Generator<V>()(); - TypeParam m; - auto p = m.insert_or_assign(k, val); - EXPECT_TRUE(p.second); - EXPECT_EQ(k, get<0>(*p.first)); - EXPECT_EQ(val, get<1>(*p.first)); - V val2 = hash_internal::Generator<V>()(); - p = m.insert_or_assign(k, val2); - EXPECT_FALSE(p.second); - EXPECT_EQ(k, get<0>(*p.first)); - EXPECT_EQ(val2, get<1>(*p.first)); -#endif -} - -TYPED_TEST_P(ModifiersTest, InsertOrAssignHint) { -#ifdef UNORDERED_MAP_CXX17 - using std::get; - using K = typename TypeParam::key_type; - using V = typename TypeParam::mapped_type; - K k = hash_internal::Generator<K>()(); - V val = hash_internal::Generator<V>()(); - TypeParam m; - auto it = m.insert_or_assign(m.end(), k, val); - EXPECT_TRUE(it != m.end()); - EXPECT_EQ(k, get<0>(*it)); - EXPECT_EQ(val, get<1>(*it)); - V val2 = hash_internal::Generator<V>()(); - it = m.insert_or_assign(it, k, val2); - EXPECT_EQ(k, get<0>(*it)); - EXPECT_EQ(val2, get<1>(*it)); -#endif -} - -TYPED_TEST_P(ModifiersTest, Emplace) { - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto p = m.emplace(val); - EXPECT_TRUE(p.second); - EXPECT_EQ(val, *p.first); - T val2 = {val.first, hash_internal::Generator<V>()()}; - p = m.emplace(val2); - EXPECT_FALSE(p.second); - EXPECT_EQ(val, *p.first); -} - -TYPED_TEST_P(ModifiersTest, EmplaceHint) { - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto it = m.emplace_hint(m.end(), val); - EXPECT_EQ(val, *it); - T val2 = {val.first, hash_internal::Generator<V>()()}; - it = m.emplace_hint(it, val2); - EXPECT_EQ(val, *it); -} - -TYPED_TEST_P(ModifiersTest, TryEmplace) { -#ifdef UNORDERED_MAP_CXX17 - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto p = m.try_emplace(val.first, val.second); - EXPECT_TRUE(p.second); - EXPECT_EQ(val, *p.first); - T val2 = {val.first, hash_internal::Generator<V>()()}; - p = m.try_emplace(val2.first, val2.second); - EXPECT_FALSE(p.second); - EXPECT_EQ(val, *p.first); -#endif -} - -TYPED_TEST_P(ModifiersTest, TryEmplaceHint) { -#ifdef UNORDERED_MAP_CXX17 - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto it = m.try_emplace(m.end(), val.first, val.second); - EXPECT_EQ(val, *it); - T val2 = {val.first, hash_internal::Generator<V>()()}; - it = m.try_emplace(it, val2.first, val2.second); - EXPECT_EQ(val, *it); -#endif -} - -template <class V> -using IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type; - -// In openmap we chose not to return the iterator from erase because that's -// more expensive. As such we adapt erase to return an iterator here. -struct EraseFirst { - template <class Map> - auto operator()(Map* m, int) const - -> IfNotVoid<decltype(m->erase(m->begin()))> { - return m->erase(m->begin()); - } - template <class Map> - typename Map::iterator operator()(Map* m, ...) const { - auto it = m->begin(); - m->erase(it++); - return it; - } -}; - -TYPED_TEST_P(ModifiersTest, Erase) { - using T = hash_internal::GeneratedType<TypeParam>; - using std::get; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - auto& first = *m.begin(); - std::vector<T> values2; - for (const auto& val : values) - if (get<0>(val) != get<0>(first)) values2.push_back(val); - auto it = EraseFirst()(&m, 0); - ASSERT_TRUE(it != m.end()); - EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it)); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values2.begin(), - values2.end())); -} - -TYPED_TEST_P(ModifiersTest, EraseRange) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - auto it = m.erase(m.begin(), m.end()); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAre()); - EXPECT_TRUE(it == m.end()); -} - -TYPED_TEST_P(ModifiersTest, EraseKey) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_EQ(1, m.erase(values[0].first)); - EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0])); - EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values.begin() + 1, - values.end())); -} - -TYPED_TEST_P(ModifiersTest, Swap) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> v1; - std::vector<T> v2; - std::generate_n(std::back_inserter(v1), 5, hash_internal::Generator<T>()); - std::generate_n(std::back_inserter(v2), 5, hash_internal::Generator<T>()); - TypeParam m1(v1.begin(), v1.end()); - TypeParam m2(v2.begin(), v2.end()); - EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v1)); - EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v2)); - m1.swap(m2); - EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v2)); - EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v1)); -} - -// TODO(alkis): Write tests for extract. -// TODO(alkis): Write tests for merge. - -REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint, - InsertRange, InsertOrAssign, InsertOrAssignHint, - Emplace, EmplaceHint, TryEmplace, TryEmplaceHint, - Erase, EraseRange, EraseKey, Swap); - -template <typename Type> -struct is_unique_ptr : std::false_type {}; - -template <typename Type> -struct is_unique_ptr<std::unique_ptr<Type>> : std::true_type {}; - -template <class UnordMap> -class UniquePtrModifiersTest : public ::testing::Test { - protected: - UniquePtrModifiersTest() { - static_assert(is_unique_ptr<typename UnordMap::mapped_type>::value, - "UniquePtrModifiersTyest may only be called with a " - "std::unique_ptr value type."); - } -}; - -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniquePtrModifiersTest); - -TYPED_TEST_SUITE_P(UniquePtrModifiersTest); - -// Test that we do not move from rvalue arguments if an insertion does not -// happen. -TYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) { -#ifdef UNORDERED_MAP_CXX17 - using T = hash_internal::GeneratedType<TypeParam>; - using V = typename TypeParam::mapped_type; - T val = hash_internal::Generator<T>()(); - TypeParam m; - auto p = m.try_emplace(val.first, std::move(val.second)); - EXPECT_TRUE(p.second); - // A moved from std::unique_ptr is guaranteed to be nullptr. - EXPECT_EQ(val.second, nullptr); - T val2 = {val.first, hash_internal::Generator<V>()()}; - p = m.try_emplace(val2.first, std::move(val2.second)); - EXPECT_FALSE(p.second); - EXPECT_NE(val2.second, nullptr); -#endif -} - -REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_map_test.cc b/third_party/abseil_cpp/absl/container/internal/unordered_map_test.cc deleted file mode 100644 index 9cbf512f32b2..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_map_test.cc +++ /dev/null @@ -1,50 +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 <memory> -#include <unordered_map> - -#include "absl/container/internal/unordered_map_constructor_test.h" -#include "absl/container/internal/unordered_map_lookup_test.h" -#include "absl/container/internal/unordered_map_members_test.h" -#include "absl/container/internal/unordered_map_modifiers_test.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using MapTypes = ::testing::Types< - std::unordered_map<int, int, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::pair<const int, int>>>, - std::unordered_map<std::string, std::string, StatefulTestingHash, - StatefulTestingEqual, - Alloc<std::pair<const std::string, std::string>>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes); - -using UniquePtrMapTypes = ::testing::Types<std::unordered_map< - int, std::unique_ptr<int>, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::pair<const int, std::unique_ptr<int>>>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, UniquePtrModifiersTest, - UniquePtrMapTypes); - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_set_constructor_test.h b/third_party/abseil_cpp/absl/container/internal/unordered_set_constructor_test.h deleted file mode 100644 index 41165b05e97b..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_set_constructor_test.h +++ /dev/null @@ -1,496 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_ - -#include <algorithm> -#include <unordered_set> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordMap> -class ConstructorTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ConstructorTest); - -TYPED_TEST_P(ConstructorTest, NoArgs) { - TypeParam m; - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); -} - -TYPED_TEST_P(ConstructorTest, BucketCount) { - TypeParam m(123); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHash) { - using H = typename TypeParam::hasher; - H hasher; - TypeParam m(123, hasher); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashEqual) { - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - H hasher; - E equal; - TypeParam m(123, hasher, equal); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) { - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); - - const auto& cm = m; - EXPECT_EQ(cm.hash_function(), hasher); - EXPECT_EQ(cm.key_eq(), equal); - EXPECT_EQ(cm.get_allocator(), alloc); - EXPECT_TRUE(cm.empty()); - EXPECT_THAT(keys(cm), ::testing::UnorderedElementsAre()); - EXPECT_GE(cm.bucket_count(), 123); -} - -template <typename T> -struct is_std_unordered_set : std::false_type {}; - -template <typename... T> -struct is_std_unordered_set<std::unordered_set<T...>> : std::true_type {}; - -#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17) -using has_cxx14_std_apis = std::true_type; -#else -using has_cxx14_std_apis = std::false_type; -#endif - -template <typename T> -using expect_cxx14_apis = - absl::disjunction<absl::negation<is_std_unordered_set<T>>, - has_cxx14_std_apis>; - -template <typename TypeParam> -void BucketCountAllocTest(std::false_type) {} - -template <typename TypeParam> -void BucketCountAllocTest(std::true_type) { - using A = typename TypeParam::allocator_type; - A alloc(0); - TypeParam m(123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountAlloc) { - BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void BucketCountHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void BucketCountHashAllocTest(std::true_type) { - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - TypeParam m(123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) { - BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS -using has_alloc_std_constructors = std::true_type; -#else -using has_alloc_std_constructors = std::false_type; -#endif - -template <typename T> -using expect_alloc_constructors = - absl::disjunction<absl::negation<is_std_unordered_set<T>>, - has_alloc_std_constructors>; - -template <typename TypeParam> -void AllocTest(std::false_type) {} - -template <typename TypeParam> -void AllocTest(std::true_type) { - using A = typename TypeParam::allocator_type; - A alloc(0); - TypeParam m(alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_TRUE(m.empty()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); -} - -TYPED_TEST_P(ConstructorTest, Alloc) { - AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - std::vector<T> values; - for (size_t i = 0; i != 10; ++i) - values.push_back(hash_internal::Generator<T>()()); - TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -template <typename TypeParam> -void InputIteratorBucketAllocTest(std::false_type) {} - -template <typename TypeParam> -void InputIteratorBucketAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using A = typename TypeParam::allocator_type; - A alloc(0); - std::vector<T> values; - for (size_t i = 0; i != 10; ++i) - values.push_back(hash_internal::Generator<T>()()); - TypeParam m(values.begin(), values.end(), 123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) { - InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void InputIteratorBucketHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void InputIteratorBucketHashAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - std::vector<T> values; - for (size_t i = 0; i != 10; ++i) - values.push_back(hash_internal::Generator<T>()()); - TypeParam m(values.begin(), values.end(), 123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) { - InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, CopyConstructor) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam n(m); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); - EXPECT_NE(TypeParam(0, hasher, equal, alloc), n); -} - -template <typename TypeParam> -void CopyConstructorAllocTest(std::false_type) {} - -template <typename TypeParam> -void CopyConstructorAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam n(m, A(11)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_NE(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) { - CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -// TODO(alkis): Test non-propagating allocators on copy constructors. - -TYPED_TEST_P(ConstructorTest, MoveConstructor) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam t(m); - TypeParam n(std::move(t)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -template <typename TypeParam> -void MoveConstructorAllocTest(std::false_type) {} - -template <typename TypeParam> -void MoveConstructorAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(123, hasher, equal, alloc); - for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()()); - TypeParam t(m); - TypeParam n(std::move(t), A(1)); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_NE(m.get_allocator(), n.get_allocator()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) { - MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>()); -} - -// TODO(alkis): Test non-propagating allocators on move constructors. - -TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - TypeParam m(values, 123, hasher, equal, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.key_eq(), equal); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -template <typename TypeParam> -void InitializerListBucketAllocTest(std::false_type) {} - -template <typename TypeParam> -void InitializerListBucketAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using A = typename TypeParam::allocator_type; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - A alloc(0); - TypeParam m(values, 123, alloc); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) { - InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -template <typename TypeParam> -void InitializerListBucketHashAllocTest(std::false_type) {} - -template <typename TypeParam> -void InitializerListBucketHashAllocTest(std::true_type) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using A = typename TypeParam::allocator_type; - H hasher; - A alloc(0); - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m(values, 123, hasher, alloc); - EXPECT_EQ(m.hash_function(), hasher); - EXPECT_EQ(m.get_allocator(), alloc); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_GE(m.bucket_count(), 123); -} - -TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) { - InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>()); -} - -TYPED_TEST_P(ConstructorTest, CopyAssignment) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc); - TypeParam n; - n = m; - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m, n); -} - -// TODO(alkis): Test [non-]propagating allocators on move/copy assignments -// (it depends on traits). - -TYPED_TEST_P(ConstructorTest, MoveAssignment) { - using T = hash_internal::GeneratedType<TypeParam>; - using H = typename TypeParam::hasher; - using E = typename TypeParam::key_equal; - using A = typename TypeParam::allocator_type; - H hasher; - E equal; - A alloc(0); - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc); - TypeParam t(m); - TypeParam n; - n = std::move(t); - EXPECT_EQ(m.hash_function(), n.hash_function()); - EXPECT_EQ(m.key_eq(), n.key_eq()); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m; - m = values; - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}); - TypeParam n({gen()}); - n = m; - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - TypeParam m({gen(), gen(), gen()}); - TypeParam t(m); - TypeParam n({gen()}); - n = std::move(t); - EXPECT_EQ(m, n); -} - -TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m; - m = values; - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) { - using T = hash_internal::GeneratedType<TypeParam>; - hash_internal::Generator<T> gen; - std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()}; - TypeParam m(values); - m = *&m; // Avoid -Wself-assign. - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); -} - -REGISTER_TYPED_TEST_CASE_P( - ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual, - BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc, - InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc, - InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc, - MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc, - InitializerListBucketAlloc, InitializerListBucketHashAlloc, CopyAssignment, - MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting, - MoveAssignmentOverwritesExisting, - AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_set_lookup_test.h b/third_party/abseil_cpp/absl/container/internal/unordered_set_lookup_test.h deleted file mode 100644 index 8f2f4b207ef0..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_set_lookup_test.h +++ /dev/null @@ -1,91 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_ - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordSet> -class LookupTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(LookupTest); - -TYPED_TEST_P(LookupTest, Count) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& v : values) - EXPECT_EQ(0, m.count(v)) << ::testing::PrintToString(v); - m.insert(values.begin(), values.end()); - for (const auto& v : values) - EXPECT_EQ(1, m.count(v)) << ::testing::PrintToString(v); -} - -TYPED_TEST_P(LookupTest, Find) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& v : values) - EXPECT_TRUE(m.end() == m.find(v)) << ::testing::PrintToString(v); - m.insert(values.begin(), values.end()); - for (const auto& v : values) { - typename TypeParam::iterator it = m.find(v); - static_assert(std::is_same<const typename TypeParam::value_type&, - decltype(*it)>::value, - ""); - static_assert(std::is_same<const typename TypeParam::value_type*, - decltype(it.operator->())>::value, - ""); - EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(v); - EXPECT_EQ(v, *it) << ::testing::PrintToString(v); - } -} - -TYPED_TEST_P(LookupTest, EqualRange) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - for (const auto& v : values) { - auto r = m.equal_range(v); - ASSERT_EQ(0, std::distance(r.first, r.second)); - } - m.insert(values.begin(), values.end()); - for (const auto& v : values) { - auto r = m.equal_range(v); - ASSERT_EQ(1, std::distance(r.first, r.second)); - EXPECT_EQ(v, *r.first); - } -} - -REGISTER_TYPED_TEST_CASE_P(LookupTest, Count, Find, EqualRange); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_set_members_test.h b/third_party/abseil_cpp/absl/container/internal/unordered_set_members_test.h deleted file mode 100644 index 4c5e104af292..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_set_members_test.h +++ /dev/null @@ -1,86 +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_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_ - -#include <type_traits> -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordSet> -class MembersTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(MembersTest); - -template <typename T> -void UseType() {} - -TYPED_TEST_P(MembersTest, Typedefs) { - EXPECT_TRUE((std::is_same<typename TypeParam::key_type, - typename TypeParam::value_type>())); - EXPECT_TRUE((absl::conjunction< - absl::negation<std::is_signed<typename TypeParam::size_type>>, - std::is_integral<typename TypeParam::size_type>>())); - EXPECT_TRUE((absl::conjunction< - std::is_signed<typename TypeParam::difference_type>, - std::is_integral<typename TypeParam::difference_type>>())); - EXPECT_TRUE((std::is_convertible< - decltype(std::declval<const typename TypeParam::hasher&>()( - std::declval<const typename TypeParam::key_type&>())), - size_t>())); - EXPECT_TRUE((std::is_convertible< - decltype(std::declval<const typename TypeParam::key_equal&>()( - std::declval<const typename TypeParam::key_type&>(), - std::declval<const typename TypeParam::key_type&>())), - bool>())); - EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type, - typename TypeParam::value_type>())); - EXPECT_TRUE((std::is_same<typename TypeParam::value_type&, - typename TypeParam::reference>())); - EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&, - typename TypeParam::const_reference>())); - EXPECT_TRUE((std::is_same<typename std::allocator_traits< - typename TypeParam::allocator_type>::pointer, - typename TypeParam::pointer>())); - EXPECT_TRUE( - (std::is_same<typename std::allocator_traits< - typename TypeParam::allocator_type>::const_pointer, - typename TypeParam::const_pointer>())); -} - -TYPED_TEST_P(MembersTest, SimpleFunctions) { - EXPECT_GT(TypeParam().max_size(), 0); -} - -TYPED_TEST_P(MembersTest, BeginEnd) { - TypeParam t = {typename TypeParam::value_type{}}; - EXPECT_EQ(t.begin(), t.cbegin()); - EXPECT_EQ(t.end(), t.cend()); - EXPECT_NE(t.begin(), t.end()); - EXPECT_NE(t.cbegin(), t.cend()); -} - -REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_ diff --git a/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 deleted file mode 100644 index 26be58d99f21..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_set_modifiers_test.h +++ /dev/null @@ -1,190 +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. - -#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_ -#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_ - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/hash_generator_testing.h" -#include "absl/container/internal/hash_policy_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -template <class UnordSet> -class ModifiersTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ModifiersTest); - -TYPED_TEST_P(ModifiersTest, Clear) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - m.clear(); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_TRUE(m.empty()); -} - -TYPED_TEST_P(ModifiersTest, Insert) { - using T = hash_internal::GeneratedType<TypeParam>; - T val = hash_internal::Generator<T>()(); - TypeParam m; - auto p = m.insert(val); - EXPECT_TRUE(p.second); - EXPECT_EQ(val, *p.first); - p = m.insert(val); - EXPECT_FALSE(p.second); -} - -TYPED_TEST_P(ModifiersTest, InsertHint) { - using T = hash_internal::GeneratedType<TypeParam>; - T val = hash_internal::Generator<T>()(); - TypeParam m; - auto it = m.insert(m.end(), val); - EXPECT_TRUE(it != m.end()); - EXPECT_EQ(val, *it); - it = m.insert(it, val); - EXPECT_TRUE(it != m.end()); - EXPECT_EQ(val, *it); -} - -TYPED_TEST_P(ModifiersTest, InsertRange) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m; - m.insert(values.begin(), values.end()); - ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); -} - -TYPED_TEST_P(ModifiersTest, Emplace) { - using T = hash_internal::GeneratedType<TypeParam>; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto p = m.emplace(val); - EXPECT_TRUE(p.second); - EXPECT_EQ(val, *p.first); - p = m.emplace(val); - EXPECT_FALSE(p.second); - EXPECT_EQ(val, *p.first); -} - -TYPED_TEST_P(ModifiersTest, EmplaceHint) { - using T = hash_internal::GeneratedType<TypeParam>; - T val = hash_internal::Generator<T>()(); - TypeParam m; - // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps - // with test traits/policy. - auto it = m.emplace_hint(m.end(), val); - EXPECT_EQ(val, *it); - it = m.emplace_hint(it, val); - EXPECT_EQ(val, *it); -} - -template <class V> -using IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type; - -// In openmap we chose not to return the iterator from erase because that's -// more expensive. As such we adapt erase to return an iterator here. -struct EraseFirst { - template <class Map> - auto operator()(Map* m, int) const - -> IfNotVoid<decltype(m->erase(m->begin()))> { - return m->erase(m->begin()); - } - template <class Map> - typename Map::iterator operator()(Map* m, ...) const { - auto it = m->begin(); - m->erase(it++); - return it; - } -}; - -TYPED_TEST_P(ModifiersTest, Erase) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - std::vector<T> values2; - for (const auto& val : values) - if (val != *m.begin()) values2.push_back(val); - auto it = EraseFirst()(&m, 0); - ASSERT_TRUE(it != m.end()); - EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it)); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values2.begin(), - values2.end())); -} - -TYPED_TEST_P(ModifiersTest, EraseRange) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - auto it = m.erase(m.begin(), m.end()); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre()); - EXPECT_TRUE(it == m.end()); -} - -TYPED_TEST_P(ModifiersTest, EraseKey) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> values; - std::generate_n(std::back_inserter(values), 10, - hash_internal::Generator<T>()); - TypeParam m(values.begin(), values.end()); - ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values)); - EXPECT_EQ(1, m.erase(values[0])); - EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0])); - EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values.begin() + 1, - values.end())); -} - -TYPED_TEST_P(ModifiersTest, Swap) { - using T = hash_internal::GeneratedType<TypeParam>; - std::vector<T> v1; - std::vector<T> v2; - std::generate_n(std::back_inserter(v1), 5, hash_internal::Generator<T>()); - std::generate_n(std::back_inserter(v2), 5, hash_internal::Generator<T>()); - TypeParam m1(v1.begin(), v1.end()); - TypeParam m2(v2.begin(), v2.end()); - EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v1)); - EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v2)); - m1.swap(m2); - EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v2)); - EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v1)); -} - -// TODO(alkis): Write tests for extract. -// TODO(alkis): Write tests for merge. - -REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint, - InsertRange, Emplace, EmplaceHint, Erase, EraseRange, - EraseKey, Swap); - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_ diff --git a/third_party/abseil_cpp/absl/container/internal/unordered_set_test.cc b/third_party/abseil_cpp/absl/container/internal/unordered_set_test.cc deleted file mode 100644 index a134b53984bc..000000000000 --- a/third_party/abseil_cpp/absl/container/internal/unordered_set_test.cc +++ /dev/null @@ -1,41 +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 <unordered_set> - -#include "absl/container/internal/unordered_set_constructor_test.h" -#include "absl/container/internal/unordered_set_lookup_test.h" -#include "absl/container/internal/unordered_set_members_test.h" -#include "absl/container/internal/unordered_set_modifiers_test.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using SetTypes = ::testing::Types< - std::unordered_set<int, StatefulTestingHash, StatefulTestingEqual, - Alloc<int>>, - std::unordered_set<std::string, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::string>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, MembersTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes); - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/node_hash_map.h b/third_party/abseil_cpp/absl/container/node_hash_map.h deleted file mode 100644 index 7a39f6284cf5..000000000000 --- a/third_party/abseil_cpp/absl/container/node_hash_map.h +++ /dev/null @@ -1,597 +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: node_hash_map.h -// ----------------------------------------------------------------------------- -// -// An `absl::node_hash_map<K, V>` is an unordered associative container of -// unique keys and associated values designed to be a more efficient replacement -// for `std::unordered_map`. Like `unordered_map`, search, insertion, and -// deletion of map elements can be done as an `O(1)` operation. However, -// `node_hash_map` (and other unordered associative containers known as the -// collection of Abseil "Swiss tables") contain other optimizations that result -// in both memory and computation advantages. -// -// In most cases, your default choice for a hash map should be a map of type -// `flat_hash_map`. However, if you need pointer stability and cannot store -// a `flat_hash_map` with `unique_ptr` elements, a `node_hash_map` may be a -// valid alternative. As well, if you are migrating your code from using -// `std::unordered_map`, a `node_hash_map` provides a more straightforward -// migration, because it guarantees pointer stability. Consider migrating to -// `node_hash_map` and perhaps converting to a more efficient `flat_hash_map` -// upon further review. - -#ifndef ABSL_CONTAINER_NODE_HASH_MAP_H_ -#define ABSL_CONTAINER_NODE_HASH_MAP_H_ - -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/algorithm/container.h" -#include "absl/container/internal/container_memory.h" -#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export -#include "absl/container/internal/node_hash_policy.h" -#include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -template <class Key, class Value> -class NodeHashMapPolicy; -} // namespace container_internal - -// ----------------------------------------------------------------------------- -// absl::node_hash_map -// ----------------------------------------------------------------------------- -// -// An `absl::node_hash_map<K, V>` is an unordered associative container which -// has been optimized for both speed and memory footprint in most common use -// cases. Its interface is similar to that of `std::unordered_map<K, V>` with -// the following notable differences: -// -// * Supports heterogeneous lookup, through `find()`, `operator[]()` and -// `insert()`, provided that the map is provided a compatible heterogeneous -// hashing function and equality operator. -// * Contains a `capacity()` member function indicating the number of element -// slots (open, deleted, and empty) within the hash map. -// * Returns `void` from the `erase(iterator)` overload. -// -// By default, `node_hash_map` uses the `absl::Hash` hashing framework. -// All fundamental and Abseil types that support the `absl::Hash` framework have -// a compatible equality operator for comparing insertions into `node_hash_map`. -// If your type is not yet supported by the `absl::Hash` framework, see -// absl/hash/hash.h for information on extending Abseil hashing to user-defined -// types. -// -// Example: -// -// // Create a node hash map of three strings (that map to strings) -// absl::node_hash_map<std::string, std::string> ducks = -// {{"a", "huey"}, {"b", "dewey"}, {"c", "louie"}}; -// -// // Insert a new element into the node hash map -// ducks.insert({"d", "donald"}}; -// -// // Force a rehash of the node hash map -// ducks.rehash(0); -// -// // Find the element with the key "b" -// std::string search_key = "b"; -// auto result = ducks.find(search_key); -// if (result != ducks.end()) { -// std::cout << "Result: " << result->second << std::endl; -// } -template <class Key, class Value, - class Hash = absl::container_internal::hash_default_hash<Key>, - class Eq = absl::container_internal::hash_default_eq<Key>, - class Alloc = std::allocator<std::pair<const Key, Value>>> -class node_hash_map - : public absl::container_internal::raw_hash_map< - absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq, - Alloc> { - using Base = typename node_hash_map::raw_hash_map; - - public: - // Constructors and Assignment Operators - // - // A node_hash_map supports the same overload set as `std::unordered_map` - // for construction and assignment: - // - // * Default constructor - // - // // No allocation for the table's elements is made. - // absl::node_hash_map<int, std::string> map1; - // - // * Initializer List constructor - // - // absl::node_hash_map<int, std::string> map2 = - // {{1, "huey"}, {2, "dewey"}, {3, "louie"},}; - // - // * Copy constructor - // - // absl::node_hash_map<int, std::string> map3(map2); - // - // * Copy assignment operator - // - // // Hash functor and Comparator are copied as well - // absl::node_hash_map<int, std::string> map4; - // map4 = map3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::node_hash_map<int, std::string> map5(std::move(map4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::node_hash_map<int, std::string> map6; - // map6 = std::move(map5); - // - // * Range constructor - // - // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}}; - // absl::node_hash_map<int, std::string> map7(v.begin(), v.end()); - node_hash_map() {} - using Base::Base; - - // node_hash_map::begin() - // - // Returns an iterator to the beginning of the `node_hash_map`. - using Base::begin; - - // node_hash_map::cbegin() - // - // Returns a const iterator to the beginning of the `node_hash_map`. - using Base::cbegin; - - // node_hash_map::cend() - // - // Returns a const iterator to the end of the `node_hash_map`. - using Base::cend; - - // node_hash_map::end() - // - // Returns an iterator to the end of the `node_hash_map`. - using Base::end; - - // node_hash_map::capacity() - // - // Returns the number of element slots (assigned, deleted, and empty) - // available within the `node_hash_map`. - // - // NOTE: this member function is particular to `absl::node_hash_map` and is - // not provided in the `std::unordered_map` API. - using Base::capacity; - - // node_hash_map::empty() - // - // Returns whether or not the `node_hash_map` is empty. - using Base::empty; - - // node_hash_map::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `node_hash_map` under current memory constraints. This value can be thought - // of as the largest value of `std::distance(begin(), end())` for a - // `node_hash_map<K, V>`. - using Base::max_size; - - // node_hash_map::size() - // - // Returns the number of elements currently within the `node_hash_map`. - using Base::size; - - // node_hash_map::clear() - // - // Removes all elements from the `node_hash_map`. Invalidates any references, - // pointers, or iterators referring to contained elements. - // - // NOTE: this operation may shrink the underlying buffer. To avoid shrinking - // the underlying buffer call `erase(begin(), end())`. - using Base::clear; - - // node_hash_map::erase() - // - // Erases elements within the `node_hash_map`. Erasing does not trigger a - // rehash. Overloads are listed below. - // - // void erase(const_iterator pos): - // - // Erases the element at `position` of the `node_hash_map`, returning - // `void`. - // - // NOTE: this return behavior is different than that of STL containers in - // general and `std::unordered_map` in particular. - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning an - // iterator pointing to `last`. - // - // size_type erase(const key_type& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // node_hash_map::insert() - // - // Inserts an element of the specified value into the `node_hash_map`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If rehashing occurs - // due to the insertion, all iterators are invalidated. Overloads are listed - // below. - // - // std::pair<iterator,bool> insert(const init_type& value): - // - // Inserts a value into the `node_hash_map`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a `bool` denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(T&& value): - // std::pair<iterator,bool> insert(init_type&& value): - // - // Inserts a moveable value into the `node_hash_map`. Returns a `std::pair` - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a `bool` denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const init_type& value): - // iterator insert(const_iterator hint, T&& value): - // iterator insert(const_iterator hint, init_type&& value); - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently, for `node_hash_map` we guarantee the - // first match is inserted. - // - // void insert(std::initializer_list<init_type> ilist): - // - // Inserts the elements within the initializer list `ilist`. - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently within the initializer list, for - // `node_hash_map` we guarantee the first match is inserted. - using Base::insert; - - // node_hash_map::insert_or_assign() - // - // Inserts an element of the specified value into the `node_hash_map` provided - // that a value with the given key does not already exist, or replaces it with - // the element value if a key for that value already exists, returning an - // iterator pointing to the newly inserted element. If rehashing occurs due to - // the insertion, all iterators are invalidated. Overloads are listed - // below. - // - // std::pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj): - // std::pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `node_hash_map`. - // - // iterator insert_or_assign(const_iterator hint, - // const init_type& k, T&& obj): - // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj): - // - // Inserts/Assigns (or moves) the element of the specified key into the - // `node_hash_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - using Base::insert_or_assign; - - // node_hash_map::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `node_hash_map`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace; - - // node_hash_map::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `node_hash_map`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. Prefer `try_emplace()` unless your key is not - // copyable or moveable. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace_hint; - - // node_hash_map::try_emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `node_hash_map`, provided that no element with the given key - // already exists. Unlike `emplace()`, if an element with the given key - // already exists, we guarantee that no element is constructed. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - // Overloads are listed below. - // - // std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args): - // std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `node_hash_map`. - // - // iterator try_emplace(const_iterator hint, - // const init_type& k, Args&&... args): - // iterator try_emplace(const_iterator hint, init_type&& k, Args&&... args): - // - // Inserts (via copy or move) the element of the specified key into the - // `node_hash_map` using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. - // - // All `try_emplace()` overloads make the same guarantees regarding rvalue - // arguments as `std::unordered_map::try_emplace()`, namely that these - // functions will not move from rvalue arguments if insertions do not happen. - using Base::try_emplace; - - // node_hash_map::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the key,value pair of the element at the indicated position and - // returns a node handle owning that extracted data. - // - // node_type extract(const key_type& x): - // - // Extracts the key,value pair of the element with a key matching the passed - // key value and returns a node handle owning that extracted data. If the - // `node_hash_map` does not contain an element with a matching key, this - // function returns an empty node handle. - // - // NOTE: when compiled in an earlier version of C++ than C++17, - // `node_type::key()` returns a const reference to the key instead of a - // mutable reference. We cannot safely return a mutable reference without - // std::launder (which is not available before C++17). - using Base::extract; - - // node_hash_map::merge() - // - // Extracts elements from a given `source` node hash map into this - // `node_hash_map`. If the destination `node_hash_map` already contains an - // element with an equivalent key, that element is not extracted. - using Base::merge; - - // node_hash_map::swap(node_hash_map& other) - // - // Exchanges the contents of this `node_hash_map` with those of the `other` - // node hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `node_hash_map` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - // - // `swap()` requires that the node hash map's hashing and key equivalence - // functions be Swappable, and are exchaged using unqualified calls to - // non-member `swap()`. If the map's allocator has - // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value` - // set to `true`, the allocators are also exchanged using an unqualified call - // to non-member `swap()`; otherwise, the allocators are not swapped. - using Base::swap; - - // node_hash_map::rehash(count) - // - // Rehashes the `node_hash_map`, setting the number of slots to be at least - // the passed value. If the new number of slots increases the load factor more - // than the current maximum load factor - // (`count` < `size()` / `max_load_factor()`), then the new number of slots - // will be at least `size()` / `max_load_factor()`. - // - // To force a rehash, pass rehash(0). - using Base::rehash; - - // node_hash_map::reserve(count) - // - // Sets the number of slots in the `node_hash_map` to the number needed to - // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. - using Base::reserve; - - // node_hash_map::at() - // - // Returns a reference to the mapped value of the element with key equivalent - // to the passed key. - using Base::at; - - // node_hash_map::contains() - // - // Determines whether an element with a key comparing equal to the given `key` - // exists within the `node_hash_map`, returning `true` if so or `false` - // otherwise. - using Base::contains; - - // node_hash_map::count(const Key& key) const - // - // Returns the number of elements with a key comparing equal to the given - // `key` within the `node_hash_map`. note that this function will return - // either `1` or `0` since duplicate keys are not allowed within a - // `node_hash_map`. - using Base::count; - - // node_hash_map::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `node_hash_map`. - using Base::equal_range; - - // node_hash_map::find() - // - // Finds an element with the passed `key` within the `node_hash_map`. - using Base::find; - - // node_hash_map::operator[]() - // - // Returns a reference to the value mapped to the passed key within the - // `node_hash_map`, performing an `insert()` if the key does not already - // exist. If an insertion occurs and results in a rehashing of the container, - // all iterators are invalidated. Otherwise iterators are not affected and - // references are not invalidated. Overloads are listed below. - // - // T& operator[](const Key& key): - // - // Inserts an init_type object constructed in-place if the element with the - // given key does not exist. - // - // T& operator[](Key&& key): - // - // Inserts an init_type object constructed in-place provided that an element - // with the given key does not exist. - using Base::operator[]; - - // node_hash_map::bucket_count() - // - // Returns the number of "buckets" within the `node_hash_map`. - using Base::bucket_count; - - // node_hash_map::load_factor() - // - // Returns the current load factor of the `node_hash_map` (the average number - // of slots occupied with a value within the hash map). - using Base::load_factor; - - // node_hash_map::max_load_factor() - // - // Manages the maximum load factor of the `node_hash_map`. Overloads are - // listed below. - // - // float node_hash_map::max_load_factor() - // - // Returns the current maximum load factor of the `node_hash_map`. - // - // void node_hash_map::max_load_factor(float ml) - // - // Sets the maximum load factor of the `node_hash_map` to the passed value. - // - // NOTE: This overload is provided only for API compatibility with the STL; - // `node_hash_map` will ignore any set load factor and manage its rehashing - // internally as an implementation detail. - using Base::max_load_factor; - - // node_hash_map::get_allocator() - // - // Returns the allocator function associated with this `node_hash_map`. - using Base::get_allocator; - - // node_hash_map::hash_function() - // - // Returns the hashing function used to hash the keys within this - // `node_hash_map`. - using Base::hash_function; - - // node_hash_map::key_eq() - // - // Returns the function used for comparing keys equality. - using Base::key_eq; -}; - -// erase_if(node_hash_map<>, Pred) -// -// Erases all elements that satisfy the predicate `pred` from the container `c`. -template <typename K, typename V, typename H, typename E, typename A, - typename Predicate> -void erase_if(node_hash_map<K, V, H, E, A>& c, Predicate pred) { - container_internal::EraseIf(pred, &c); -} - -namespace container_internal { - -template <class Key, class Value> -class NodeHashMapPolicy - : public absl::container_internal::node_hash_policy< - std::pair<const Key, Value>&, NodeHashMapPolicy<Key, Value>> { - using value_type = std::pair<const Key, Value>; - - public: - using key_type = Key; - using mapped_type = Value; - using init_type = std::pair</*non const*/ key_type, mapped_type>; - - template <class Allocator, class... Args> - static value_type* new_element(Allocator* alloc, Args&&... args) { - using PairAlloc = typename absl::allocator_traits< - Allocator>::template rebind_alloc<value_type>; - PairAlloc pair_alloc(*alloc); - value_type* res = - absl::allocator_traits<PairAlloc>::allocate(pair_alloc, 1); - absl::allocator_traits<PairAlloc>::construct(pair_alloc, res, - std::forward<Args>(args)...); - return res; - } - - template <class Allocator> - static void delete_element(Allocator* alloc, value_type* pair) { - using PairAlloc = typename absl::allocator_traits< - Allocator>::template rebind_alloc<value_type>; - PairAlloc pair_alloc(*alloc); - absl::allocator_traits<PairAlloc>::destroy(pair_alloc, pair); - absl::allocator_traits<PairAlloc>::deallocate(pair_alloc, pair, 1); - } - - template <class F, class... Args> - static decltype(absl::container_internal::DecomposePair( - std::declval<F>(), std::declval<Args>()...)) - apply(F&& f, Args&&... args) { - return absl::container_internal::DecomposePair(std::forward<F>(f), - std::forward<Args>(args)...); - } - - static size_t element_space_used(const value_type*) { - return sizeof(value_type); - } - - static Value& value(value_type* elem) { return elem->second; } - static const Value& value(const value_type* elem) { return elem->second; } -}; -} // namespace container_internal - -namespace container_algorithm_internal { - -// Specialization of trait in absl/algorithm/container.h -template <class Key, class T, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer< - absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {}; - -} // namespace container_algorithm_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_NODE_HASH_MAP_H_ diff --git a/third_party/abseil_cpp/absl/container/node_hash_map_test.cc b/third_party/abseil_cpp/absl/container/node_hash_map_test.cc deleted file mode 100644 index 8f59a1e4a210..000000000000 --- a/third_party/abseil_cpp/absl/container/node_hash_map_test.cc +++ /dev/null @@ -1,275 +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/node_hash_map.h" - -#include "absl/container/internal/tracked.h" -#include "absl/container/internal/unordered_map_constructor_test.h" -#include "absl/container/internal/unordered_map_lookup_test.h" -#include "absl/container/internal/unordered_map_members_test.h" -#include "absl/container/internal/unordered_map_modifiers_test.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { - -using ::testing::Field; -using ::testing::IsEmpty; -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -using MapTypes = ::testing::Types< - absl::node_hash_map<int, int, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::pair<const int, int>>>, - absl::node_hash_map<std::string, std::string, StatefulTestingHash, - StatefulTestingEqual, - Alloc<std::pair<const std::string, std::string>>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, MembersTest, MapTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes); - -using M = absl::node_hash_map<std::string, Tracked<int>>; - -TEST(NodeHashMap, Emplace) { - M m; - Tracked<int> t(53); - m.emplace("a", t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(1, t.num_copies()); - - m.emplace(std::string("a"), t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(1, t.num_copies()); - - std::string a("a"); - m.emplace(a, t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(1, t.num_copies()); - - const std::string ca("a"); - m.emplace(a, t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(1, t.num_copies()); - - m.emplace(std::make_pair("a", t)); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(2, t.num_copies()); - - m.emplace(std::make_pair(std::string("a"), t)); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(3, t.num_copies()); - - std::pair<std::string, Tracked<int>> p("a", t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(4, t.num_copies()); - m.emplace(p); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(4, t.num_copies()); - - const std::pair<std::string, Tracked<int>> cp("a", t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(5, t.num_copies()); - m.emplace(cp); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(5, t.num_copies()); - - std::pair<const std::string, Tracked<int>> pc("a", t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(6, t.num_copies()); - m.emplace(pc); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(6, t.num_copies()); - - const std::pair<const std::string, Tracked<int>> cpc("a", t); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(7, t.num_copies()); - m.emplace(cpc); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(7, t.num_copies()); - - m.emplace(std::piecewise_construct, std::forward_as_tuple("a"), - std::forward_as_tuple(t)); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(7, t.num_copies()); - - m.emplace(std::piecewise_construct, std::forward_as_tuple(std::string("a")), - std::forward_as_tuple(t)); - ASSERT_EQ(0, t.num_moves()); - ASSERT_EQ(7, t.num_copies()); -} - -TEST(NodeHashMap, AssignRecursive) { - struct Tree { - // Verify that unordered_map<K, IncompleteType> can be instantiated. - absl::node_hash_map<int, Tree> children; - }; - Tree root; - const Tree& child = root.children.emplace().first->second; - // Verify that `lhs = rhs` doesn't read rhs after clearing lhs. - root = child; -} - -TEST(FlatHashMap, MoveOnlyKey) { - struct Key { - Key() = default; - Key(Key&&) = default; - Key& operator=(Key&&) = default; - }; - struct Eq { - bool operator()(const Key&, const Key&) const { return true; } - }; - struct Hash { - size_t operator()(const Key&) const { return 0; } - }; - absl::node_hash_map<Key, int, Hash, Eq> m; - m[Key()]; -} - -struct NonMovableKey { - explicit NonMovableKey(int i) : i(i) {} - NonMovableKey(NonMovableKey&&) = delete; - int i; -}; -struct NonMovableKeyHash { - using is_transparent = void; - size_t operator()(const NonMovableKey& k) const { return k.i; } - size_t operator()(int k) const { return k; } -}; -struct NonMovableKeyEq { - using is_transparent = void; - bool operator()(const NonMovableKey& a, const NonMovableKey& b) const { - return a.i == b.i; - } - bool operator()(const NonMovableKey& a, int b) const { return a.i == b; } -}; - -TEST(NodeHashMap, MergeExtractInsert) { - absl::node_hash_map<NonMovableKey, int, NonMovableKeyHash, NonMovableKeyEq> - set1, set2; - set1.emplace(std::piecewise_construct, std::make_tuple(7), - std::make_tuple(-7)); - set1.emplace(std::piecewise_construct, std::make_tuple(17), - std::make_tuple(-17)); - - set2.emplace(std::piecewise_construct, std::make_tuple(7), - std::make_tuple(-70)); - set2.emplace(std::piecewise_construct, std::make_tuple(19), - std::make_tuple(-190)); - - auto Elem = [](int key, int value) { - return Pair(Field(&NonMovableKey::i, key), value); - }; - - EXPECT_THAT(set1, UnorderedElementsAre(Elem(7, -7), Elem(17, -17))); - EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(19, -190))); - - // NonMovableKey is neither copyable nor movable. We should still be able to - // move nodes around. - static_assert(!std::is_move_constructible<NonMovableKey>::value, ""); - set1.merge(set2); - - EXPECT_THAT(set1, - UnorderedElementsAre(Elem(7, -7), Elem(17, -17), Elem(19, -190))); - EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70))); - - auto node = set1.extract(7); - EXPECT_TRUE(node); - EXPECT_EQ(node.key().i, 7); - EXPECT_EQ(node.mapped(), -7); - EXPECT_THAT(set1, UnorderedElementsAre(Elem(17, -17), Elem(19, -190))); - - auto insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_FALSE(insert_result.inserted); - EXPECT_TRUE(insert_result.node); - EXPECT_EQ(insert_result.node.key().i, 7); - EXPECT_EQ(insert_result.node.mapped(), -7); - EXPECT_THAT(*insert_result.position, Elem(7, -70)); - EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70))); - - node = set1.extract(17); - EXPECT_TRUE(node); - EXPECT_EQ(node.key().i, 17); - EXPECT_EQ(node.mapped(), -17); - EXPECT_THAT(set1, UnorderedElementsAre(Elem(19, -190))); - - node.mapped() = 23; - - insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_TRUE(insert_result.inserted); - EXPECT_FALSE(insert_result.node); - EXPECT_THAT(*insert_result.position, Elem(17, 23)); - EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23))); -} - -bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; } - -TEST(NodeHashMap, EraseIf) { - // Erase all elements. - { - node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, [](std::pair<const int, int>) { return true; }); - EXPECT_THAT(s, IsEmpty()); - } - // Erase no elements. - { - node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, [](std::pair<const int, int>) { return false; }); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), - Pair(4, 4), Pair(5, 5))); - } - // Erase specific elements. - { - node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, - [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; }); - EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); - } - // Predicate is function reference. - { - node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, FirstIsEven); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); - } - // Predicate is function pointer. - { - node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - erase_if(s, &FirstIsEven); - EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); - } -} - -// This test requires std::launder for mutable key access in node handles. -#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 -TEST(NodeHashMap, NodeHandleMutableKeyAccess) { - node_hash_map<std::string, std::string> map; - - map["key1"] = "mapped"; - - auto nh = map.extract(map.begin()); - nh.key().resize(3); - map.insert(std::move(nh)); - - EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped"))); -} -#endif - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/container/node_hash_set.h b/third_party/abseil_cpp/absl/container/node_hash_set.h deleted file mode 100644 index 56ce3b66c0be..000000000000 --- a/third_party/abseil_cpp/absl/container/node_hash_set.h +++ /dev/null @@ -1,493 +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: node_hash_set.h -// ----------------------------------------------------------------------------- -// -// An `absl::node_hash_set<T>` is an unordered associative container designed to -// be a more efficient replacement for `std::unordered_set`. Like -// `unordered_set`, search, insertion, and deletion of 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 -// advantages. -// -// In most cases, your default choice for a hash table should be a map of type -// `flat_hash_map` or a set of type `flat_hash_set`. However, if you need -// pointer stability, a `node_hash_set` should be your preferred choice. As -// well, if you are migrating your code from using `std::unordered_set`, a -// `node_hash_set` should be an easy migration. Consider migrating to -// `node_hash_set` and perhaps converting to a more efficient `flat_hash_set` -// upon further review. - -#ifndef ABSL_CONTAINER_NODE_HASH_SET_H_ -#define ABSL_CONTAINER_NODE_HASH_SET_H_ - -#include <type_traits> - -#include "absl/algorithm/container.h" -#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export -#include "absl/container/internal/node_hash_policy.h" -#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -template <typename T> -struct NodeHashSetPolicy; -} // namespace container_internal - -// ----------------------------------------------------------------------------- -// absl::node_hash_set -// ----------------------------------------------------------------------------- -// -// An `absl::node_hash_set<T>` is an unordered associative container which -// has been optimized for both speed and memory footprint in most common use -// cases. Its interface is similar to that of `std::unordered_set<T>` with the -// following notable differences: -// -// * Supports heterogeneous lookup, through `find()`, `operator[]()` and -// `insert()`, provided that the 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. -// * Returns `void` from the `erase(iterator)` overload. -// -// By default, `node_hash_set` uses the `absl::Hash` hashing framework. -// All fundamental and Abseil types that support the `absl::Hash` framework have -// a compatible equality operator for comparing insertions into `node_hash_set`. -// If your type is not yet supported by the `absl::Hash` framework, see -// absl/hash/hash.h for information on extending Abseil hashing to user-defined -// types. -// -// Example: -// -// // Create a node hash set of three strings -// absl::node_hash_map<std::string, std::string> ducks = -// {"huey", "dewey", "louie"}; -// -// // Insert a new element into the node hash map -// ducks.insert("donald"}; -// -// // Force a rehash of the node hash map -// ducks.rehash(0); -// -// // See if "dewey" is present -// if (ducks.contains("dewey")) { -// std::cout << "We found dewey!" << std::endl; -// } -template <class T, class Hash = absl::container_internal::hash_default_hash<T>, - class Eq = absl::container_internal::hash_default_eq<T>, - class Alloc = std::allocator<T>> -class node_hash_set - : public absl::container_internal::raw_hash_set< - absl::container_internal::NodeHashSetPolicy<T>, Hash, Eq, Alloc> { - using Base = typename node_hash_set::raw_hash_set; - - public: - // Constructors and Assignment Operators - // - // A node_hash_set supports the same overload set as `std::unordered_map` - // for construction and assignment: - // - // * Default constructor - // - // // No allocation for the table's elements is made. - // absl::node_hash_set<std::string> set1; - // - // * Initializer List constructor - // - // absl::node_hash_set<std::string> set2 = - // {{"huey"}, {"dewey"}, {"louie"}}; - // - // * Copy constructor - // - // absl::node_hash_set<std::string> set3(set2); - // - // * Copy assignment operator - // - // // Hash functor and Comparator are copied as well - // absl::node_hash_set<std::string> set4; - // set4 = set3; - // - // * Move constructor - // - // // Move is guaranteed efficient - // absl::node_hash_set<std::string> set5(std::move(set4)); - // - // * Move assignment operator - // - // // May be efficient if allocators are compatible - // absl::node_hash_set<std::string> set6; - // set6 = std::move(set5); - // - // * Range constructor - // - // std::vector<std::string> v = {"a", "b"}; - // absl::node_hash_set<std::string> set7(v.begin(), v.end()); - node_hash_set() {} - using Base::Base; - - // node_hash_set::begin() - // - // Returns an iterator to the beginning of the `node_hash_set`. - using Base::begin; - - // node_hash_set::cbegin() - // - // Returns a const iterator to the beginning of the `node_hash_set`. - using Base::cbegin; - - // node_hash_set::cend() - // - // Returns a const iterator to the end of the `node_hash_set`. - using Base::cend; - - // node_hash_set::end() - // - // Returns an iterator to the end of the `node_hash_set`. - using Base::end; - - // node_hash_set::capacity() - // - // Returns the number of element slots (assigned, deleted, and empty) - // available within the `node_hash_set`. - // - // NOTE: this member function is particular to `absl::node_hash_set` and is - // not provided in the `std::unordered_map` API. - using Base::capacity; - - // node_hash_set::empty() - // - // Returns whether or not the `node_hash_set` is empty. - using Base::empty; - - // node_hash_set::max_size() - // - // Returns the largest theoretical possible number of elements within a - // `node_hash_set` under current memory constraints. This value can be thought - // of the largest value of `std::distance(begin(), end())` for a - // `node_hash_set<T>`. - using Base::max_size; - - // node_hash_set::size() - // - // Returns the number of elements currently within the `node_hash_set`. - using Base::size; - - // node_hash_set::clear() - // - // Removes all elements from the `node_hash_set`. Invalidates any references, - // pointers, or iterators referring to contained elements. - // - // NOTE: this operation may shrink the underlying buffer. To avoid shrinking - // the underlying buffer call `erase(begin(), end())`. - using Base::clear; - - // node_hash_set::erase() - // - // Erases elements within the `node_hash_set`. Erasing does not trigger a - // rehash. Overloads are listed below. - // - // void erase(const_iterator pos): - // - // Erases the element at `position` of the `node_hash_set`, returning - // `void`. - // - // NOTE: this return behavior is different than that of STL containers in - // general and `std::unordered_map` in particular. - // - // iterator erase(const_iterator first, const_iterator last): - // - // Erases the elements in the open interval [`first`, `last`), returning an - // iterator pointing to `last`. - // - // size_type erase(const key_type& key): - // - // Erases the element with the matching key, if it exists, returning the - // number of elements erased (0 or 1). - using Base::erase; - - // node_hash_set::insert() - // - // Inserts an element of the specified value into the `node_hash_set`, - // returning an iterator pointing to the newly inserted element, provided that - // an element with the given key does not already exist. If rehashing occurs - // due to the insertion, all iterators are invalidated. Overloads are listed - // below. - // - // std::pair<iterator,bool> insert(const T& value): - // - // Inserts a value into the `node_hash_set`. Returns a pair consisting of an - // iterator to the inserted element (or to the element that prevented the - // insertion) and a bool denoting whether the insertion took place. - // - // std::pair<iterator,bool> insert(T&& value): - // - // Inserts a moveable value into the `node_hash_set`. Returns a pair - // consisting of an iterator to the inserted element (or to the element that - // prevented the insertion) and a bool denoting whether the insertion took - // place. - // - // iterator insert(const_iterator hint, const T& value): - // iterator insert(const_iterator hint, T&& value): - // - // Inserts a value, using the position of `hint` as a non-binding suggestion - // for where to begin the insertion search. Returns an iterator to the - // inserted element, or to the existing element that prevented the - // insertion. - // - // void insert(InputIterator first, InputIterator last): - // - // Inserts a range of values [`first`, `last`). - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently, for `node_hash_set` we guarantee the - // first match is inserted. - // - // void insert(std::initializer_list<T> ilist): - // - // Inserts the elements within the initializer list `ilist`. - // - // NOTE: Although the STL does not specify which element may be inserted if - // multiple keys compare equivalently within the initializer list, for - // `node_hash_set` we guarantee the first match is inserted. - using Base::insert; - - // node_hash_set::emplace() - // - // Inserts an element of the specified value by constructing it in-place - // within the `node_hash_set`, provided that no element with the given key - // already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace; - - // node_hash_set::emplace_hint() - // - // Inserts an element of the specified value by constructing it in-place - // within the `node_hash_set`, using the position of `hint` as a non-binding - // suggestion for where to begin the insertion search, and only inserts - // provided that no element with the given key already exists. - // - // The element may be constructed even if there already is an element with the - // key in the container, in which case the newly constructed element will be - // destroyed immediately. - // - // If rehashing occurs due to the insertion, all iterators are invalidated. - using Base::emplace_hint; - - // node_hash_set::extract() - // - // Extracts the indicated element, erasing it in the process, and returns it - // as a C++17-compatible node handle. Overloads are listed below. - // - // node_type extract(const_iterator position): - // - // Extracts the element at the indicated position and returns a node handle - // owning that extracted data. - // - // node_type extract(const key_type& x): - // - // Extracts the element with the key matching the passed key value and - // returns a node handle owning that extracted data. If the `node_hash_set` - // does not contain an element with a matching key, this function returns an - // empty node handle. - using Base::extract; - - // node_hash_set::merge() - // - // Extracts elements from a given `source` 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; - - // node_hash_set::swap(node_hash_set& other) - // - // Exchanges the contents of this `node_hash_set` with those of the `other` - // flat hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. - // - // All iterators and references on the `node_hash_set` remain valid, excepting - // for the past-the-end iterator, which is invalidated. - // - // `swap()` requires that the flat hash set's hashing and key equivalence - // functions be Swappable, and are exchaged using unqualified calls to - // non-member `swap()`. If the map's allocator has - // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value` - // set to `true`, the allocators are also exchanged using an unqualified call - // to non-member `swap()`; otherwise, the allocators are not swapped. - using Base::swap; - - // node_hash_set::rehash(count) - // - // Rehashes the `node_hash_set`, setting the number of slots to be at least - // the passed value. If the new number of slots increases the load factor more - // than the current maximum load factor - // (`count` < `size()` / `max_load_factor()`), then the new number of slots - // will be at least `size()` / `max_load_factor()`. - // - // To force a rehash, pass rehash(0). - // - // NOTE: unlike behavior in `std::unordered_set`, references are also - // invalidated upon a `rehash()`. - using Base::rehash; - - // node_hash_set::reserve(count) - // - // Sets the number of slots in the `node_hash_set` to the number needed to - // accommodate at least `count` total elements without exceeding the current - // maximum load factor, and may rehash the container if needed. - using Base::reserve; - - // node_hash_set::contains() - // - // Determines whether an element comparing equal to the given `key` exists - // within the `node_hash_set`, returning `true` if so or `false` otherwise. - using Base::contains; - - // node_hash_set::count(const Key& key) const - // - // Returns the number of elements comparing equal to the given `key` within - // the `node_hash_set`. note that this function will return either `1` or `0` - // since duplicate elements are not allowed within a `node_hash_set`. - using Base::count; - - // node_hash_set::equal_range() - // - // Returns a closed range [first, last], defined by a `std::pair` of two - // iterators, containing all elements with the passed key in the - // `node_hash_set`. - using Base::equal_range; - - // node_hash_set::find() - // - // Finds an element with the passed `key` within the `node_hash_set`. - using Base::find; - - // node_hash_set::bucket_count() - // - // Returns the number of "buckets" within the `node_hash_set`. Note that - // because a 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 map). - using Base::load_factor; - - // node_hash_set::max_load_factor() - // - // Manages the maximum load factor of the `node_hash_set`. Overloads are - // listed below. - // - // float node_hash_set::max_load_factor() - // - // Returns the current maximum load factor of the `node_hash_set`. - // - // void node_hash_set::max_load_factor(float ml) - // - // Sets the maximum load factor of the `node_hash_set` to the passed value. - // - // NOTE: This overload is provided only for API compatibility with the STL; - // `node_hash_set` will ignore any set load factor and manage its rehashing - // internally as an implementation detail. - using Base::max_load_factor; - - // node_hash_set::get_allocator() - // - // Returns the allocator function associated with this `node_hash_set`. - using Base::get_allocator; - - // node_hash_set::hash_function() - // - // Returns the hashing function used to hash the keys within this - // `node_hash_set`. - using Base::hash_function; - - // node_hash_set::key_eq() - // - // Returns the function used for comparing keys equality. - using Base::key_eq; -}; - -// erase_if(node_hash_set<>, Pred) -// -// Erases all elements that satisfy the predicate `pred` from the container `c`. -template <typename T, typename H, typename E, typename A, typename Predicate> -void erase_if(node_hash_set<T, H, E, A>& c, Predicate pred) { - container_internal::EraseIf(pred, &c); -} - -namespace container_internal { - -template <class T> -struct NodeHashSetPolicy - : absl::container_internal::node_hash_policy<T&, NodeHashSetPolicy<T>> { - using key_type = T; - using init_type = T; - using constant_iterators = std::true_type; - - template <class Allocator, class... Args> - static T* new_element(Allocator* alloc, Args&&... args) { - using ValueAlloc = - typename absl::allocator_traits<Allocator>::template rebind_alloc<T>; - ValueAlloc value_alloc(*alloc); - T* res = absl::allocator_traits<ValueAlloc>::allocate(value_alloc, 1); - absl::allocator_traits<ValueAlloc>::construct(value_alloc, res, - std::forward<Args>(args)...); - return res; - } - - template <class Allocator> - static void delete_element(Allocator* alloc, T* elem) { - using ValueAlloc = - typename absl::allocator_traits<Allocator>::template rebind_alloc<T>; - ValueAlloc value_alloc(*alloc); - absl::allocator_traits<ValueAlloc>::destroy(value_alloc, elem); - absl::allocator_traits<ValueAlloc>::deallocate(value_alloc, elem, 1); - } - - template <class F, class... Args> - static decltype(absl::container_internal::DecomposeValue( - std::declval<F>(), std::declval<Args>()...)) - apply(F&& f, Args&&... args) { - return absl::container_internal::DecomposeValue( - std::forward<F>(f), std::forward<Args>(args)...); - } - - static size_t element_space_used(const T*) { return sizeof(T); } -}; -} // namespace container_internal - -namespace container_algorithm_internal { - -// Specialization of trait in absl/algorithm/container.h -template <class Key, class Hash, class KeyEqual, class Allocator> -struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>> - : std::true_type {}; - -} // namespace container_algorithm_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_NODE_HASH_SET_H_ diff --git a/third_party/abseil_cpp/absl/container/node_hash_set_test.cc b/third_party/abseil_cpp/absl/container/node_hash_set_test.cc deleted file mode 100644 index 7ddad2021d2f..000000000000 --- a/third_party/abseil_cpp/absl/container/node_hash_set_test.cc +++ /dev/null @@ -1,143 +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/node_hash_set.h" - -#include "absl/container/internal/unordered_set_constructor_test.h" -#include "absl/container/internal/unordered_set_lookup_test.h" -#include "absl/container/internal/unordered_set_members_test.h" -#include "absl/container/internal/unordered_set_modifiers_test.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { -namespace { -using ::absl::container_internal::hash_internal::Enum; -using ::absl::container_internal::hash_internal::EnumClass; -using ::testing::IsEmpty; -using ::testing::Pointee; -using ::testing::UnorderedElementsAre; - -using SetTypes = ::testing::Types< - node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>, - node_hash_set<std::string, StatefulTestingHash, StatefulTestingEqual, - Alloc<std::string>>, - node_hash_set<Enum, StatefulTestingHash, StatefulTestingEqual, Alloc<Enum>>, - node_hash_set<EnumClass, StatefulTestingHash, StatefulTestingEqual, - Alloc<EnumClass>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, MembersTest, SetTypes); -INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes); - -TEST(NodeHashSet, MoveableNotCopyableCompiles) { - node_hash_set<std::unique_ptr<void*>> t; - node_hash_set<std::unique_ptr<void*>> u; - u = std::move(t); -} - -TEST(NodeHashSet, MergeExtractInsert) { - struct Hash { - size_t operator()(const std::unique_ptr<int>& p) const { return *p; } - }; - struct Eq { - bool operator()(const std::unique_ptr<int>& a, - const std::unique_ptr<int>& b) const { - return *a == *b; - } - }; - absl::node_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2; - set1.insert(absl::make_unique<int>(7)); - set1.insert(absl::make_unique<int>(17)); - - set2.insert(absl::make_unique<int>(7)); - set2.insert(absl::make_unique<int>(19)); - - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17))); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(19))); - - set1.merge(set2); - - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17), Pointee(19))); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7))); - - auto node = set1.extract(absl::make_unique<int>(7)); - EXPECT_TRUE(node); - EXPECT_THAT(node.value(), Pointee(7)); - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(17), Pointee(19))); - - auto insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_FALSE(insert_result.inserted); - EXPECT_TRUE(insert_result.node); - EXPECT_THAT(insert_result.node.value(), Pointee(7)); - EXPECT_EQ(**insert_result.position, 7); - EXPECT_NE(insert_result.position->get(), insert_result.node.value().get()); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7))); - - node = set1.extract(absl::make_unique<int>(17)); - EXPECT_TRUE(node); - EXPECT_THAT(node.value(), Pointee(17)); - EXPECT_THAT(set1, UnorderedElementsAre(Pointee(19))); - - node.value() = absl::make_unique<int>(23); - - insert_result = set2.insert(std::move(node)); - EXPECT_FALSE(node); - EXPECT_TRUE(insert_result.inserted); - EXPECT_FALSE(insert_result.node); - EXPECT_EQ(**insert_result.position, 23); - EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23))); -} - -bool IsEven(int k) { return k % 2 == 0; } - -TEST(NodeHashSet, EraseIf) { - // Erase all elements. - { - node_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int) { return true; }); - EXPECT_THAT(s, IsEmpty()); - } - // Erase no elements. - { - node_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int) { return false; }); - EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); - } - // Erase specific elements. - { - node_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, [](int k) { return k % 2 == 1; }); - EXPECT_THAT(s, UnorderedElementsAre(2, 4)); - } - // Predicate is function reference. - { - node_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, IsEven); - EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); - } - // Predicate is function pointer. - { - node_hash_set<int> s = {1, 2, 3, 4, 5}; - erase_if(s, &IsEven); - EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); - } -} - -} // namespace -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/copts/AbseilConfigureCopts.cmake b/third_party/abseil_cpp/absl/copts/AbseilConfigureCopts.cmake deleted file mode 100644 index acd46d04aa5a..000000000000 --- a/third_party/abseil_cpp/absl/copts/AbseilConfigureCopts.cmake +++ /dev/null @@ -1,67 +0,0 @@ -# See absl/copts/copts.py and absl/copts/generate_copts.py -include(GENERATED_AbseilCopts) - -set(ABSL_LSAN_LINKOPTS "") -set(ABSL_HAVE_LSAN OFF) -set(ABSL_DEFAULT_LINKOPTS "") - -if (BUILD_SHARED_LIBS AND MSVC) - set(ABSL_BUILD_DLL TRUE) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -else() - set(ABSL_BUILD_DLL FALSE) -endif() - -if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64|amd64|AMD64") - if (MSVC) - set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}") - else() - set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}") - endif() -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm.*|aarch64") - if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") - set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM64_FLAGS}") - elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") - set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM32_FLAGS}") - else() - message(WARNING "Value of CMAKE_SIZEOF_VOID_P (${CMAKE_SIZEOF_VOID_P}) is not supported.") - endif() -else() - message(WARNING "Value of CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) is unknown and cannot be used to set ABSL_RANDOM_RANDEN_COPTS") - set(ABSL_RANDOM_RANDEN_COPTS "") -endif() - - -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}") - set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}") -elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - # MATCHES so we get both Clang and AppleClang - if(MSVC) - # clang-cl is half MSVC, half LLVM - set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}") - set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}") - 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") - # AppleClang doesn't have lsan - # https://developer.apple.com/documentation/code_diagnostics - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) - set(ABSL_LSAN_LINKOPTS "-fsanitize=leak") - set(ABSL_HAVE_LSAN ON) - endif() - endif() - endif() -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(ABSL_DEFAULT_COPTS "${ABSL_MSVC_FLAGS}") - set(ABSL_TEST_COPTS "${ABSL_MSVC_FLAGS};${ABSL_MSVC_TEST_FLAGS}") - set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}") -else() - message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}. Building with no default flags") - set(ABSL_DEFAULT_COPTS "") - set(ABSL_TEST_COPTS "") -endif() - -set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}") diff --git a/third_party/abseil_cpp/absl/copts/GENERATED_AbseilCopts.cmake b/third_party/abseil_cpp/absl/copts/GENERATED_AbseilCopts.cmake deleted file mode 100644 index 51742c9b6b3a..000000000000 --- a/third_party/abseil_cpp/absl/copts/GENERATED_AbseilCopts.cmake +++ /dev/null @@ -1,162 +0,0 @@ -# GENERATED! DO NOT MANUALLY EDIT THIS FILE. -# -# (1) Edit absl/copts/copts.py. -# (2) Run `python <path_to_absl>/copts/generate_copts.py`. - -list(APPEND ABSL_CLANG_CL_FLAGS - "/W3" - "/DNOMINMAX" - "/DWIN32_LEAN_AND_MEAN" - "/D_CRT_SECURE_NO_WARNINGS" - "/D_SCL_SECURE_NO_WARNINGS" - "/D_ENABLE_EXTENDED_ALIGNED_STORAGE" -) - -list(APPEND ABSL_CLANG_CL_TEST_FLAGS - "-Wno-c99-extensions" - "-Wno-deprecated-declarations" - "-Wno-missing-noreturn" - "-Wno-missing-prototypes" - "-Wno-missing-variable-declarations" - "-Wno-null-conversion" - "-Wno-shadow" - "-Wno-shift-sign-overflow" - "-Wno-sign-compare" - "-Wno-unused-function" - "-Wno-unused-member-function" - "-Wno-unused-parameter" - "-Wno-unused-private-field" - "-Wno-unused-template" - "-Wno-used-but-marked-unused" - "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-zero-variadic-macro-arguments" -) - -list(APPEND ABSL_GCC_FLAGS - "-Wall" - "-Wextra" - "-Wcast-qual" - "-Wconversion-null" - "-Wformat-security" - "-Wmissing-declarations" - "-Woverlength-strings" - "-Wpointer-arith" - "-Wundef" - "-Wunused-local-typedefs" - "-Wunused-result" - "-Wvarargs" - "-Wvla" - "-Wwrite-strings" - "-DNOMINMAX" -) - -list(APPEND ABSL_GCC_TEST_FLAGS - "-Wno-conversion-null" - "-Wno-deprecated-declarations" - "-Wno-missing-declarations" - "-Wno-sign-compare" - "-Wno-unused-function" - "-Wno-unused-parameter" - "-Wno-unused-private-field" -) - -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" - "-Wliteral-conversion" - "-Wmissing-declarations" - "-Woverlength-strings" - "-Wpointer-arith" - "-Wself-assign" - "-Wshadow" - "-Wstring-conversion" - "-Wtautological-overlap-compare" - "-Wundef" - "-Wuninitialized" - "-Wunreachable-code" - "-Wunused-comparison" - "-Wunused-local-typedefs" - "-Wunused-result" - "-Wvla" - "-Wwrite-strings" - "-Wno-float-conversion" - "-Wno-implicit-float-conversion" - "-Wno-implicit-int-float-conversion" - "-Wno-implicit-int-conversion" - "-Wno-shorten-64-to-32" - "-Wno-sign-conversion" - "-DNOMINMAX" -) - -list(APPEND ABSL_LLVM_TEST_FLAGS - "-Wno-c99-extensions" - "-Wno-deprecated-declarations" - "-Wno-missing-noreturn" - "-Wno-missing-prototypes" - "-Wno-missing-variable-declarations" - "-Wno-null-conversion" - "-Wno-shadow" - "-Wno-shift-sign-overflow" - "-Wno-sign-compare" - "-Wno-unused-function" - "-Wno-unused-member-function" - "-Wno-unused-parameter" - "-Wno-unused-private-field" - "-Wno-unused-template" - "-Wno-used-but-marked-unused" - "-Wno-zero-as-null-pointer-constant" - "-Wno-gnu-zero-variadic-macro-arguments" -) - -list(APPEND ABSL_MSVC_FLAGS - "/W3" - "/DNOMINMAX" - "/DWIN32_LEAN_AND_MEAN" - "/D_CRT_SECURE_NO_WARNINGS" - "/D_SCL_SECURE_NO_WARNINGS" - "/D_ENABLE_EXTENDED_ALIGNED_STORAGE" - "/bigobj" - "/wd4005" - "/wd4068" - "/wd4180" - "/wd4244" - "/wd4267" - "/wd4503" - "/wd4800" -) - -list(APPEND ABSL_MSVC_LINKOPTS - "-ignore:4221" -) - -list(APPEND ABSL_MSVC_TEST_FLAGS - "/wd4018" - "/wd4101" - "/wd4503" - "/wd4996" - "/DNOMINMAX" -) - -list(APPEND ABSL_RANDOM_HWAES_ARM32_FLAGS - "-mfpu=neon" -) - -list(APPEND ABSL_RANDOM_HWAES_ARM64_FLAGS - "-march=armv8-a+crypto" -) - -list(APPEND ABSL_RANDOM_HWAES_MSVC_X64_FLAGS -) - -list(APPEND ABSL_RANDOM_HWAES_X64_FLAGS - "-maes" - "-msse4.1" -) diff --git a/third_party/abseil_cpp/absl/copts/GENERATED_copts.bzl b/third_party/abseil_cpp/absl/copts/GENERATED_copts.bzl deleted file mode 100644 index 6707488f23db..000000000000 --- a/third_party/abseil_cpp/absl/copts/GENERATED_copts.bzl +++ /dev/null @@ -1,163 +0,0 @@ -"""GENERATED! DO NOT MANUALLY EDIT THIS FILE. - -(1) Edit absl/copts/copts.py. -(2) Run `python <path_to_absl>/copts/generate_copts.py`. -""" - -ABSL_CLANG_CL_FLAGS = [ - "/W3", - "/DNOMINMAX", - "/DWIN32_LEAN_AND_MEAN", - "/D_CRT_SECURE_NO_WARNINGS", - "/D_SCL_SECURE_NO_WARNINGS", - "/D_ENABLE_EXTENDED_ALIGNED_STORAGE", -] - -ABSL_CLANG_CL_TEST_FLAGS = [ - "-Wno-c99-extensions", - "-Wno-deprecated-declarations", - "-Wno-missing-noreturn", - "-Wno-missing-prototypes", - "-Wno-missing-variable-declarations", - "-Wno-null-conversion", - "-Wno-shadow", - "-Wno-shift-sign-overflow", - "-Wno-sign-compare", - "-Wno-unused-function", - "-Wno-unused-member-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", - "-Wno-unused-template", - "-Wno-used-but-marked-unused", - "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-zero-variadic-macro-arguments", -] - -ABSL_GCC_FLAGS = [ - "-Wall", - "-Wextra", - "-Wcast-qual", - "-Wconversion-null", - "-Wformat-security", - "-Wmissing-declarations", - "-Woverlength-strings", - "-Wpointer-arith", - "-Wundef", - "-Wunused-local-typedefs", - "-Wunused-result", - "-Wvarargs", - "-Wvla", - "-Wwrite-strings", - "-DNOMINMAX", -] - -ABSL_GCC_TEST_FLAGS = [ - "-Wno-conversion-null", - "-Wno-deprecated-declarations", - "-Wno-missing-declarations", - "-Wno-sign-compare", - "-Wno-unused-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", -] - -ABSL_LLVM_FLAGS = [ - "-Wall", - "-Wextra", - "-Wcast-qual", - "-Wconversion", - "-Wfloat-overflow-conversion", - "-Wfloat-zero-conversion", - "-Wfor-loop-analysis", - "-Wformat-security", - "-Wgnu-redeclared-enum", - "-Winfinite-recursion", - "-Wliteral-conversion", - "-Wmissing-declarations", - "-Woverlength-strings", - "-Wpointer-arith", - "-Wself-assign", - "-Wshadow", - "-Wstring-conversion", - "-Wtautological-overlap-compare", - "-Wundef", - "-Wuninitialized", - "-Wunreachable-code", - "-Wunused-comparison", - "-Wunused-local-typedefs", - "-Wunused-result", - "-Wvla", - "-Wwrite-strings", - "-Wno-float-conversion", - "-Wno-implicit-float-conversion", - "-Wno-implicit-int-float-conversion", - "-Wno-implicit-int-conversion", - "-Wno-shorten-64-to-32", - "-Wno-sign-conversion", - "-DNOMINMAX", -] - -ABSL_LLVM_TEST_FLAGS = [ - "-Wno-c99-extensions", - "-Wno-deprecated-declarations", - "-Wno-missing-noreturn", - "-Wno-missing-prototypes", - "-Wno-missing-variable-declarations", - "-Wno-null-conversion", - "-Wno-shadow", - "-Wno-shift-sign-overflow", - "-Wno-sign-compare", - "-Wno-unused-function", - "-Wno-unused-member-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", - "-Wno-unused-template", - "-Wno-used-but-marked-unused", - "-Wno-zero-as-null-pointer-constant", - "-Wno-gnu-zero-variadic-macro-arguments", -] - -ABSL_MSVC_FLAGS = [ - "/W3", - "/DNOMINMAX", - "/DWIN32_LEAN_AND_MEAN", - "/D_CRT_SECURE_NO_WARNINGS", - "/D_SCL_SECURE_NO_WARNINGS", - "/D_ENABLE_EXTENDED_ALIGNED_STORAGE", - "/bigobj", - "/wd4005", - "/wd4068", - "/wd4180", - "/wd4244", - "/wd4267", - "/wd4503", - "/wd4800", -] - -ABSL_MSVC_LINKOPTS = [ - "-ignore:4221", -] - -ABSL_MSVC_TEST_FLAGS = [ - "/wd4018", - "/wd4101", - "/wd4503", - "/wd4996", - "/DNOMINMAX", -] - -ABSL_RANDOM_HWAES_ARM32_FLAGS = [ - "-mfpu=neon", -] - -ABSL_RANDOM_HWAES_ARM64_FLAGS = [ - "-march=armv8-a+crypto", -] - -ABSL_RANDOM_HWAES_MSVC_X64_FLAGS = [ -] - -ABSL_RANDOM_HWAES_X64_FLAGS = [ - "-maes", - "-msse4.1", -] diff --git a/third_party/abseil_cpp/absl/copts/configure_copts.bzl b/third_party/abseil_cpp/absl/copts/configure_copts.bzl deleted file mode 100644 index 4d3425444349..000000000000 --- a/third_party/abseil_cpp/absl/copts/configure_copts.bzl +++ /dev/null @@ -1,76 +0,0 @@ -"""absl specific copts. - -This file simply selects the correct options from the generated files. To -change Abseil copts, edit absl/copts/copts.py -""" - -load( - "//absl:copts/GENERATED_copts.bzl", - "ABSL_CLANG_CL_FLAGS", - "ABSL_CLANG_CL_TEST_FLAGS", - "ABSL_GCC_FLAGS", - "ABSL_GCC_TEST_FLAGS", - "ABSL_LLVM_FLAGS", - "ABSL_LLVM_TEST_FLAGS", - "ABSL_MSVC_FLAGS", - "ABSL_MSVC_LINKOPTS", - "ABSL_MSVC_TEST_FLAGS", - "ABSL_RANDOM_HWAES_ARM32_FLAGS", - "ABSL_RANDOM_HWAES_ARM64_FLAGS", - "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS", - "ABSL_RANDOM_HWAES_X64_FLAGS", -) - -ABSL_DEFAULT_COPTS = select({ - "//absl:windows": ABSL_MSVC_FLAGS, - "//absl:clang_compiler": ABSL_LLVM_FLAGS, - "//conditions:default": ABSL_GCC_FLAGS, -}) - -ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({ - "//absl:windows": ABSL_MSVC_TEST_FLAGS, - "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS, - "//conditions:default": ABSL_GCC_TEST_FLAGS, -}) - -ABSL_DEFAULT_LINKOPTS = select({ - "//absl:windows": ABSL_MSVC_LINKOPTS, - "//conditions:default": [], -}) - -# ABSL_RANDOM_RANDEN_COPTS blaze copts flags which are required by each -# environment to build an accelerated RandenHwAes library. -ABSL_RANDOM_RANDEN_COPTS = select({ - # APPLE - ":cpu_darwin_x86_64": ABSL_RANDOM_HWAES_X64_FLAGS, - ":cpu_darwin": ABSL_RANDOM_HWAES_X64_FLAGS, - ":cpu_x64_windows_msvc": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS, - ":cpu_x64_windows": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS, - ":cpu_k8": ABSL_RANDOM_HWAES_X64_FLAGS, - ":cpu_ppc": ["-mcrypto"], - - # Supported by default or unsupported. - "//conditions:default": [], -}) - -# absl_random_randen_copts_init: -# Initialize the config targets based on cpu, os, etc. used to select -# the required values for ABSL_RANDOM_RANDEN_COPTS -def absl_random_randen_copts_init(): - """Initialize the config_settings used by ABSL_RANDOM_RANDEN_COPTS.""" - - # CPU configs. - # These configs have consistent flags to enable HWAES intsructions. - cpu_configs = [ - "ppc", - "k8", - "darwin_x86_64", - "darwin", - "x64_windows_msvc", - "x64_windows", - ] - for cpu in cpu_configs: - native.config_setting( - name = "cpu_%s" % cpu, - values = {"cpu": cpu}, - ) diff --git a/third_party/abseil_cpp/absl/copts/copts.py b/third_party/abseil_cpp/absl/copts/copts.py deleted file mode 100644 index cf52981c58cc..000000000000 --- a/third_party/abseil_cpp/absl/copts/copts.py +++ /dev/null @@ -1,162 +0,0 @@ -"""Abseil compiler options. - -This is the source of truth for Abseil compiler options. To modify Abseil -compilation options: - - (1) Edit the appropriate list in this file based on the platform the flag is - needed on. - (2) Run `<path_to_absl>/copts/generate_copts.py`. - -The generated copts are consumed by configure_copts.bzl and -AbseilConfigureCopts.cmake. -""" - -# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ... -MSVC_BIG_WARNING_FLAGS = [ - "/W3", -] - -LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ - "-Wno-c99-extensions", - "-Wno-deprecated-declarations", - "-Wno-missing-noreturn", - "-Wno-missing-prototypes", - "-Wno-missing-variable-declarations", - "-Wno-null-conversion", - "-Wno-shadow", - "-Wno-shift-sign-overflow", - "-Wno-sign-compare", - "-Wno-unused-function", - "-Wno-unused-member-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", - "-Wno-unused-template", - "-Wno-used-but-marked-unused", - "-Wno-zero-as-null-pointer-constant", - # gtest depends on this GNU extension being offered. - "-Wno-gnu-zero-variadic-macro-arguments", -] - -MSVC_DEFINES = [ - "/DNOMINMAX", # Don't define min and max macros (windows.h) - # Don't bloat namespace with incompatible winsock versions. - "/DWIN32_LEAN_AND_MEAN", - # Don't warn about usage of insecure C functions. - "/D_CRT_SECURE_NO_WARNINGS", - "/D_SCL_SECURE_NO_WARNINGS", - # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage - "/D_ENABLE_EXTENDED_ALIGNED_STORAGE", -] - -COPT_VARS = { - "ABSL_GCC_FLAGS": [ - "-Wall", - "-Wextra", - "-Wcast-qual", - "-Wconversion-null", - "-Wformat-security", - "-Wmissing-declarations", - "-Woverlength-strings", - "-Wpointer-arith", - "-Wundef", - "-Wunused-local-typedefs", - "-Wunused-result", - "-Wvarargs", - "-Wvla", # variable-length array - "-Wwrite-strings", - # Don't define min and max macros (Build on Windows using gcc) - "-DNOMINMAX", - ], - "ABSL_GCC_TEST_FLAGS": [ - "-Wno-conversion-null", - "-Wno-deprecated-declarations", - "-Wno-missing-declarations", - "-Wno-sign-compare", - "-Wno-unused-function", - "-Wno-unused-parameter", - "-Wno-unused-private-field", - ], - "ABSL_LLVM_FLAGS": [ - "-Wall", - "-Wextra", - "-Wcast-qual", - "-Wconversion", - "-Wfloat-overflow-conversion", - "-Wfloat-zero-conversion", - "-Wfor-loop-analysis", - "-Wformat-security", - "-Wgnu-redeclared-enum", - "-Winfinite-recursion", - "-Wliteral-conversion", - "-Wmissing-declarations", - "-Woverlength-strings", - "-Wpointer-arith", - "-Wself-assign", - "-Wshadow", - "-Wstring-conversion", - "-Wtautological-overlap-compare", - "-Wundef", - "-Wuninitialized", - "-Wunreachable-code", - "-Wunused-comparison", - "-Wunused-local-typedefs", - "-Wunused-result", - "-Wvla", - "-Wwrite-strings", - # Warnings that are enabled by group warning flags like -Wall that we - # explicitly disable. - "-Wno-float-conversion", - "-Wno-implicit-float-conversion", - "-Wno-implicit-int-float-conversion", - "-Wno-implicit-int-conversion", - "-Wno-shorten-64-to-32", - "-Wno-sign-conversion", - # Don't define min and max macros (Build on Windows using clang) - "-DNOMINMAX", - ], - "ABSL_LLVM_TEST_FLAGS": - LLVM_TEST_DISABLE_WARNINGS_FLAGS, - "ABSL_CLANG_CL_FLAGS": - (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES), - "ABSL_CLANG_CL_TEST_FLAGS": - LLVM_TEST_DISABLE_WARNINGS_FLAGS, - "ABSL_MSVC_FLAGS": - MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + [ - # Increase the number of sections available in object files - "/bigobj", - "/wd4005", # macro-redefinition - "/wd4068", # unknown pragma - # qualifier applied to function type has no meaning; ignored - "/wd4180", - # conversion from 'type1' to 'type2', possible loss of data - "/wd4244", - # conversion from 'size_t' to 'type', possible loss of data - "/wd4267", - # The decorated name was longer than the compiler limit - "/wd4503", - # forcing value to bool 'true' or 'false' (performance warning) - "/wd4800", - ], - "ABSL_MSVC_TEST_FLAGS": [ - "/wd4018", # signed/unsigned mismatch - "/wd4101", # unreferenced local variable - "/wd4503", # decorated name length exceeded, name was truncated - "/wd4996", # use of deprecated symbol - "/DNOMINMAX", # disable the min() and max() macros from <windows.h> - ], - "ABSL_MSVC_LINKOPTS": [ - # Object file doesn't export any previously undefined symbols - "-ignore:4221", - ], - # "HWAES" is an abbreviation for "hardware AES" (AES - Advanced Encryption - # Standard). These flags are used for detecting whether or not the target - # architecture has hardware support for AES instructions which can be used - # to improve performance of some random bit generators. - "ABSL_RANDOM_HWAES_ARM64_FLAGS": ["-march=armv8-a+crypto"], - "ABSL_RANDOM_HWAES_ARM32_FLAGS": ["-mfpu=neon"], - "ABSL_RANDOM_HWAES_X64_FLAGS": [ - "-maes", - "-msse4.1", - ], - "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS": [], -} diff --git a/third_party/abseil_cpp/absl/copts/generate_copts.py b/third_party/abseil_cpp/absl/copts/generate_copts.py deleted file mode 100755 index 0e5dc9fad295..000000000000 --- a/third_party/abseil_cpp/absl/copts/generate_copts.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/python -"""Generate Abseil compile compile option configs. - -Usage: <path_to_absl>/copts/generate_copts.py - -The configs are generated from copts.py. -""" - -from os import path -import sys -from copts import COPT_VARS - - -# Helper functions -def file_header_lines(): - return [ - "GENERATED! DO NOT MANUALLY EDIT THIS FILE.", "", - "(1) Edit absl/copts/copts.py.", - "(2) Run `python <path_to_absl>/copts/generate_copts.py`." - ] - - -def flatten(*lists): - return [item for sublist in lists for item in sublist] - - -def relative_filename(filename): - return path.join(path.dirname(__file__), filename) - - -# Style classes. These contain all the syntactic styling needed to generate a -# copt file for different build tools. -class CMakeStyle(object): - """Style object for CMake copts file.""" - - def separator(self): - return "" - - def list_introducer(self, name): - return "list(APPEND " + name - - def list_closer(self): - return ")\n" - - def docstring(self): - return "\n".join((("# " + line).strip() for line in file_header_lines())) - - def filename(self): - return "GENERATED_AbseilCopts.cmake" - - -class StarlarkStyle(object): - """Style object for Starlark copts file.""" - - def separator(self): - return "," - - def list_introducer(self, name): - return name + " = [" - - def list_closer(self): - return "]\n" - - def docstring(self): - docstring_quotes = "\"\"\"" - return docstring_quotes + "\n".join( - flatten(file_header_lines(), [docstring_quotes])) - - def filename(self): - return "GENERATED_copts.bzl" - - -def copt_list(name, arg_list, style): - """Copt file generation.""" - - make_line = lambda s: " \"" + s + "\"" + style.separator() - external_str_list = [make_line(s) for s in arg_list] - - return "\n".join( - flatten( - [style.list_introducer(name)], - external_str_list, - [style.list_closer()])) - - -def generate_copt_file(style): - """Creates a generated copt file using the given style object. - - Args: - style: either StarlarkStyle() or CMakeStyle() - """ - with open(relative_filename(style.filename()), "w") as f: - f.write(style.docstring()) - f.write("\n") - for var_name, arg_list in sorted(COPT_VARS.items()): - f.write("\n") - f.write(copt_list(var_name, arg_list, style)) - - -def main(argv): - if len(argv) > 1: - raise RuntimeError("generate_copts needs no command line args") - - generate_copt_file(StarlarkStyle()) - generate_copt_file(CMakeStyle()) - - -if __name__ == "__main__": - main(sys.argv) diff --git a/third_party/abseil_cpp/absl/debugging/BUILD.bazel b/third_party/abseil_cpp/absl/debugging/BUILD.bazel deleted file mode 100644 index cd6e45439657..000000000000 --- a/third_party/abseil_cpp/absl/debugging/BUILD.bazel +++ /dev/null @@ -1,347 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) - -cc_library( - name = "stacktrace", - srcs = [ - "internal/stacktrace_aarch64-inl.inc", - "internal/stacktrace_arm-inl.inc", - "internal/stacktrace_config.h", - "internal/stacktrace_generic-inl.inc", - "internal/stacktrace_powerpc-inl.inc", - "internal/stacktrace_unimplemented-inl.inc", - "internal/stacktrace_win32-inl.inc", - "internal/stacktrace_x86-inl.inc", - "stacktrace.cc", - ], - hdrs = ["stacktrace.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":debugging_internal", - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -cc_library( - name = "symbolize", - srcs = [ - "symbolize.cc", - "symbolize_darwin.inc", - "symbolize_elf.inc", - "symbolize_unimplemented.inc", - "symbolize_win32.inc", - ], - hdrs = [ - "internal/symbolize.h", - "symbolize.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS + select({ - "//absl:windows": ["-DEFAULTLIB:dbghelp.lib"], - "//conditions:default": [], - }), - deps = [ - ":debugging_internal", - ":demangle_internal", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "//absl/base:malloc_internal", - "//absl/base:raw_logging_internal", - "//absl/strings", - ], -) - -cc_test( - name = "symbolize_test", - srcs = ["symbolize_test.cc"], - copts = ABSL_TEST_COPTS + select({ - "//absl:windows": ["/Z7"], - "//conditions:default": [], - }), - linkopts = ABSL_DEFAULT_LINKOPTS + select({ - "//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", - ], -) - -cc_library( - name = "examine_stack", - srcs = [ - "internal/examine_stack.cc", - ], - hdrs = [ - "internal/examine_stack.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - ":stacktrace", - ":symbolize", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "failure_signal_handler", - srcs = ["failure_signal_handler.cc"], - hdrs = ["failure_signal_handler.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":examine_stack", - ":stacktrace", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:errno_saver", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "failure_signal_handler_test", - srcs = ["failure_signal_handler_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = select({ - "//absl:windows": [], - "//absl:wasm": [], - "//conditions:default": ["-pthread"], - }) + ABSL_DEFAULT_LINKOPTS, - deps = [ - ":failure_signal_handler", - ":stacktrace", - ":symbolize", - "//absl/base:raw_logging_internal", - "//absl/strings", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "debugging_internal", - srcs = [ - "internal/address_is_readable.cc", - "internal/elf_mem_image.cc", - "internal/vdso_support.cc", - ], - hdrs = [ - "internal/address_is_readable.h", - "internal/elf_mem_image.h", - "internal/vdso_support.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "//absl/base:errno_saver", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "demangle_internal", - srcs = ["internal/demangle.cc"], - hdrs = ["internal/demangle.h"], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -cc_test( - name = "demangle_test", - srcs = ["internal/demangle_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":demangle_internal", - ":stack_consumption", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "leak_check", - srcs = ["leak_check.cc"], - hdrs = ["leak_check.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -# Adding a dependency to leak_check_disable will disable -# sanitizer leak checking (asan/lsan) in a test without -# the need to mess around with build features. -cc_library( - name = "leak_check_disable", - srcs = ["leak_check_disable.cc"], - linkopts = ABSL_DEFAULT_LINKOPTS, - linkstatic = 1, - deps = ["//absl/base:config"], - alwayslink = 1, -) - -# These targets exists for use in tests only, explicitly configuring the -# LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan. -ABSL_LSAN_LINKOPTS = select({ - "//absl:clang_compiler": ["-fsanitize=leak"], - "//conditions:default": [], -}) - -cc_library( - name = "leak_check_api_enabled_for_testing", - testonly = 1, - srcs = ["leak_check.cc"], - hdrs = ["leak_check.h"], - copts = select({ - "//absl:clang_compiler": ["-DLEAK_SANITIZER"], - "//conditions:default": [], - }), - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:config", - ], -) - -cc_library( - name = "leak_check_api_disabled_for_testing", - testonly = 1, - srcs = ["leak_check.cc"], - hdrs = ["leak_check.h"], - copts = ["-ULEAK_SANITIZER"], - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:config", - ], -) - -cc_test( - name = "leak_check_test", - srcs = ["leak_check_test.cc"], - copts = select({ - "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"], - "//conditions:default": [], - }), - linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS, - tags = ["notsan"], - deps = [ - ":leak_check_api_enabled_for_testing", - "//absl/base", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "leak_check_no_lsan_test", - srcs = ["leak_check_test.cc"], - copts = ["-UABSL_EXPECT_LEAK_SANITIZER"], - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["noasan"], - deps = [ - ":leak_check_api_disabled_for_testing", - "//absl/base", # for raw_logging - "@com_google_googletest//:gtest_main", - ], -) - -# Test that leak checking is skipped when lsan is enabled but -# ":leak_check_disable" is linked in. -# -# This test should fail in the absence of a dependency on ":leak_check_disable" -cc_test( - name = "disabled_leak_check_test", - srcs = ["leak_check_fail_test.cc"], - linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS, - tags = ["notsan"], - deps = [ - ":leak_check_api_enabled_for_testing", - ":leak_check_disable", - "//absl/base", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "stack_consumption", - testonly = 1, - srcs = ["internal/stack_consumption.cc"], - hdrs = ["internal/stack_consumption.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "stack_consumption_test", - srcs = ["internal/stack_consumption_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":stack_consumption", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/debugging/CMakeLists.txt b/third_party/abseil_cpp/absl/debugging/CMakeLists.txt deleted file mode 100644 index 074b44cf1781..000000000000 --- a/third_party/abseil_cpp/absl/debugging/CMakeLists.txt +++ /dev/null @@ -1,338 +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. -# - -absl_cc_library( - NAME - stacktrace - HDRS - "stacktrace.h" - "internal/stacktrace_aarch64-inl.inc" - "internal/stacktrace_arm-inl.inc" - "internal/stacktrace_config.h" - "internal/stacktrace_generic-inl.inc" - "internal/stacktrace_powerpc-inl.inc" - "internal/stacktrace_unimplemented-inl.inc" - "internal/stacktrace_win32-inl.inc" - "internal/stacktrace_x86-inl.inc" - SRCS - "stacktrace.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::debugging_internal - absl::config - absl::core_headers - PUBLIC -) - -absl_cc_library( - NAME - symbolize - HDRS - "symbolize.h" - "internal/symbolize.h" - SRCS - "symbolize.cc" - "symbolize_darwin.inc" - "symbolize_elf.inc" - "symbolize_unimplemented.inc" - "symbolize_win32.inc" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - $<$<BOOL:${MINGW}>:"dbghelp"> - DEPS - absl::debugging_internal - absl::demangle_internal - absl::base - absl::config - absl::core_headers - absl::dynamic_annotations - absl::malloc_internal - absl::raw_logging_internal - absl::strings - PUBLIC -) - -absl_cc_test( - NAME - symbolize_test - SRCS - "symbolize_test.cc" - COPTS - ${ABSL_TEST_COPTS} - $<$<BOOL:${MSVC}>:-Z7> - LINKOPTS - $<$<BOOL:${MSVC}>:-DEBUG> - DEPS - absl::stack_consumption - absl::symbolize - absl::base - absl::config - absl::core_headers - absl::memory - absl::raw_logging_internal - absl::strings - gmock -) - -absl_cc_library( - NAME - examine_stack - HDRS - "internal/examine_stack.h" - SRCS - "internal/examine_stack.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::stacktrace - absl::symbolize - absl::config - absl::core_headers - absl::raw_logging_internal -) - -absl_cc_library( - NAME - failure_signal_handler - HDRS - "failure_signal_handler.h" - SRCS - "failure_signal_handler.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::examine_stack - absl::stacktrace - absl::base - absl::config - absl::core_headers - absl::errno_saver - absl::raw_logging_internal - PUBLIC -) - -absl_cc_test( - NAME - failure_signal_handler_test - SRCS - "failure_signal_handler_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::failure_signal_handler - absl::stacktrace - absl::symbolize - absl::strings - absl::raw_logging_internal - Threads::Threads - gmock -) - -absl_cc_library( - NAME - debugging_internal - HDRS - "internal/address_is_readable.h" - "internal/elf_mem_image.h" - "internal/vdso_support.h" - SRCS - "internal/address_is_readable.cc" - "internal/elf_mem_image.cc" - "internal/vdso_support.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::config - absl::dynamic_annotations - absl::errno_saver - absl::raw_logging_internal -) - -absl_cc_library( - NAME - demangle_internal - HDRS - "internal/demangle.h" - SRCS - "internal/demangle.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::core_headers - PUBLIC -) - -absl_cc_test( - NAME - demangle_test - SRCS - "internal/demangle_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::demangle_internal - absl::stack_consumption - absl::config - absl::core_headers - absl::memory - absl::raw_logging_internal - gmock_main -) - -absl_cc_library( - NAME - leak_check - HDRS - "leak_check.h" - SRCS - "leak_check.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - PUBLIC -) - -absl_cc_library( - NAME - leak_check_disable - SRCS - "leak_check_disable.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - PUBLIC -) - -absl_cc_library( - NAME - leak_check_api_enabled_for_testing - HDRS - "leak_check.h" - SRCS - "leak_check.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - $<$<BOOL:${ABSL_HAVE_LSAN}>:-DLEAK_SANITIZER> - TESTONLY -) - -absl_cc_library( - NAME - leak_check_api_disabled_for_testing - HDRS - "leak_check.h" - SRCS - "leak_check.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - "-ULEAK_SANITIZER" - TESTONLY -) - -absl_cc_test( - NAME - leak_check_test - SRCS - "leak_check_test.cc" - COPTS - ${ABSL_TEST_COPTS} - "$<$<BOOL:${ABSL_HAVE_LSAN}>:-DABSL_EXPECT_LEAK_SANITIZER>" - LINKOPTS - "${ABSL_LSAN_LINKOPTS}" - DEPS - absl::leak_check_api_enabled_for_testing - absl::base - gmock_main -) - -absl_cc_test( - NAME - leak_check_no_lsan_test - SRCS - "leak_check_test.cc" - COPTS - ${ABSL_TEST_COPTS} - "-UABSL_EXPECT_LEAK_SANITIZER" - DEPS - absl::leak_check_api_disabled_for_testing - absl::base - gmock_main -) - -absl_cc_test( - NAME - disabled_leak_check_test - SRCS - "leak_check_fail_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - "${ABSL_LSAN_LINKOPTS}" - DEPS - absl::leak_check_api_enabled_for_testing - absl::leak_check_disable - absl::base - absl::raw_logging_internal - gmock_main -) - -absl_cc_library( - NAME - stack_consumption - HDRS - "internal/stack_consumption.h" - SRCS - "internal/stack_consumption.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - absl::raw_logging_internal - TESTONLY -) - -absl_cc_test( - NAME - stack_consumption_test - SRCS - "internal/stack_consumption_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::stack_consumption - absl::core_headers - absl::raw_logging_internal - gmock_main -) - -# component target -absl_cc_library( - NAME - debugging - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::stacktrace - absl::leak_check - PUBLIC -) diff --git a/third_party/abseil_cpp/absl/debugging/failure_signal_handler.cc b/third_party/abseil_cpp/absl/debugging/failure_signal_handler.cc deleted file mode 100644 index 5d13bdbbbd13..000000000000 --- a/third_party/abseil_cpp/absl/debugging/failure_signal_handler.cc +++ /dev/null @@ -1,370 +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/debugging/failure_signal_handler.h" - -#include "absl/base/config.h" - -#ifdef _WIN32 -#include <windows.h> -#else -#include <unistd.h> -#endif - -#ifdef __APPLE__ -#include <TargetConditionals.h> -#endif - -#ifdef ABSL_HAVE_MMAP -#include <sys/mman.h> -#endif - -#include <algorithm> -#include <atomic> -#include <cerrno> -#include <csignal> -#include <cstdio> -#include <cstring> -#include <ctime> - -#include "absl/base/attributes.h" -#include "absl/base/internal/errno_saver.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/sysinfo.h" -#include "absl/debugging/internal/examine_stack.h" -#include "absl/debugging/stacktrace.h" - -#ifndef _WIN32 -#define ABSL_HAVE_SIGACTION -// Apple WatchOS and TVOS don't allow sigaltstack -#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \ - !(defined(TARGET_OS_TV) && TARGET_OS_TV) -#define ABSL_HAVE_SIGALTSTACK -#endif -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN - -ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options; - -// Resets the signal handler for signo to the default action for that -// signal, then raises the signal. -static void RaiseToDefaultHandler(int signo) { - signal(signo, SIG_DFL); - raise(signo); -} - -struct FailureSignalData { - const int signo; - const char* const as_string; -#ifdef ABSL_HAVE_SIGACTION - struct sigaction previous_action; - // StructSigaction is used to silence -Wmissing-field-initializers. - using StructSigaction = struct sigaction; - #define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction() -#else - void (*previous_handler)(int); - #define FSD_PREVIOUS_INIT SIG_DFL -#endif -}; - -ABSL_CONST_INIT static FailureSignalData failure_signal_data[] = { - {SIGSEGV, "SIGSEGV", FSD_PREVIOUS_INIT}, - {SIGILL, "SIGILL", FSD_PREVIOUS_INIT}, - {SIGFPE, "SIGFPE", FSD_PREVIOUS_INIT}, - {SIGABRT, "SIGABRT", FSD_PREVIOUS_INIT}, - {SIGTERM, "SIGTERM", FSD_PREVIOUS_INIT}, -#ifndef _WIN32 - {SIGBUS, "SIGBUS", FSD_PREVIOUS_INIT}, - {SIGTRAP, "SIGTRAP", FSD_PREVIOUS_INIT}, -#endif -}; - -#undef FSD_PREVIOUS_INIT - -static void RaiseToPreviousHandler(int signo) { - // Search for the previous handler. - for (const auto& it : failure_signal_data) { - if (it.signo == signo) { -#ifdef ABSL_HAVE_SIGACTION - sigaction(signo, &it.previous_action, nullptr); -#else - signal(signo, it.previous_handler); -#endif - raise(signo); - return; - } - } - - // Not found, use the default handler. - RaiseToDefaultHandler(signo); -} - -namespace debugging_internal { - -const char* FailureSignalToString(int signo) { - for (const auto& it : failure_signal_data) { - if (it.signo == signo) { - return it.as_string; - } - } - return ""; -} - -} // namespace debugging_internal - -#ifdef ABSL_HAVE_SIGALTSTACK - -static bool SetupAlternateStackOnce() { -#if defined(__wasm__) || defined (__asjms__) - const size_t page_mask = getpagesize() - 1; -#else - const size_t page_mask = sysconf(_SC_PAGESIZE) - 1; -#endif - size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask; -#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ - defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) - // Account for sanitizer instrumentation requiring additional stack space. - stack_size *= 5; -#endif - - stack_t sigstk; - memset(&sigstk, 0, sizeof(sigstk)); - sigstk.ss_size = stack_size; - -#ifdef ABSL_HAVE_MMAP -#ifndef MAP_STACK -#define MAP_STACK 0 -#endif -#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) -#define MAP_ANONYMOUS MAP_ANON -#endif - sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); - if (sigstk.ss_sp == MAP_FAILED) { - ABSL_RAW_LOG(FATAL, "mmap() for alternate signal stack failed"); - } -#else - sigstk.ss_sp = malloc(sigstk.ss_size); - if (sigstk.ss_sp == nullptr) { - ABSL_RAW_LOG(FATAL, "malloc() for alternate signal stack failed"); - } -#endif - - if (sigaltstack(&sigstk, nullptr) != 0) { - ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno); - } - return true; -} - -#endif - -#ifdef ABSL_HAVE_SIGACTION - -// Sets up an alternate stack for signal handlers once. -// Returns the appropriate flag for sig_action.sa_flags -// if the system supports using an alternate stack. -static int MaybeSetupAlternateStack() { -#ifdef ABSL_HAVE_SIGALTSTACK - ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce(); - return SA_ONSTACK; -#else - return 0; -#endif -} - -static void InstallOneFailureHandler(FailureSignalData* data, - void (*handler)(int, siginfo_t*, void*)) { - struct sigaction act; - memset(&act, 0, sizeof(act)); - sigemptyset(&act.sa_mask); - act.sa_flags |= SA_SIGINFO; - // SA_NODEFER is required to handle SIGABRT from - // ImmediateAbortSignalHandler(). - act.sa_flags |= SA_NODEFER; - if (fsh_options.use_alternate_stack) { - act.sa_flags |= MaybeSetupAlternateStack(); - } - act.sa_sigaction = handler; - ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0, - "sigaction() failed"); -} - -#else - -static void InstallOneFailureHandler(FailureSignalData* data, - void (*handler)(int)) { - data->previous_handler = signal(data->signo, handler); - ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, "signal() failed"); -} - -#endif - -static void WriteToStderr(const char* data) { - absl::base_internal::ErrnoSaver errno_saver; - absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data)); -} - -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 ***\n", - signal_string, - static_cast<long>(time(nullptr))); // NOLINT(runtime/int) - } else { - snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n", - signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int) - } - writerfn(buf); -} - -// `void*` might not be big enough to store `void(*)(const char*)`. -struct WriterFnStruct { - void (*writerfn)(const char*); -}; - -// Many of the absl::debugging_internal::Dump* functions in -// examine_stack.h take a writer function pointer that has a void* arg -// for historical reasons. failure_signal_handler_writer only takes a -// data pointer. This function converts between these types. -static void WriterFnWrapper(const char* data, void* arg) { - static_cast<WriterFnStruct*>(arg)->writerfn(data); -} - -// Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal -// handlers. "noinline" so that GetStackFrames() skips the top-most stack -// frame for this function. -ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace( - void* ucontext, bool symbolize_stacktrace, - void (*writerfn)(const char*, void*), void* writerfn_arg) { - constexpr int kNumStackFrames = 32; - void* stack[kNumStackFrames]; - int frame_sizes[kNumStackFrames]; - int min_dropped_frames; - int depth = absl::GetStackFramesWithContext( - stack, frame_sizes, kNumStackFrames, - 1, // Do not include this function in stack trace. - ucontext, &min_dropped_frames); - absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace( - absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes, - depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg); -} - -// 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, - void (*writerfn)(const char*)) { - WriterFnStruct writerfn_struct{writerfn}; - WriteSignalMessage(signo, writerfn); - WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper, - &writerfn_struct); -} - -// absl::SleepFor() can't be used here since AbslInternalSleepFor() -// may be overridden to do something that isn't async-signal-safe on -// some platforms. -static void PortableSleepForSeconds(int seconds) { -#ifdef _WIN32 - Sleep(seconds * 1000); -#else - struct timespec sleep_time; - sleep_time.tv_sec = seconds; - sleep_time.tv_nsec = 0; - while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {} -#endif -} - -#ifdef ABSL_HAVE_ALARM -// AbslFailureSignalHandler() installs this as a signal handler for -// SIGALRM, then sets an alarm to be delivered to the program after a -// set amount of time. If AbslFailureSignalHandler() hangs for more than -// the alarm timeout, ImmediateAbortSignalHandler() will abort the -// program. -static void ImmediateAbortSignalHandler(int) { - RaiseToDefaultHandler(SIGABRT); -} -#endif - -// absl::base_internal::GetTID() returns pid_t on most platforms, but -// returns absl::base_internal::pid_t on Windows. -using GetTidType = decltype(absl::base_internal::GetTID()); -ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0); - -#ifndef ABSL_HAVE_SIGACTION -static void AbslFailureSignalHandler(int signo) { - void* ucontext = nullptr; -#else -static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { -#endif - - const GetTidType this_tid = absl::base_internal::GetTID(); - GetTidType previous_failed_tid = 0; - if (!failed_tid.compare_exchange_strong( - previous_failed_tid, static_cast<intptr_t>(this_tid), - std::memory_order_acq_rel, std::memory_order_relaxed)) { - ABSL_RAW_LOG( - ERROR, - "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()", - signo, absl::debugging_internal::GetProgramCounter(ucontext)); - if (this_tid != previous_failed_tid) { - // Another thread is already in AbslFailureSignalHandler(), so wait - // a bit for it to finish. If the other thread doesn't kill us, - // we do so after sleeping. - PortableSleepForSeconds(3); - RaiseToDefaultHandler(signo); - // The recursively raised signal may be blocked until we return. - return; - } - } - -#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) { - alarm(0); // Cancel any existing alarms. - signal(SIGALRM, ImmediateAbortSignalHandler); - alarm(fsh_options.alarm_on_failure_secs); - } -#endif - - // First write to stderr. - 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, fsh_options.writerfn); - } - - if (fsh_options.call_previous_handler) { - RaiseToPreviousHandler(signo); - } else { - RaiseToDefaultHandler(signo); - } -} - -void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) { - fsh_options = options; - for (auto& it : failure_signal_data) { - InstallOneFailureHandler(&it, AbslFailureSignalHandler); - } -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/debugging/failure_signal_handler.h b/third_party/abseil_cpp/absl/debugging/failure_signal_handler.h deleted file mode 100644 index 0c0f585d0fb4..000000000000 --- a/third_party/abseil_cpp/absl/debugging/failure_signal_handler.h +++ /dev/null @@ -1,121 +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: failure_signal_handler.h -// ----------------------------------------------------------------------------- -// -// This file configures the Abseil *failure signal handler* to capture and dump -// useful debugging information (such as a stacktrace) upon program failure. -// -// To use the failure signal handler, call `absl::InstallFailureSignalHandler()` -// very early in your program, usually in the first few lines of main(): -// -// int main(int argc, char** argv) { -// // Initialize the symbolizer to get a human-readable stack trace -// absl::InitializeSymbolizer(argv[0]); -// -// absl::FailureSignalHandlerOptions options; -// absl::InstallFailureSignalHandler(options); -// DoSomethingInteresting(); -// return 0; -// } -// -// Any program that raises a fatal signal (such as `SIGSEGV`, `SIGILL`, -// `SIGFPE`, `SIGABRT`, `SIGTERM`, `SIGBUG`, and `SIGTRAP`) will call the -// installed failure signal handler and provide debugging information to stderr. -// -// Note that you should *not* install the Abseil failure signal handler more -// than once. You may, of course, have another (non-Abseil) failure signal -// handler installed (which would be triggered if Abseil's failure signal -// handler sets `call_previous_handler` to `true`). - -#ifndef ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ -#define ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// FailureSignalHandlerOptions -// -// Struct for holding `absl::InstallFailureSignalHandler()` configuration -// options. -struct FailureSignalHandlerOptions { - // If true, try to symbolize the stacktrace emitted on failure, provided that - // you have initialized a symbolizer for that purpose. (See symbolize.h for - // more information.) - bool symbolize_stacktrace = true; - - // If true, try to run signal handlers on an alternate stack (if supported on - // the given platform). An alternate stack is useful for program crashes due - // to a stack overflow; by running on a alternate stack, the signal handler - // may run even when normal stack space has been exausted. The downside of - // using an alternate stack is that extra memory for the alternate stack needs - // to be pre-allocated. - bool use_alternate_stack = true; - - // If positive, indicates the number of seconds after which the failure signal - // handler is invoked to abort the program. Setting such an alarm is useful in - // cases where the failure signal handler itself may become hung or - // deadlocked. - int alarm_on_failure_secs = 3; - - // If true, call the previously registered signal handler for the signal that - // was received (if one was registered) after the existing signal handler - // runs. This mechanism can be used to chain signal handlers together. - // - // If false, the signal is raised to the default handler for that signal - // (which normally terminates the program). - // - // IMPORTANT: If true, the chained fatal signal handlers must not try to - // recover from the fatal signal. Instead, they should terminate the program - // via some mechanism, like raising the default handler for the signal, or by - // calling `_exit()`. Note that the failure signal handler may put parts of - // the Abseil library into a state from which they cannot recover. - 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 - // may be used as a hook to write failure data to a secondary location, such - // as a log file. This function may also be called with null data, as a hint - // to flush any buffered data before the program may be terminated. Consider - // flushing any buffered data in all calls to this function. - // - // Since this function runs within a signal handler, it should be - // async-signal-safe if possible. - // See http://man7.org/linux/man-pages/man7/signal-safety.7.html - void (*writerfn)(const char*) = nullptr; -}; - -// InstallFailureSignalHandler() -// -// Installs a signal handler for the common failure signals `SIGSEGV`, `SIGILL`, -// `SIGFPE`, `SIGABRT`, `SIGTERM`, `SIGBUG`, and `SIGTRAP` (provided they exist -// on the given platform). The failure signal handler dumps program failure data -// useful for debugging in an unspecified format to stderr. This data may -// include the program counter, a stacktrace, and register information on some -// systems; do not rely on an exact format for the output, as it is subject to -// change. -void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options); - -namespace debugging_internal { -const char* FailureSignalToString(int signo); -} // namespace debugging_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ diff --git a/third_party/abseil_cpp/absl/debugging/failure_signal_handler_test.cc b/third_party/abseil_cpp/absl/debugging/failure_signal_handler_test.cc deleted file mode 100644 index d8283b2f47cd..000000000000 --- a/third_party/abseil_cpp/absl/debugging/failure_signal_handler_test.cc +++ /dev/null @@ -1,159 +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/debugging/failure_signal_handler.h" - -#include <csignal> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <fstream> - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/symbolize.h" -#include "absl/strings/match.h" -#include "absl/strings/str_cat.h" - -namespace { - -using testing::StartsWith; - -#if GTEST_HAS_DEATH_TEST - -// For the parameterized death tests. GetParam() returns the signal number. -using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>; - -// This function runs in a fork()ed process on most systems. -void InstallHandlerAndRaise(int signo) { - absl::InstallFailureSignalHandler(absl::FailureSignalHandlerOptions()); - raise(signo); -} - -TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) { - const int signo = GetParam(); - std::string exit_regex = absl::StrCat( - "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), - " received at time="); -#ifndef _WIN32 - EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo), - exit_regex); -#else - // Windows doesn't have testing::KilledBySignal(). - EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex); -#endif -} - -ABSL_CONST_INIT FILE* error_file = nullptr; - -void WriteToErrorFile(const char* msg) { - if (msg != nullptr) { - ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1, - "fwrite() failed"); - } - ABSL_RAW_CHECK(fflush(error_file) == 0, "fflush() failed"); -} - -std::string GetTmpDir() { - // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel. - static const char* const kTmpEnvVars[] = {"TEST_TMPDIR", "TMPDIR", "TEMP", - "TEMPDIR", "TMP"}; - for (const char* const var : kTmpEnvVars) { - const char* tmp_dir = std::getenv(var); - if (tmp_dir != nullptr) { - return tmp_dir; - } - } - - // Try something reasonable. - return "/tmp"; -} - -// This function runs in a fork()ed process on most systems. -void InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) { - error_file = fopen(file, "w"); - ABSL_RAW_CHECK(error_file != nullptr, "Failed create error_file"); - absl::FailureSignalHandlerOptions options; - options.writerfn = WriteToErrorFile; - absl::InstallFailureSignalHandler(options); - raise(signo); -} - -TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) { - const int signo = GetParam(); - std::string tmp_dir = GetTmpDir(); - std::string file = absl::StrCat(tmp_dir, "/signo_", signo); - - std::string exit_regex = absl::StrCat( - "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), - " received at time="); -#ifndef _WIN32 - EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), - testing::KilledBySignal(signo), exit_regex); -#else - // Windows doesn't have testing::KilledBySignal(). - EXPECT_DEATH_IF_SUPPORTED( - InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex); -#endif - - // Open the file in this process and check its contents. - std::fstream error_output(file); - ASSERT_TRUE(error_output.is_open()) << file; - std::string error_line; - std::getline(error_output, error_line); - EXPECT_THAT( - error_line, - StartsWith(absl::StrCat( - "*** ", absl::debugging_internal::FailureSignalToString(signo), - " received at "))); - - if (absl::debugging_internal::StackTraceWorksForTest()) { - std::getline(error_output, error_line); - EXPECT_THAT(error_line, StartsWith("PC: ")); - } -} - -constexpr int kFailureSignals[] = { - SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGTERM, -#ifndef _WIN32 - SIGBUS, SIGTRAP, -#endif -}; - -std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) { - std::string result = - absl::debugging_internal::FailureSignalToString(info.param); - if (result.empty()) { - result = absl::StrCat(info.param); - } - return result; -} - -INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest, - ::testing::ValuesIn(kFailureSignals), - SignalParamToString); - -#endif // GTEST_HAS_DEATH_TEST - -} // namespace - -int main(int argc, char** argv) { - absl::InitializeSymbolizer(argv[0]); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} 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 deleted file mode 100644 index 329c285f3b58..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/address_is_readable.cc +++ /dev/null @@ -1,139 +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. - -// base::AddressIsReadable() probes an address to see whether it is readable, -// without faulting. - -#include "absl/debugging/internal/address_is_readable.h" - -#if !defined(__linux__) || defined(__ANDROID__) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// On platforms other than Linux, just return true. -bool AddressIsReadable(const void* /* addr */) { return true; } - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#else - -#include <fcntl.h> -#include <sys/syscall.h> -#include <unistd.h> - -#include <atomic> -#include <cerrno> -#include <cstdint> - -#include "absl/base/internal/errno_saver.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Pack a pid and two file descriptors into a 64-bit word, -// using 16, 24, and 24 bits for each respectively. -static uint64_t Pack(uint64_t pid, uint64_t read_fd, uint64_t write_fd) { - ABSL_RAW_CHECK((read_fd >> 24) == 0 && (write_fd >> 24) == 0, - "fd out of range"); - return (pid << 48) | ((read_fd & 0xffffff) << 24) | (write_fd & 0xffffff); -} - -// Unpack x into a pid and two file descriptors, where x was created with -// Pack(). -static void Unpack(uint64_t x, int *pid, int *read_fd, int *write_fd) { - *pid = x >> 48; - *read_fd = (x >> 24) & 0xffffff; - *write_fd = x & 0xffffff; -} - -// Return whether the byte at *addr is readable, without faulting. -// Save and restores errno. Returns true on systems where -// 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 - // be done via a cached file descriptor to /dev/null, but linux fails to - // check whether the byte is readable when the destination is /dev/null, so - // we use a cached pipe. We store the pid of the process that created the - // pipe to handle the case where a process forks, and the child closes all - // the file descriptors and then calls this routine. This is not perfect: - // the child could use the routine, then close all file descriptors and then - // use this routine again. But the likely use of this routine is when - // crashing, to test the validity of pages when dumping the stack. Beware - // that we may leak file descriptors, but we're unlikely to leak many. - int bytes_written; - int current_pid = getpid() & 0xffff; // we use only the low order 16 bits - do { // until we do not get EBADF trying to use file descriptors - int pid; - int read_fd; - int write_fd; - uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire); - Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd); - while (current_pid != pid) { - int p[2]; - // new pipe - if (pipe(p) != 0) { - ABSL_RAW_LOG(FATAL, "Failed to create pipe, errno=%d", errno); - } - fcntl(p[0], F_SETFD, FD_CLOEXEC); - 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, - 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); - } - Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd); - } - errno = 0; - // Use syscall(SYS_write, ...) instead of write() to prevent ASAN - // and other checkers from complaining about accesses to arbitrary - // memory. - do { - bytes_written = syscall(SYS_write, write_fd, addr, 1); - } while (bytes_written == -1 && errno == EINTR); - if (bytes_written == 1) { // remove the byte from the pipe - char c; - while (read(read_fd, &c, 1) == -1 && errno == EINTR) { - } - } - if (errno == EBADF) { // Descriptors invalid. - // 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); - } - } while (errno == EBADF); - return bytes_written == 1; -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif diff --git a/third_party/abseil_cpp/absl/debugging/internal/address_is_readable.h b/third_party/abseil_cpp/absl/debugging/internal/address_is_readable.h deleted file mode 100644 index 4bbaf4d69bd8..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/address_is_readable.h +++ /dev/null @@ -1,32 +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. - -#ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ -#define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Return whether the byte at *addr is readable, without faulting. -// Save and restores errno. -bool AddressIsReadable(const void *addr); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/demangle.cc b/third_party/abseil_cpp/absl/debugging/internal/demangle.cc deleted file mode 100644 index 46cdb67b1fbf..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/demangle.cc +++ /dev/null @@ -1,1945 +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. - -// For reference check out: -// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling -// -// Note that we only have partial C++11 support yet. - -#include "absl/debugging/internal/demangle.h" - -#include <cstdint> -#include <cstdio> -#include <limits> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -typedef struct { - const char *abbrev; - const char *real_name; - // Number of arguments in <expression> context, or 0 if disallowed. - int arity; -} AbbrevPair; - -// List of operators from Itanium C++ ABI. -static const AbbrevPair kOperatorList[] = { - // New has special syntax (not currently supported). - {"nw", "new", 0}, - {"na", "new[]", 0}, - - // Works except that the 'gs' prefix is not supported. - {"dl", "delete", 1}, - {"da", "delete[]", 1}, - - {"ps", "+", 1}, // "positive" - {"ng", "-", 1}, // "negative" - {"ad", "&", 1}, // "address-of" - {"de", "*", 1}, // "dereference" - {"co", "~", 1}, - - {"pl", "+", 2}, - {"mi", "-", 2}, - {"ml", "*", 2}, - {"dv", "/", 2}, - {"rm", "%", 2}, - {"an", "&", 2}, - {"or", "|", 2}, - {"eo", "^", 2}, - {"aS", "=", 2}, - {"pL", "+=", 2}, - {"mI", "-=", 2}, - {"mL", "*=", 2}, - {"dV", "/=", 2}, - {"rM", "%=", 2}, - {"aN", "&=", 2}, - {"oR", "|=", 2}, - {"eO", "^=", 2}, - {"ls", "<<", 2}, - {"rs", ">>", 2}, - {"lS", "<<=", 2}, - {"rS", ">>=", 2}, - {"eq", "==", 2}, - {"ne", "!=", 2}, - {"lt", "<", 2}, - {"gt", ">", 2}, - {"le", "<=", 2}, - {"ge", ">=", 2}, - {"nt", "!", 1}, - {"aa", "&&", 2}, - {"oo", "||", 2}, - {"pp", "++", 1}, - {"mm", "--", 1}, - {"cm", ",", 2}, - {"pm", "->*", 2}, - {"pt", "->", 0}, // Special syntax - {"cl", "()", 0}, // Special syntax - {"ix", "[]", 2}, - {"qu", "?", 3}, - {"st", "sizeof", 0}, // Special syntax - {"sz", "sizeof", 1}, // Not a real operator name, but used in expressions. - {nullptr, nullptr, 0}, -}; - -// List of builtin types from Itanium C++ ABI. -// -// Invariant: only one- or two-character type abbreviations here. -static const AbbrevPair kBuiltinTypeList[] = { - {"v", "void", 0}, - {"w", "wchar_t", 0}, - {"b", "bool", 0}, - {"c", "char", 0}, - {"a", "signed char", 0}, - {"h", "unsigned char", 0}, - {"s", "short", 0}, - {"t", "unsigned short", 0}, - {"i", "int", 0}, - {"j", "unsigned int", 0}, - {"l", "long", 0}, - {"m", "unsigned long", 0}, - {"x", "long long", 0}, - {"y", "unsigned long long", 0}, - {"n", "__int128", 0}, - {"o", "unsigned __int128", 0}, - {"f", "float", 0}, - {"d", "double", 0}, - {"e", "long double", 0}, - {"g", "__float128", 0}, - {"z", "ellipsis", 0}, - - {"De", "decimal128", 0}, // IEEE 754r decimal floating point (128 bits) - {"Dd", "decimal64", 0}, // IEEE 754r decimal floating point (64 bits) - {"Dc", "decltype(auto)", 0}, - {"Da", "auto", 0}, - {"Dn", "std::nullptr_t", 0}, // i.e., decltype(nullptr) - {"Df", "decimal32", 0}, // IEEE 754r decimal floating point (32 bits) - {"Di", "char32_t", 0}, - {"Du", "char8_t", 0}, - {"Ds", "char16_t", 0}, - {"Dh", "float16", 0}, // IEEE 754r half-precision float (16 bits) - {nullptr, nullptr, 0}, -}; - -// List of substitutions Itanium C++ ABI. -static const AbbrevPair kSubstitutionList[] = { - {"St", "", 0}, - {"Sa", "allocator", 0}, - {"Sb", "basic_string", 0}, - // std::basic_string<char, std::char_traits<char>,std::allocator<char> > - {"Ss", "string", 0}, - // std::basic_istream<char, std::char_traits<char> > - {"Si", "istream", 0}, - // std::basic_ostream<char, std::char_traits<char> > - {"So", "ostream", 0}, - // std::basic_iostream<char, std::char_traits<char> > - {"Sd", "iostream", 0}, - {nullptr, nullptr, 0}, -}; - -// State needed for demangling. This struct is copied in almost every stack -// frame, so every byte counts. -typedef struct { - int mangled_idx; // Cursor of mangled name. - int out_cur_idx; // Cursor of output string. - int prev_name_idx; // For constructors/destructors. - signed int prev_name_length : 16; // For constructors/destructors. - signed int nest_level : 15; // For nested names. - unsigned int append : 1; // Append flag. - // Note: for some reason MSVC can't pack "bool append : 1" into the same int - // with the above two fields, so we use an int instead. Amusingly it can pack - // "signed bool" as expected, but relying on that to continue to be a legal - // type seems ill-advised (as it's illegal in at least clang). -} ParseState; - -static_assert(sizeof(ParseState) == 4 * sizeof(int), - "unexpected size of ParseState"); - -// One-off state for demangling that's not subject to backtracking -- either -// constant data, data that's intentionally immune to backtracking (steps), or -// data that would never be changed by backtracking anyway (recursion_depth). -// -// 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. - 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. - ParseState parse_state; // Backtrackable state copied for most frames. -} State; - -namespace { -// Prevent deep recursion / stack exhaustion. -// Also prevent unbounded handling of complex inputs. -class ComplexityGuard { - public: - explicit ComplexityGuard(State *state) : state_(state) { - ++state->recursion_depth; - ++state->steps; - } - ~ComplexityGuard() { --state_->recursion_depth; } - - // 256 levels of recursion seems like a reasonable upper limit on depth. - // 128 is not enough to demagle synthetic tests from demangle_unittest.txt: - // "_ZaaZZZZ..." and "_ZaaZcvZcvZ..." - static constexpr int kRecursionDepthLimit = 256; - - // We're trying to pick a charitable upper-limit on how many parse steps are - // necessary to handle something that a human could actually make use of. - // This is mostly in place as a bound on how much work we'll do if we are - // asked to demangle an mangled name from an untrusted source, so it should be - // much larger than the largest expected symbol, but much smaller than the - // amount of work we can do in, e.g., a second. - // - // Some real-world symbols from an arbitrary binary started failing between - // 2^12 and 2^13, so we multiply the latter by an extra factor of 16 to set - // the limit. - // - // Spending one second on 2^17 parse steps would require each step to take - // 7.6us, or ~30000 clock cycles, so it's safe to say this can be done in - // under a second. - static constexpr int kParseStepsLimit = 1 << 17; - - bool IsTooComplex() const { - return state_->recursion_depth > kRecursionDepthLimit || - state_->steps > kParseStepsLimit; - } - - private: - State *state_; -}; -} // namespace - -// We don't use strlen() in libc since it's not guaranteed to be async -// signal safe. -static size_t StrLen(const char *str) { - size_t len = 0; - while (*str != '\0') { - ++str; - ++len; - } - return len; -} - -// Returns true if "str" has at least "n" characters remaining. -static bool AtLeastNumCharsRemaining(const char *str, int n) { - for (int i = 0; i < n; ++i) { - if (str[i] == '\0') { - return false; - } - } - return true; -} - -// Returns true if "str" has "prefix" as a prefix. -static bool StrPrefix(const char *str, const char *prefix) { - size_t i = 0; - while (str[i] != '\0' && prefix[i] != '\0' && str[i] == prefix[i]) { - ++i; - } - return prefix[i] == '\0'; // Consumed everything in "prefix". -} - -static void InitState(State *state, const char *mangled, char *out, - int out_size) { - state->mangled_begin = mangled; - state->out = out; - state->out_end_idx = out_size; - state->recursion_depth = 0; - state->steps = 0; - - state->parse_state.mangled_idx = 0; - state->parse_state.out_cur_idx = 0; - state->parse_state.prev_name_idx = 0; - state->parse_state.prev_name_length = -1; - state->parse_state.nest_level = -1; - state->parse_state.append = true; -} - -static inline const char *RemainingInput(State *state) { - return &state->mangled_begin[state->parse_state.mangled_idx]; -} - -// Returns true and advances "mangled_idx" if we find "one_char_token" -// at "mangled_idx" position. It is assumed that "one_char_token" does -// not contain '\0'. -static bool ParseOneCharToken(State *state, const char one_char_token) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (RemainingInput(state)[0] == one_char_token) { - ++state->parse_state.mangled_idx; - return true; - } - return false; -} - -// Returns true and advances "mangled_cur" if we find "two_char_token" -// at "mangled_cur" position. It is assumed that "two_char_token" does -// not contain '\0'. -static bool ParseTwoCharToken(State *state, const char *two_char_token) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (RemainingInput(state)[0] == two_char_token[0] && - RemainingInput(state)[1] == two_char_token[1]) { - state->parse_state.mangled_idx += 2; - return true; - } - return false; -} - -// Returns true and advances "mangled_cur" if we find any character in -// "char_class" at "mangled_cur" position. -static bool ParseCharClass(State *state, const char *char_class) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (RemainingInput(state)[0] == '\0') { - return false; - } - const char *p = char_class; - for (; *p != '\0'; ++p) { - if (RemainingInput(state)[0] == *p) { - ++state->parse_state.mangled_idx; - return true; - } - } - return false; -} - -static bool ParseDigit(State *state, int *digit) { - char c = RemainingInput(state)[0]; - if (ParseCharClass(state, "0123456789")) { - if (digit != nullptr) { - *digit = c - '0'; - } - return true; - } - return false; -} - -// This function is used for handling an optional non-terminal. -static bool Optional(bool /*status*/) { return true; } - -// This function is used for handling <non-terminal>+ syntax. -typedef bool (*ParseFunc)(State *); -static bool OneOrMore(ParseFunc parse_func, State *state) { - if (parse_func(state)) { - while (parse_func(state)) { - } - return true; - } - return false; -} - -// This function is used for handling <non-terminal>* syntax. The function -// always returns true and must be followed by a termination token or a -// terminating sequence not handled by parse_func (e.g. -// ParseOneCharToken(state, 'E')). -static bool ZeroOrMore(ParseFunc parse_func, State *state) { - while (parse_func(state)) { - } - return true; -} - -// Append "str" at "out_cur_idx". If there is an overflow, out_cur_idx is -// set to out_end_idx+1. The output string is ensured to -// always terminate with '\0' as long as there is no overflow. -static void Append(State *state, const char *const str, const int length) { - for (int i = 0; i < length; ++i) { - if (state->parse_state.out_cur_idx + 1 < - state->out_end_idx) { // +1 for '\0' - state->out[state->parse_state.out_cur_idx++] = str[i]; - } else { - // signal overflow - state->parse_state.out_cur_idx = state->out_end_idx + 1; - break; - } - } - if (state->parse_state.out_cur_idx < state->out_end_idx) { - state->out[state->parse_state.out_cur_idx] = - '\0'; // Terminate it with '\0' - } -} - -// We don't use equivalents in libc to avoid locale issues. -static bool IsLower(char c) { return c >= 'a' && c <= 'z'; } - -static bool IsAlpha(char c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - -static bool IsDigit(char c) { return c >= '0' && c <= '9'; } - -// Returns true if "str" is a function clone suffix. These suffixes are used -// 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. -static bool IsFunctionCloneSuffix(const char *str) { - size_t i = 0; - while (str[i] != '\0') { - // Consume a single .<alpha>+.<digit>+ sequence. - if (str[i] != '.' || !IsAlpha(str[i + 1])) { - return false; - } - i += 2; - while (IsAlpha(str[i])) { - ++i; - } - 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]; -} - -// Append "str" with some tweaks, iff "append" state is true. -static void MaybeAppendWithLength(State *state, const char *const str, - const int length) { - if (state->parse_state.append && length > 0) { - // Append a space if the output buffer ends with '<' and "str" - // starts with '<' to avoid <<<. - 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] == '_')) { - state->parse_state.prev_name_idx = state->parse_state.out_cur_idx; - state->parse_state.prev_name_length = length; - } - Append(state, str, length); - } -} - -// Appends a positive decimal number to the output if appending is enabled. -static bool MaybeAppendDecimal(State *state, unsigned int val) { - // Max {32-64}-bit unsigned int is 20 digits. - constexpr size_t kMaxLength = 20; - char buf[kMaxLength]; - - // We can't use itoa or sprintf as neither is specified to be - // async-signal-safe. - if (state->parse_state.append) { - // We can't have a one-before-the-beginning pointer, so instead start with - // one-past-the-end and manipulate one character before the pointer. - char *p = &buf[kMaxLength]; - do { // val=0 is the only input that should write a leading zero digit. - *--p = (val % 10) + '0'; - val /= 10; - } while (p > buf && val != 0); - - // 'p' landed on the last character we set. How convenient. - Append(state, p, kMaxLength - (p - buf)); - } - - return true; -} - -// A convenient wrapper around MaybeAppendWithLength(). -// Returns true so that it can be placed in "if" conditions. -static bool MaybeAppend(State *state, const char *const str) { - if (state->parse_state.append) { - int length = StrLen(str); - MaybeAppendWithLength(state, str, length); - } - return true; -} - -// This function is used for handling nested names. -static bool EnterNestedName(State *state) { - state->parse_state.nest_level = 0; - return true; -} - -// This function is used for handling nested names. -static bool LeaveNestedName(State *state, int16_t prev_value) { - state->parse_state.nest_level = prev_value; - return true; -} - -// Disable the append mode not to print function parameters, etc. -static bool DisableAppend(State *state) { - state->parse_state.append = false; - return true; -} - -// Restore the append mode to the previous state. -static bool RestoreAppend(State *state, bool prev_value) { - state->parse_state.append = prev_value; - return true; -} - -// Increase the nest level for nested names. -static void MaybeIncreaseNestLevel(State *state) { - if (state->parse_state.nest_level > -1) { - ++state->parse_state.nest_level; - } -} - -// Appends :: for nested names if necessary. -static void MaybeAppendSeparator(State *state) { - if (state->parse_state.nest_level >= 1) { - MaybeAppend(state, "::"); - } -} - -// Cancel the last separator if necessary. -static void MaybeCancelLastSeparator(State *state) { - if (state->parse_state.nest_level >= 1 && state->parse_state.append && - state->parse_state.out_cur_idx >= 2) { - state->parse_state.out_cur_idx -= 2; - state->out[state->parse_state.out_cur_idx] = '\0'; - } -} - -// Returns true if the identifier of the given length pointed to by -// "mangled_cur" is anonymous namespace. -static bool IdentifierIsAnonymousNamespace(State *state, int length) { - // Returns true if "anon_prefix" is a proper prefix of "mangled_cur". - static const char anon_prefix[] = "_GLOBAL__N_"; - return (length > static_cast<int>(sizeof(anon_prefix) - 1) && - StrPrefix(RemainingInput(state), anon_prefix)); -} - -// Forward declarations of our parsing functions. -static bool ParseMangledName(State *state); -static bool ParseEncoding(State *state); -static bool ParseName(State *state); -static bool ParseUnscopedName(State *state); -static bool ParseNestedName(State *state); -static bool ParsePrefix(State *state); -static bool ParseUnqualifiedName(State *state); -static bool ParseSourceName(State *state); -static bool ParseLocalSourceName(State *state); -static bool ParseUnnamedTypeName(State *state); -static bool ParseNumber(State *state, int *number_out); -static bool ParseFloatNumber(State *state); -static bool ParseSeqId(State *state); -static bool ParseIdentifier(State *state, int length); -static bool ParseOperatorName(State *state, int *arity); -static bool ParseSpecialName(State *state); -static bool ParseCallOffset(State *state); -static bool ParseNVOffset(State *state); -static bool ParseVOffset(State *state); -static bool ParseCtorDtorName(State *state); -static bool ParseDecltype(State *state); -static bool ParseType(State *state); -static bool ParseCVQualifiers(State *state); -static bool ParseBuiltinType(State *state); -static bool ParseFunctionType(State *state); -static bool ParseBareFunctionType(State *state); -static bool ParseClassEnumType(State *state); -static bool ParseArrayType(State *state); -static bool ParsePointerToMemberType(State *state); -static bool ParseTemplateParam(State *state); -static bool ParseTemplateTemplateParam(State *state); -static bool ParseTemplateArgs(State *state); -static bool ParseTemplateArg(State *state); -static bool ParseBaseUnresolvedName(State *state); -static bool ParseUnresolvedName(State *state); -static bool ParseExpression(State *state); -static bool ParseExprPrimary(State *state); -static bool ParseExprCastValue(State *state); -static bool ParseLocalName(State *state); -static bool ParseLocalNameSuffix(State *state); -static bool ParseDiscriminator(State *state); -static bool ParseSubstitution(State *state, bool accept_std); - -// Implementation note: the following code is a straightforward -// translation of the Itanium C++ ABI defined in BNF with a couple of -// exceptions. -// -// - Support GNU extensions not defined in the Itanium C++ ABI -// - <prefix> and <template-prefix> are combined to avoid infinite loop -// - Reorder patterns to shorten the code -// - Reorder patterns to give greedier functions precedence -// We'll mark "Less greedy than" for these cases in the code -// -// Each parsing function changes the parse state and returns true on -// success, or returns false and doesn't change the parse state (note: -// the parse-steps counter increases regardless of success or failure). -// To ensure that the parse state isn't changed in the latter case, we -// save the original state before we call multiple parsing functions -// consecutively with &&, and restore it if unsuccessful. See -// ParseEncoding() as an example of this convention. We follow the -// convention throughout the code. -// -// Originally we tried to do demangling without following the full ABI -// syntax but it turned out we needed to follow the full syntax to -// parse complicated cases like nested template arguments. Note that -// implementing a full-fledged demangler isn't trivial (libiberty's -// cp-demangle.c has +4300 lines). -// -// Note that (foo) in <(foo) ...> is a modifier to be ignored. -// -// Reference: -// - Itanium C++ ABI -// <https://mentorembedded.github.io/cxx-abi/abi.html#mangling> - -// <mangled-name> ::= _Z <encoding> -static bool ParseMangledName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - return ParseTwoCharToken(state, "_Z") && ParseEncoding(state); -} - -// <encoding> ::= <(function) name> <bare-function-type> -// ::= <(data) name> -// ::= <special-name> -static bool ParseEncoding(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - // Implementing the first two productions together as <name> - // [<bare-function-type>] avoids exponential blowup of backtracking. - // - // Since Optional(...) can't fail, there's no need to copy the state for - // backtracking. - if (ParseName(state) && Optional(ParseBareFunctionType(state))) { - return true; - } - - if (ParseSpecialName(state)) { - return true; - } - return false; -} - -// <name> ::= <nested-name> -// ::= <unscoped-template-name> <template-args> -// ::= <unscoped-name> -// ::= <local-name> -static bool ParseName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseNestedName(state) || ParseLocalName(state)) { - return true; - } - - // We reorganize the productions to avoid re-parsing unscoped names. - // - Inline <unscoped-template-name> productions: - // <name> ::= <substitution> <template-args> - // ::= <unscoped-name> <template-args> - // ::= <unscoped-name> - // - Merge the two productions that start with unscoped-name: - // <name> ::= <unscoped-name> [<template-args>] - - ParseState copy = state->parse_state; - // "std<...>" isn't a valid name. - if (ParseSubstitution(state, /*accept_std=*/false) && - ParseTemplateArgs(state)) { - return true; - } - state->parse_state = copy; - - // Note there's no need to restore state after this since only the first - // subparser can fail. - return ParseUnscopedName(state) && Optional(ParseTemplateArgs(state)); -} - -// <unscoped-name> ::= <unqualified-name> -// ::= St <unqualified-name> -static bool ParseUnscopedName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseUnqualifiedName(state)) { - return true; - } - - ParseState copy = state->parse_state; - if (ParseTwoCharToken(state, "St") && MaybeAppend(state, "std::") && - ParseUnqualifiedName(state)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <ref-qualifer> ::= R // lvalue method reference qualifier -// ::= O // rvalue method reference qualifier -static inline bool ParseRefQualifier(State *state) { - return ParseCharClass(state, "OR"); -} - -// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> -// <unqualified-name> E -// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> -// <template-args> E -static bool ParseNestedName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'N') && EnterNestedName(state) && - Optional(ParseCVQualifiers(state)) && - Optional(ParseRefQualifier(state)) && ParsePrefix(state) && - LeaveNestedName(state, copy.nest_level) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - return false; -} - -// This part is tricky. If we literally translate them to code, we'll -// end up infinite loop. Hence we merge them to avoid the case. -// -// <prefix> ::= <prefix> <unqualified-name> -// ::= <template-prefix> <template-args> -// ::= <template-param> -// ::= <substitution> -// ::= # empty -// <template-prefix> ::= <prefix> <(template) unqualified-name> -// ::= <template-param> -// ::= <substitution> -static bool ParsePrefix(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - bool has_something = false; - while (true) { - MaybeAppendSeparator(state); - if (ParseTemplateParam(state) || - ParseSubstitution(state, /*accept_std=*/true) || - ParseUnscopedName(state) || - (ParseOneCharToken(state, 'M') && ParseUnnamedTypeName(state))) { - has_something = true; - MaybeIncreaseNestLevel(state); - continue; - } - MaybeCancelLastSeparator(state); - if (has_something && ParseTemplateArgs(state)) { - return ParsePrefix(state); - } else { - break; - } - } - return true; -} - -// <unqualified-name> ::= <operator-name> -// ::= <ctor-dtor-name> -// ::= <source-name> -// ::= <local-source-name> // GCC extension; see below. -// ::= <unnamed-type-name> -static bool ParseUnqualifiedName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - return (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) || - ParseSourceName(state) || ParseLocalSourceName(state) || - ParseUnnamedTypeName(state)); -} - -// <source-name> ::= <positive length number> <identifier> -static bool ParseSourceName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - int length = -1; - if (ParseNumber(state, &length) && ParseIdentifier(state, length)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <local-source-name> ::= L <source-name> [<discriminator>] -// -// References: -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 -// https://gcc.gnu.org/viewcvs?view=rev&revision=124467 -static bool ParseLocalSourceName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'L') && ParseSourceName(state) && - Optional(ParseDiscriminator(state))) { - return true; - } - state->parse_state = copy; - return false; -} - -// <unnamed-type-name> ::= Ut [<(nonnegative) number>] _ -// ::= <closure-type-name> -// <closure-type-name> ::= Ul <lambda-sig> E [<(nonnegative) number>] _ -// <lambda-sig> ::= <(parameter) type>+ -static bool ParseUnnamedTypeName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - // Type's 1-based index n is encoded as { "", n == 1; itoa(n-2), otherwise }. - // Optionally parse the encoded value into 'which' and add 2 to get the index. - int which = -1; - - // Unnamed type local to function or class. - if (ParseTwoCharToken(state, "Ut") && Optional(ParseNumber(state, &which)) && - which <= std::numeric_limits<int>::max() - 2 && // Don't overflow. - ParseOneCharToken(state, '_')) { - MaybeAppend(state, "{unnamed type#"); - MaybeAppendDecimal(state, 2 + which); - MaybeAppend(state, "}"); - return true; - } - state->parse_state = copy; - - // Closure type. - which = -1; - if (ParseTwoCharToken(state, "Ul") && DisableAppend(state) && - OneOrMore(ParseType, state) && RestoreAppend(state, copy.append) && - ParseOneCharToken(state, 'E') && Optional(ParseNumber(state, &which)) && - which <= std::numeric_limits<int>::max() - 2 && // Don't overflow. - ParseOneCharToken(state, '_')) { - MaybeAppend(state, "{lambda()#"); - MaybeAppendDecimal(state, 2 + which); - MaybeAppend(state, "}"); - return true; - } - state->parse_state = copy; - - return false; -} - -// <number> ::= [n] <non-negative decimal integer> -// If "number_out" is non-null, then *number_out is set to the value of the -// parsed number on success. -static bool ParseNumber(State *state, int *number_out) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - bool negative = false; - if (ParseOneCharToken(state, 'n')) { - negative = true; - } - const char *p = RemainingInput(state); - uint64_t number = 0; - for (; *p != '\0'; ++p) { - if (IsDigit(*p)) { - number = number * 10 + (*p - '0'); - } else { - break; - } - } - // Apply the sign with uint64_t arithmetic so overflows aren't UB. Gives - // "incorrect" results for out-of-range inputs, but negative values only - // appear for literals, which aren't printed. - if (negative) { - number = ~number + 1; - } - if (p != RemainingInput(state)) { // Conversion succeeded. - state->parse_state.mangled_idx += p - RemainingInput(state); - if (number_out != nullptr) { - // Note: possibly truncate "number". - *number_out = number; - } - return true; - } - return false; -} - -// Floating-point literals are encoded using a fixed-length lowercase -// hexadecimal string. -static bool ParseFloatNumber(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - const char *p = RemainingInput(state); - for (; *p != '\0'; ++p) { - if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) { - break; - } - } - if (p != RemainingInput(state)) { // Conversion succeeded. - state->parse_state.mangled_idx += p - RemainingInput(state); - return true; - } - return false; -} - -// The <seq-id> is a sequence number in base 36, -// using digits and upper case letters -static bool ParseSeqId(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - const char *p = RemainingInput(state); - for (; *p != '\0'; ++p) { - if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) { - break; - } - } - if (p != RemainingInput(state)) { // Conversion succeeded. - state->parse_state.mangled_idx += p - RemainingInput(state); - return true; - } - return false; -} - -// <identifier> ::= <unqualified source code identifier> (of given length) -static bool ParseIdentifier(State *state, int length) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (length < 0 || !AtLeastNumCharsRemaining(RemainingInput(state), length)) { - return false; - } - if (IdentifierIsAnonymousNamespace(state, length)) { - MaybeAppend(state, "(anonymous namespace)"); - } else { - MaybeAppendWithLength(state, RemainingInput(state), length); - } - state->parse_state.mangled_idx += length; - return true; -} - -// <operator-name> ::= nw, and other two letters cases -// ::= cv <type> # (cast) -// ::= v <digit> <source-name> # vendor extended operator -static bool ParseOperatorName(State *state, int *arity) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (!AtLeastNumCharsRemaining(RemainingInput(state), 2)) { - return false; - } - // First check with "cv" (cast) case. - ParseState copy = state->parse_state; - if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") && - EnterNestedName(state) && ParseType(state) && - LeaveNestedName(state, copy.nest_level)) { - if (arity != nullptr) { - *arity = 1; - } - return true; - } - state->parse_state = copy; - - // Then vendor extended operators. - if (ParseOneCharToken(state, 'v') && ParseDigit(state, arity) && - ParseSourceName(state)) { - return true; - } - state->parse_state = copy; - - // Other operator names should start with a lower alphabet followed - // by a lower/upper alphabet. - if (!(IsLower(RemainingInput(state)[0]) && - IsAlpha(RemainingInput(state)[1]))) { - return false; - } - // We may want to perform a binary search if we really need speed. - const AbbrevPair *p; - for (p = kOperatorList; p->abbrev != nullptr; ++p) { - if (RemainingInput(state)[0] == p->abbrev[0] && - RemainingInput(state)[1] == p->abbrev[1]) { - if (arity != nullptr) { - *arity = p->arity; - } - MaybeAppend(state, "operator"); - if (IsLower(*p->real_name)) { // new, delete, etc. - MaybeAppend(state, " "); - } - MaybeAppend(state, p->real_name); - state->parse_state.mangled_idx += 2; - return true; - } - } - return false; -} - -// <special-name> ::= TV <type> -// ::= 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> -// G++ extensions: -// ::= TC <type> <(offset) number> _ <(base) type> -// ::= TF <type> -// ::= TJ <type> -// ::= GR <name> -// ::= GA <encoding> -// ::= Th <call-offset> <(base) encoding> -// ::= Tv <call-offset> <(base) encoding> -// -// Note: we don't care much about them since they don't appear in -// stack traces. The are special data. -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") && - ParseType(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) && - ParseCallOffset(state) && ParseEncoding(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "GV") && ParseName(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) && - ParseEncoding(state)) { - return true; - } - state->parse_state = copy; - - // G++ extensions - if (ParseTwoCharToken(state, "TC") && ParseType(state) && - ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') && - DisableAppend(state) && ParseType(state)) { - RestoreAppend(state, copy.append); - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") && - ParseType(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "GR") && ParseName(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") && - ParseCallOffset(state) && ParseEncoding(state)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <call-offset> ::= h <nv-offset> _ -// ::= v <v-offset> _ -static bool ParseCallOffset(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'h') && ParseNVOffset(state) && - ParseOneCharToken(state, '_')) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'v') && ParseVOffset(state) && - ParseOneCharToken(state, '_')) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <nv-offset> ::= <(offset) number> -static bool ParseNVOffset(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - return ParseNumber(state, nullptr); -} - -// <v-offset> ::= <(offset) number> _ <(virtual offset) number> -static bool ParseVOffset(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') && - ParseNumber(state, nullptr)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2 -// <base-class-type> -// ::= D0 | D1 | D2 -// # GCC extensions: "unified" constructor/destructor. See -// # -// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847 -// ::= 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; - } - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "0124")) { - const char *const prev_name = state->out + state->parse_state.prev_name_idx; - MaybeAppend(state, "~"); - MaybeAppendWithLength(state, prev_name, - state->parse_state.prev_name_length); - return true; - } - state->parse_state = copy; - return false; -} - -// <decltype> ::= Dt <expression> E # decltype of an id-expression or class -// # member access (C++0x) -// ::= DT <expression> E # decltype of an expression (C++0x) -static bool ParseDecltype(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") && - ParseExpression(state) && ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <type> ::= <CV-qualifiers> <type> -// ::= P <type> # pointer-to -// ::= R <type> # reference-to -// ::= O <type> # rvalue reference-to (C++0x) -// ::= C <type> # complex pair (C 2000) -// ::= G <type> # imaginary (C 2000) -// ::= U <source-name> <type> # vendor extended type qualifier -// ::= <builtin-type> -// ::= <function-type> -// ::= <class-enum-type> # note: just an alias for <name> -// ::= <array-type> -// ::= <pointer-to-member-type> -// ::= <template-template-param> <template-args> -// ::= <template-param> -// ::= <decltype> -// ::= <substitution> -// ::= Dp <type> # pack expansion of (C++0x) -// ::= Dv <num-elems> _ # GNU vector extension -// -static bool ParseType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - - // We should check CV-qualifers, and PRGC things first. - // - // CV-qualifiers overlap with some operator names, but an operator name is not - // valid as a type. To avoid an ambiguity that can lead to exponential time - // complexity, refuse to backtrack the CV-qualifiers. - // - // _Z4aoeuIrMvvE - // => _Z 4aoeuI rM v v E - // aoeu<operator%=, void, void> - // => _Z 4aoeuI r Mv v E - // aoeu<void void::* restrict> - // - // By consuming the CV-qualifiers first, the former parse is disabled. - if (ParseCVQualifiers(state)) { - const bool result = ParseType(state); - if (!result) state->parse_state = copy; - return result; - } - state->parse_state = copy; - - // Similarly, these tag characters can overlap with other <name>s resulting in - // two different parse prefixes that land on <template-args> in the same - // place, such as "C3r1xI...". So, disable the "ctor-name = C3" parse by - // refusing to backtrack the tag characters. - if (ParseCharClass(state, "OPRCG")) { - const bool result = ParseType(state); - if (!result) state->parse_state = copy; - return result; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "Dp") && ParseType(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && - ParseType(state)) { - return true; - } - state->parse_state = copy; - - if (ParseBuiltinType(state) || ParseFunctionType(state) || - ParseClassEnumType(state) || ParseArrayType(state) || - ParsePointerToMemberType(state) || ParseDecltype(state) || - // "std" on its own isn't a type. - ParseSubstitution(state, /*accept_std=*/false)) { - return true; - } - - if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) { - return true; - } - state->parse_state = copy; - - // Less greedy than <template-template-param> <template-args>. - if (ParseTemplateParam(state)) { - return true; - } - - if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) && - ParseOneCharToken(state, '_')) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <CV-qualifiers> ::= [r] [V] [K] -// We don't allow empty <CV-qualifiers> to avoid infinite loop in -// ParseType(). -static bool ParseCVQualifiers(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - int num_cv_qualifiers = 0; - num_cv_qualifiers += ParseOneCharToken(state, 'r'); - num_cv_qualifiers += ParseOneCharToken(state, 'V'); - num_cv_qualifiers += ParseOneCharToken(state, 'K'); - return num_cv_qualifiers > 0; -} - -// <builtin-type> ::= v, etc. # single-character builtin types -// ::= u <source-name> -// ::= Dd, etc. # two-character builtin types -// -// Not supported: -// ::= DF <number> _ # _FloatN (N bits) -// -static bool ParseBuiltinType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - const AbbrevPair *p; - for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { - // Guaranteed only 1- or 2-character strings in kBuiltinTypeList. - if (p->abbrev[1] == '\0') { - if (ParseOneCharToken(state, p->abbrev[0])) { - MaybeAppend(state, p->real_name); - return true; - } - } else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) { - MaybeAppend(state, p->real_name); - return true; - } - } - - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) { - return true; - } - state->parse_state = copy; - 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 -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') && - Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) && - Optional(ParseOneCharToken(state, 'O')) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - return false; -} - -// <bare-function-type> ::= <(signature) type>+ -static bool ParseBareFunctionType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - DisableAppend(state); - if (OneOrMore(ParseType, state)) { - RestoreAppend(state, copy.append); - MaybeAppend(state, "()"); - return true; - } - state->parse_state = copy; - return false; -} - -// <class-enum-type> ::= <name> -static bool ParseClassEnumType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - return ParseName(state); -} - -// <array-type> ::= A <(positive dimension) number> _ <(element) type> -// ::= A [<(dimension) expression>] _ <(element) type> -static bool ParseArrayType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'A') && ParseNumber(state, nullptr) && - ParseOneCharToken(state, '_') && ParseType(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) && - ParseOneCharToken(state, '_') && ParseType(state)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <pointer-to-member-type> ::= M <(class) type> <(member) type> -static bool ParsePointerToMemberType(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'M') && ParseType(state) && ParseType(state)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <template-param> ::= T_ -// ::= T <parameter-2 non-negative number> _ -static bool ParseTemplateParam(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseTwoCharToken(state, "T_")) { - MaybeAppend(state, "?"); // We don't support template substitutions. - return true; - } - - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'T') && ParseNumber(state, nullptr) && - ParseOneCharToken(state, '_')) { - MaybeAppend(state, "?"); // We don't support template substitutions. - return true; - } - state->parse_state = copy; - return false; -} - -// <template-template-param> ::= <template-param> -// ::= <substitution> -static bool ParseTemplateTemplateParam(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - return (ParseTemplateParam(state) || - // "std" on its own isn't a template. - ParseSubstitution(state, /*accept_std=*/false)); -} - -// <template-args> ::= I <template-arg>+ E -static bool ParseTemplateArgs(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - DisableAppend(state); - if (ParseOneCharToken(state, 'I') && OneOrMore(ParseTemplateArg, state) && - ParseOneCharToken(state, 'E')) { - RestoreAppend(state, copy.append); - MaybeAppend(state, "<>"); - return true; - } - state->parse_state = copy; - return false; -} - -// <template-arg> ::= <type> -// ::= <expr-primary> -// ::= J <template-arg>* E # argument pack -// ::= X <expression> E -static bool ParseTemplateArg(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'J') && ZeroOrMore(ParseTemplateArg, state) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - - // There can be significant overlap between the following leading to - // exponential backtracking: - // - // <expr-primary> ::= L <type> <expr-cast-value> E - // e.g. L 2xxIvE 1 E - // <type> ==> <local-source-name> <template-args> - // e.g. L 2xx IvE - // - // This means parsing an entire <type> twice, and <type> can contain - // <template-arg>, so this can generate exponential backtracking. There is - // only overlap when the remaining input starts with "L <source-name>", so - // parse all cases that can start this way jointly to share the common prefix. - // - // We have: - // - // <template-arg> ::= <type> - // ::= <expr-primary> - // - // First, drop all the productions of <type> that must start with something - // other than 'L'. All that's left is <class-enum-type>; inline it. - // - // <type> ::= <nested-name> # starts with 'N' - // ::= <unscoped-name> - // ::= <unscoped-template-name> <template-args> - // ::= <local-name> # starts with 'Z' - // - // Drop and inline again: - // - // <type> ::= <unscoped-name> - // ::= <unscoped-name> <template-args> - // ::= <substitution> <template-args> # starts with 'S' - // - // Merge the first two, inline <unscoped-name>, drop last: - // - // <type> ::= <unqualified-name> [<template-args>] - // ::= St <unqualified-name> [<template-args>] # starts with 'S' - // - // Drop and inline: - // - // <type> ::= <operator-name> [<template-args>] # starts with lowercase - // ::= <ctor-dtor-name> [<template-args>] # starts with 'C' or 'D' - // ::= <source-name> [<template-args>] # starts with digit - // ::= <local-source-name> [<template-args>] - // ::= <unnamed-type-name> [<template-args>] # starts with 'U' - // - // One more time: - // - // <type> ::= L <source-name> [<template-args>] - // - // Likewise with <expr-primary>: - // - // <expr-primary> ::= L <type> <expr-cast-value> E - // ::= LZ <encoding> E # cannot overlap; drop - // ::= L <mangled_name> E # cannot overlap; drop - // - // By similar reasoning as shown above, the only <type>s starting with - // <source-name> are "<source-name> [<template-args>]". Inline this. - // - // <expr-primary> ::= L <source-name> [<template-args>] <expr-cast-value> E - // - // Now inline both of these into <template-arg>: - // - // <template-arg> ::= L <source-name> [<template-args>] - // ::= L <source-name> [<template-args>] <expr-cast-value> E - // - // Merge them and we're done: - // <template-arg> - // ::= L <source-name> [<template-args>] [<expr-cast-value> E] - if (ParseLocalSourceName(state) && Optional(ParseTemplateArgs(state))) { - copy = state->parse_state; - if (ParseExprCastValue(state) && ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - return true; - } - - // Now that the overlapping cases can't reach this code, we can safely call - // both of these. - if (ParseType(state) || ParseExprPrimary(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'X') && ParseExpression(state) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - return false; -} - -// <unresolved-type> ::= <template-param> [<template-args>] -// ::= <decltype> -// ::= <substitution> -static inline bool ParseUnresolvedType(State *state) { - // No ComplexityGuard because we don't copy the state in this stack frame. - return (ParseTemplateParam(state) && Optional(ParseTemplateArgs(state))) || - ParseDecltype(state) || ParseSubstitution(state, /*accept_std=*/false); -} - -// <simple-id> ::= <source-name> [<template-args>] -static inline bool ParseSimpleId(State *state) { - // No ComplexityGuard because we don't copy the state in this stack frame. - - // Note: <simple-id> cannot be followed by a parameter pack; see comment in - // ParseUnresolvedType. - return ParseSourceName(state) && Optional(ParseTemplateArgs(state)); -} - -// <base-unresolved-name> ::= <source-name> [<template-args>] -// ::= on <operator-name> [<template-args>] -// ::= dn <destructor-name> -static bool ParseBaseUnresolvedName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - - if (ParseSimpleId(state)) { - return true; - } - - ParseState copy = state->parse_state; - if (ParseTwoCharToken(state, "on") && ParseOperatorName(state, nullptr) && - Optional(ParseTemplateArgs(state))) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "dn") && - (ParseUnresolvedType(state) || ParseSimpleId(state))) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <unresolved-name> ::= [gs] <base-unresolved-name> -// ::= sr <unresolved-type> <base-unresolved-name> -// ::= srN <unresolved-type> <unresolved-qualifier-level>+ E -// <base-unresolved-name> -// ::= [gs] sr <unresolved-qualifier-level>+ E -// <base-unresolved-name> -static bool ParseUnresolvedName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - - ParseState copy = state->parse_state; - if (Optional(ParseTwoCharToken(state, "gs")) && - ParseBaseUnresolvedName(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "sr") && ParseUnresolvedType(state) && - ParseBaseUnresolvedName(state)) { - return true; - } - state->parse_state = copy; - - if (ParseTwoCharToken(state, "sr") && ParseOneCharToken(state, 'N') && - ParseUnresolvedType(state) && - OneOrMore(/* <unresolved-qualifier-level> ::= */ ParseSimpleId, state) && - ParseOneCharToken(state, 'E') && ParseBaseUnresolvedName(state)) { - return true; - } - state->parse_state = copy; - - if (Optional(ParseTwoCharToken(state, "gs")) && - ParseTwoCharToken(state, "sr") && - OneOrMore(/* <unresolved-qualifier-level> ::= */ ParseSimpleId, state) && - ParseOneCharToken(state, 'E') && ParseBaseUnresolvedName(state)) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <expression> ::= <1-ary operator-name> <expression> -// ::= <2-ary operator-name> <expression> <expression> -// ::= <3-ary operator-name> <expression> <expression> <expression> -// ::= cl <expression>+ E -// ::= cv <type> <expression> # type (expression) -// ::= cv <type> _ <expression>* E # type (expr-list) -// ::= st <type> -// ::= <template-param> -// ::= <function-param> -// ::= <expr-primary> -// ::= dt <expression> <unresolved-name> # expr.name -// ::= pt <expression> <unresolved-name> # expr->name -// ::= sp <expression> # argument pack expansion -// ::= sr <type> <unqualified-name> <template-args> -// ::= sr <type> <unqualified-name> -// <function-param> ::= fp <(top-level) CV-qualifiers> _ -// ::= fp <(top-level) CV-qualifiers> <number> _ -// ::= fL <number> p <(top-level) CV-qualifiers> _ -// ::= fL <number> p <(top-level) CV-qualifiers> <number> _ -static bool ParseExpression(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseTemplateParam(state) || ParseExprPrimary(state)) { - return true; - } - - // 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; - - // Function-param expression (level 0). - if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) && - Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) { - return true; - } - state->parse_state = copy; - - // Function-param expression (level 1+). - if (ParseTwoCharToken(state, "fL") && Optional(ParseNumber(state, nullptr)) && - ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) && - Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) { - return true; - } - state->parse_state = copy; - - // Parse the conversion expressions jointly to avoid re-parsing the <type> in - // their common prefix. Parsed as: - // <expression> ::= cv <type> <conversion-args> - // <conversion-args> ::= _ <expression>* E - // ::= <expression> - // - // Also don't try ParseOperatorName after seeing "cv", since ParseOperatorName - // also needs to accept "cv <type>" in other contexts. - if (ParseTwoCharToken(state, "cv")) { - if (ParseType(state)) { - ParseState copy2 = state->parse_state; - if (ParseOneCharToken(state, '_') && ZeroOrMore(ParseExpression, state) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy2; - if (ParseExpression(state)) { - return true; - } - } - } else { - // Parse unary, binary, and ternary operator expressions jointly, taking - // care not to re-parse subexpressions repeatedly. Parse like: - // <expression> ::= <operator-name> <expression> - // [<one-to-two-expressions>] - // <one-to-two-expressions> ::= <expression> [<expression>] - int arity = -1; - if (ParseOperatorName(state, &arity) && - arity > 0 && // 0 arity => disabled. - (arity < 3 || ParseExpression(state)) && - (arity < 2 || ParseExpression(state)) && - (arity < 1 || ParseExpression(state))) { - return true; - } - } - state->parse_state = copy; - - // sizeof type - if (ParseTwoCharToken(state, "st") && ParseType(state)) { - return true; - } - state->parse_state = copy; - - // Object and pointer member access expressions. - if ((ParseTwoCharToken(state, "dt") || ParseTwoCharToken(state, "pt")) && - ParseExpression(state) && ParseType(state)) { - return true; - } - state->parse_state = copy; - - // Pointer-to-member access expressions. This parses the same as a binary - // operator, but it's implemented separately because "ds" shouldn't be - // accepted in other contexts that parse an operator name. - if (ParseTwoCharToken(state, "ds") && ParseExpression(state) && - ParseExpression(state)) { - return true; - } - state->parse_state = copy; - - // Parameter pack expansion - if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) { - return true; - } - state->parse_state = copy; - - return ParseUnresolvedName(state); -} - -// <expr-primary> ::= L <type> <(value) number> E -// ::= L <type> <(value) float> E -// ::= L <mangled-name> E -// // A bug in g++'s C++ ABI version 2 (-fabi-version=2). -// ::= LZ <encoding> E -// -// Warning, subtle: the "bug" LZ production above is ambiguous with the first -// production where <type> starts with <local-name>, which can lead to -// exponential backtracking in two scenarios: -// -// - When whatever follows the E in the <local-name> in the first production is -// not a name, we backtrack the whole <encoding> and re-parse the whole thing. -// -// - When whatever follows the <local-name> in the first production is not a -// number and this <expr-primary> may be followed by a name, we backtrack the -// <name> and re-parse it. -// -// Moreover this ambiguity isn't always resolved -- for example, the following -// has two different parses: -// -// _ZaaILZ4aoeuE1x1EvE -// => operator&&<aoeu, x, E, void> -// => operator&&<(aoeu::x)(1), void> -// -// To resolve this, we just do what GCC's demangler does, and refuse to parse -// casts to <local-name> types. -static bool ParseExprPrimary(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - - // The "LZ" special case: if we see LZ, we commit to accept "LZ <encoding> E" - // or fail, no backtracking. - if (ParseTwoCharToken(state, "LZ")) { - if (ParseEncoding(state) && ParseOneCharToken(state, 'E')) { - return true; - } - - state->parse_state = copy; - return false; - } - - // The merged cast production. - if (ParseOneCharToken(state, 'L') && ParseType(state) && - ParseExprCastValue(state)) { - return true; - } - state->parse_state = copy; - - if (ParseOneCharToken(state, 'L') && ParseMangledName(state) && - ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <number> or <float>, followed by 'E', as described above ParseExprPrimary. -static bool ParseExprCastValue(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - // We have to be able to backtrack after accepting a number because we could - // have e.g. "7fffE", which will accept "7" as a number but then fail to find - // the 'E'. - ParseState copy = state->parse_state; - if (ParseNumber(state, nullptr) && ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - - if (ParseFloatNumber(state) && ParseOneCharToken(state, 'E')) { - return true; - } - state->parse_state = copy; - - return false; -} - -// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] -// ::= Z <(function) encoding> E s [<discriminator>] -// -// Parsing a common prefix of these two productions together avoids an -// exponential blowup of backtracking. Parse like: -// <local-name> := Z <encoding> E <local-name-suffix> -// <local-name-suffix> ::= s [<discriminator>] -// ::= <name> [<discriminator>] - -static bool ParseLocalNameSuffix(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - - if (MaybeAppend(state, "::") && ParseName(state) && - Optional(ParseDiscriminator(state))) { - return true; - } - - // Since we're not going to overwrite the above "::" by re-parsing the - // <encoding> (whose trailing '\0' byte was in the byte now holding the - // first ':'), we have to rollback the "::" if the <name> parse failed. - if (state->parse_state.append) { - state->out[state->parse_state.out_cur_idx - 2] = '\0'; - } - - return ParseOneCharToken(state, 's') && Optional(ParseDiscriminator(state)); -} - -static bool ParseLocalName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) && - ParseOneCharToken(state, 'E') && ParseLocalNameSuffix(state)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <discriminator> := _ <(non-negative) number> -static bool ParseDiscriminator(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr)) { - return true; - } - state->parse_state = copy; - return false; -} - -// <substitution> ::= S_ -// ::= S <seq-id> _ -// ::= St, etc. -// -// "St" is special in that it's not valid as a standalone name, and it *is* -// allowed to precede a name without being wrapped in "N...E". This means that -// if we accept it on its own, we can accept "St1a" and try to parse -// template-args, then fail and backtrack, accept "St" on its own, then "1a" as -// an unqualified name and re-parse the same template-args. To block this -// exponential backtracking, we disable it with 'accept_std=false' in -// problematic contexts. -static bool ParseSubstitution(State *state, bool accept_std) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseTwoCharToken(state, "S_")) { - MaybeAppend(state, "?"); // We don't support substitutions. - return true; - } - - ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'S') && ParseSeqId(state) && - ParseOneCharToken(state, '_')) { - MaybeAppend(state, "?"); // We don't support substitutions. - return true; - } - state->parse_state = copy; - - // Expand abbreviations like "St" => "std". - if (ParseOneCharToken(state, 'S')) { - const AbbrevPair *p; - for (p = kSubstitutionList; p->abbrev != nullptr; ++p) { - if (RemainingInput(state)[0] == p->abbrev[1] && - (accept_std || p->abbrev[1] != 't')) { - MaybeAppend(state, "std"); - if (p->real_name[0] != '\0') { - MaybeAppend(state, "::"); - MaybeAppend(state, p->real_name); - } - ++state->parse_state.mangled_idx; - return true; - } - } - } - state->parse_state = copy; - return false; -} - -// Parse <mangled-name>, optionally followed by either a function-clone suffix -// or version suffix. Returns true only if all of "mangled_cur" was consumed. -static bool ParseTopLevelMangledName(State *state) { - ComplexityGuard guard(state); - if (guard.IsTooComplex()) return false; - if (ParseMangledName(state)) { - if (RemainingInput(state)[0] != '\0') { - // Drop trailing function clone suffix, if any. - if (IsFunctionCloneSuffix(RemainingInput(state))) { - return true; - } - // Append trailing version suffix if any. - // ex. _Z3foo@@GLIBCXX_3.4 - if (RemainingInput(state)[0] == '@') { - MaybeAppend(state, RemainingInput(state)); - return true; - } - return false; // Unconsumed suffix. - } - return true; - } - return false; -} - -static bool Overflowed(const State *state) { - return state->parse_state.out_cur_idx >= state->out_end_idx; -} - -// The demangler entry point. -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; -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/debugging/internal/demangle.h b/third_party/abseil_cpp/absl/debugging/internal/demangle.h deleted file mode 100644 index c314d9bc237c..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/demangle.h +++ /dev/null @@ -1,71 +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. - -// An async-signal-safe and thread-safe demangler for Itanium C++ ABI -// (aka G++ V3 ABI). -// -// The demangler is implemented to be used in async signal handlers to -// symbolize stack traces. We cannot use libstdc++'s -// abi::__cxa_demangle() in such signal handlers since it's not async -// signal safe (it uses malloc() internally). -// -// Note that this demangler doesn't support full demangling. More -// specifically, it doesn't print types of function parameters and -// types of template arguments. It just skips them. However, it's -// still very useful to extract basic information such as class, -// function, constructor, destructor, and operator names. -// -// See the implementation note in demangle.cc if you are interested. -// -// Example: -// -// | Mangled Name | The Demangler | abi::__cxa_demangle() -// |---------------|---------------|----------------------- -// | _Z1fv | f() | f() -// | _Z1fi | f() | f(int) -// | _Z3foo3bar | foo() | foo(bar) -// | _Z1fIiEvi | f<>() | void f<int>(int) -// | _ZN1N1fE | N::f | N::f -// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar() -// | _Zrm1XS_" | operator%() | operator%(X, X) -// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo() -// | _Z1fSs | f() | f(std::basic_string<char, -// | | | std::char_traits<char>, -// | | | std::allocator<char> >) -// -// See the unit test for more examples. -// -// Note: we might want to write demanglers for ABIs other than Itanium -// C++ ABI in the future. -// - -#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ -#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Demangle `mangled`. On success, return true and write the -// demangled symbol name to `out`. Otherwise, return false. -// `out` is modified even if demangling is unsuccessful. -bool Demangle(const char *mangled, char *out, int out_size); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/demangle_test.cc b/third_party/abseil_cpp/absl/debugging/internal/demangle_test.cc deleted file mode 100644 index 0bed7359d8b4..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/demangle_test.cc +++ /dev/null @@ -1,197 +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/debugging/internal/demangle.h" - -#include <cstdlib> -#include <string> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/internal/stack_consumption.h" -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -namespace { - -// A wrapper function for Demangle() to make the unit test simple. -static const char *DemangleIt(const char * const mangled) { - static char demangled[4096]; - if (Demangle(mangled, demangled, sizeof(demangled))) { - return demangled; - } else { - return mangled; - } -} - -// Test corner cases of bounary conditions. -TEST(Demangle, CornerCases) { - char tmp[10]; - EXPECT_TRUE(Demangle("_Z6foobarv", tmp, sizeof(tmp))); - // sizeof("foobar()") == 9 - EXPECT_STREQ("foobar()", tmp); - EXPECT_TRUE(Demangle("_Z6foobarv", tmp, 9)); - EXPECT_STREQ("foobar()", tmp); - EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 8)); // Not enough. - EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 1)); - EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 0)); - EXPECT_FALSE(Demangle("_Z6foobarv", nullptr, 0)); // Should not cause SEGV. - EXPECT_FALSE(Demangle("_Z1000000", tmp, 9)); -} - -// Test handling of functions suffixed with .clone.N, which is used -// by GCC 4.5.x (and our locally-modified version of GCC 4.4.x), and -// .constprop.N and .isra.N, which are used by GCC 4.6.x. These -// suffixes are used to indicate functions which have been cloned -// during optimization. We ignore these suffixes. -TEST(Demangle, Clones) { - char tmp[20]; - EXPECT_TRUE(Demangle("_ZL3Foov", tmp, sizeof(tmp))); - EXPECT_STREQ("Foo()", tmp); - EXPECT_TRUE(Demangle("_ZL3Foov.clone.3", tmp, sizeof(tmp))); - EXPECT_STREQ("Foo()", tmp); - EXPECT_TRUE(Demangle("_ZL3Foov.constprop.80", tmp, sizeof(tmp))); - EXPECT_STREQ("Foo()", tmp); - EXPECT_TRUE(Demangle("_ZL3Foov.isra.18", tmp, sizeof(tmp))); - EXPECT_STREQ("Foo()", tmp); - EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp))); - EXPECT_STREQ("Foo()", tmp); - // Invalid (truncated), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp))); - // 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))); -} - -// 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) - -static const char *g_mangled; -static char g_demangle_buffer[4096]; -static char *g_demangle_result; - -static void DemangleSignalHandler(int signo) { - if (Demangle(g_mangled, g_demangle_buffer, sizeof(g_demangle_buffer))) { - g_demangle_result = g_demangle_buffer; - } else { - g_demangle_result = nullptr; - } -} - -// Call Demangle and figure out the stack footprint of this call. -static const char *DemangleStackConsumption(const char *mangled, - int *stack_consumed) { - g_mangled = mangled; - *stack_consumed = GetSignalHandlerStackConsumption(DemangleSignalHandler); - ABSL_RAW_LOG(INFO, "Stack consumption of Demangle: %d", *stack_consumed); - return g_demangle_result; -} - -// Demangle stack consumption should be within 8kB for simple mangled names -// with some level of nesting. With alternate signal stack we have 64K, -// but some signal handlers run on thread stack, and could have arbitrarily -// little space left (so we don't want to make this number too large). -const int kStackConsumptionUpperLimit = 8192; - -// Returns a mangled name nested to the given depth. -static std::string NestedMangledName(int depth) { - std::string mangled_name = "_Z1a"; - if (depth > 0) { - mangled_name += "IXL"; - mangled_name += NestedMangledName(depth - 1); - mangled_name += "EEE"; - } - return mangled_name; -} - -TEST(Demangle, DemangleStackConsumption) { - // Measure stack consumption of Demangle for nested mangled names of varying - // depth. Since Demangle is implemented as a recursive descent parser, - // stack consumption will grow as the nesting depth increases. By measuring - // the stack consumption for increasing depths, we can see the growing - // impact of any stack-saving changes made to the code for Demangle. - int stack_consumed = 0; - - const char *demangled = - DemangleStackConsumption("_Z6foobarv", &stack_consumed); - EXPECT_STREQ("foobar()", demangled); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); - - const std::string nested_mangled_name0 = NestedMangledName(0); - demangled = DemangleStackConsumption(nested_mangled_name0.c_str(), - &stack_consumed); - EXPECT_STREQ("a", demangled); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); - - const std::string nested_mangled_name1 = NestedMangledName(1); - demangled = DemangleStackConsumption(nested_mangled_name1.c_str(), - &stack_consumed); - EXPECT_STREQ("a<>", demangled); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); - - const std::string nested_mangled_name2 = NestedMangledName(2); - demangled = DemangleStackConsumption(nested_mangled_name2.c_str(), - &stack_consumed); - EXPECT_STREQ("a<>", demangled); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); - - const std::string nested_mangled_name3 = NestedMangledName(3); - demangled = DemangleStackConsumption(nested_mangled_name3.c_str(), - &stack_consumed); - EXPECT_STREQ("a<>", demangled); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); -} - -#endif // Stack consumption tests - -static void TestOnInput(const char* input) { - static const int kOutSize = 1048576; - auto out = absl::make_unique<char[]>(kOutSize); - Demangle(input, out.get(), kOutSize); -} - -TEST(DemangleRegression, NegativeLength) { - TestOnInput("_ZZn4"); -} - -TEST(DemangleRegression, DeeplyNestedArrayType) { - const int depth = 100000; - std::string data = "_ZStI"; - data.reserve(data.size() + 3 * depth + 1); - for (int i = 0; i < depth; i++) { - data += "A1_"; - } - TestOnInput(data.c_str()); -} - -} // namespace -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 24cc01302dc5..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/elf_mem_image.cc +++ /dev/null @@ -1,382 +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. - -// Allow dynamic symbol lookup in an in-memory Elf image. -// - -#include "absl/debugging/internal/elf_mem_image.h" - -#ifdef ABSL_HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h - -#include <string.h> -#include <cassert> -#include <cstddef> -#include "absl/base/internal/raw_logging.h" - -// From binutils/include/elf/common.h (this doesn't appear to be documented -// anywhere else). -// -// /* This flag appears in a Versym structure. It means that the symbol -// is hidden, and is only visible with an explicit version number. -// This is a GNU extension. */ -// #define VERSYM_HIDDEN 0x8000 -// -// /* This is the mask for the rest of the Versym information. */ -// #define VERSYM_VERSION 0x7fff - -#define VERSYM_VERSION 0x7fff - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -namespace { - -#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 __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); } -#else -const int kElfClass = -1; -int ElfBind(const ElfW(Sym) *) { - ABSL_RAW_LOG(FATAL, "Unexpected word size"); - return 0; -} -int ElfType(const ElfW(Sym) *) { - ABSL_RAW_LOG(FATAL, "Unexpected word size"); - return 0; -} -#endif - -// Extract an element from one of the ELF tables, cast it to desired type. -// This is just a simple arithmetic and a glorified cast. -// Callers are responsible for bounds checking. -template <typename T> -const T *GetTableElement(const ElfW(Ehdr) * ehdr, ElfW(Off) table_offset, - ElfW(Word) element_size, size_t index) { - return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr) - + table_offset - + index * element_size); -} - -} // namespace - -// The value of this variable doesn't matter; it's used only for its -// unique address. -const int ElfMemImage::kInvalidBaseSentinel = 0; - -ElfMemImage::ElfMemImage(const void *base) { - ABSL_RAW_CHECK(base != kInvalidBase, "bad pointer"); - Init(base); -} - -int ElfMemImage::GetNumSymbols() const { - if (!hash_) { - return 0; - } - // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash - return hash_[1]; -} - -const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { - ABSL_RAW_CHECK(index < GetNumSymbols(), "index out of range"); - return dynsym_ + index; -} - -const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { - ABSL_RAW_CHECK(index < GetNumSymbols(), "index out of range"); - return versym_ + index; -} - -const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const { - ABSL_RAW_CHECK(index < ehdr_->e_phnum, "index out of range"); - return GetTableElement<ElfW(Phdr)>(ehdr_, - ehdr_->e_phoff, - ehdr_->e_phentsize, - index); -} - -const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const { - ABSL_RAW_CHECK(offset < strsize_, "offset out of range"); - return dynstr_ + offset; -} - -const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { - if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { - // Symbol corresponds to "special" (e.g. SHN_ABS) section. - return reinterpret_cast<const void *>(sym->st_value); - } - ABSL_RAW_CHECK(link_base_ < sym->st_value, "symbol out of range"); - return GetTableElement<char>(ehdr_, 0, 1, sym->st_value - link_base_); -} - -const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const { - ABSL_RAW_CHECK(0 <= index && static_cast<size_t>(index) <= verdefnum_, - "index out of range"); - const ElfW(Verdef) *version_definition = verdef_; - while (version_definition->vd_ndx < index && version_definition->vd_next) { - const char *const version_definition_as_char = - reinterpret_cast<const char *>(version_definition); - version_definition = - reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char + - version_definition->vd_next); - } - return version_definition->vd_ndx == index ? version_definition : nullptr; -} - -const ElfW(Verdaux) *ElfMemImage::GetVerdefAux( - const ElfW(Verdef) *verdef) const { - return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1); -} - -const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const { - ABSL_RAW_CHECK(offset < strsize_, "offset out of range"); - return dynstr_ + offset; -} - -void ElfMemImage::Init(const void *base) { - ehdr_ = nullptr; - dynsym_ = nullptr; - dynstr_ = nullptr; - versym_ = nullptr; - verdef_ = nullptr; - hash_ = nullptr; - strsize_ = 0; - verdefnum_ = 0; - link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. - if (!base) { - return; - } - const char *const base_as_char = reinterpret_cast<const char *>(base); - if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || - base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { - assert(false); - return; - } - int elf_class = base_as_char[EI_CLASS]; - if (elf_class != kElfClass) { - assert(false); - return; - } - switch (base_as_char[EI_DATA]) { - case ELFDATA2LSB: { - if (__LITTLE_ENDIAN != __BYTE_ORDER) { - assert(false); - return; - } - break; - } - case ELFDATA2MSB: { - if (__BIG_ENDIAN != __BYTE_ORDER) { - assert(false); - return; - } - break; - } - default: { - assert(false); - return; - } - } - - ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base); - const ElfW(Phdr) *dynamic_program_header = nullptr; - for (int i = 0; i < ehdr_->e_phnum; ++i) { - const ElfW(Phdr) *const program_header = GetPhdr(i); - switch (program_header->p_type) { - case PT_LOAD: - if (!~link_base_) { - link_base_ = program_header->p_vaddr; - } - break; - case PT_DYNAMIC: - dynamic_program_header = program_header; - break; - } - } - if (!~link_base_ || !dynamic_program_header) { - assert(false); - // Mark this image as not present. Can not recur infinitely. - Init(nullptr); - return; - } - ptrdiff_t relocation = - base_as_char - reinterpret_cast<const char *>(link_base_); - ElfW(Dyn) *dynamic_entry = - reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + - relocation); - for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { - 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); - break; - case DT_SYMTAB: - dynsym_ = reinterpret_cast<ElfW(Sym) *>(value); - break; - case DT_STRTAB: - dynstr_ = reinterpret_cast<const char *>(value); - break; - case DT_VERSYM: - versym_ = reinterpret_cast<ElfW(Versym) *>(value); - break; - case DT_VERDEF: - verdef_ = reinterpret_cast<ElfW(Verdef) *>(value); - break; - case DT_VERDEFNUM: - verdefnum_ = dynamic_entry->d_un.d_val; - break; - case DT_STRSZ: - strsize_ = dynamic_entry->d_un.d_val; - break; - default: - // Unrecognized entries explicitly ignored. - break; - } - } - if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || - !verdef_ || !verdefnum_ || !strsize_) { - assert(false); // invalid VDSO - // Mark this image as not present. Can not recur infinitely. - Init(nullptr); - return; - } -} - -bool ElfMemImage::LookupSymbol(const char *name, - const char *version, - int type, - SymbolInfo *info_out) const { - for (const SymbolInfo& info : *this) { - if (strcmp(info.name, name) == 0 && strcmp(info.version, version) == 0 && - ElfType(info.symbol) == type) { - if (info_out) { - *info_out = info; - } - return true; - } - } - return false; -} - -bool ElfMemImage::LookupSymbolByAddress(const void *address, - SymbolInfo *info_out) const { - for (const SymbolInfo& info : *this) { - const char *const symbol_start = - reinterpret_cast<const char *>(info.address); - const char *const symbol_end = symbol_start + info.symbol->st_size; - if (symbol_start <= address && address < symbol_end) { - if (info_out) { - // Client wants to know details for that symbol (the usual case). - if (ElfBind(info.symbol) == STB_GLOBAL) { - // Strong symbol; just return it. - *info_out = info; - return true; - } else { - // Weak or local. Record it, but keep looking for a strong one. - *info_out = info; - } - } else { - // Client only cares if there is an overlapping symbol. - return true; - } - } - } - return false; -} - -ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) - : index_(index), image_(image) { -} - -const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { - return &info_; -} - -const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const { - return info_; -} - -bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const { - return this->image_ == rhs.image_ && this->index_ == rhs.index_; -} - -bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const { - return !(*this == rhs); -} - -ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() { - this->Update(1); - return *this; -} - -ElfMemImage::SymbolIterator ElfMemImage::begin() const { - SymbolIterator it(this, 0); - it.Update(0); - return it; -} - -ElfMemImage::SymbolIterator ElfMemImage::end() const { - return SymbolIterator(this, GetNumSymbols()); -} - -void ElfMemImage::SymbolIterator::Update(int increment) { - const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_); - ABSL_RAW_CHECK(image->IsPresent() || increment == 0, ""); - if (!image->IsPresent()) { - return; - } - index_ += increment; - if (index_ >= image->GetNumSymbols()) { - index_ = image->GetNumSymbols(); - return; - } - const ElfW(Sym) *symbol = image->GetDynsym(index_); - const ElfW(Versym) *version_symbol = image->GetVersym(index_); - ABSL_RAW_CHECK(symbol && version_symbol, ""); - const char *const symbol_name = image->GetDynstr(symbol->st_name); - const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION; - const ElfW(Verdef) *version_definition = nullptr; - const char *version_name = ""; - if (symbol->st_shndx == SHN_UNDEF) { - // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and - // version_index could well be greater than verdefnum_, so calling - // GetVerdef(version_index) may trigger assertion. - } else { - version_definition = image->GetVerdef(version_index); - } - if (version_definition) { - // I am expecting 1 or 2 auxiliary entries: 1 for the version itself, - // optional 2nd if the version has a parent. - ABSL_RAW_CHECK( - version_definition->vd_cnt == 1 || version_definition->vd_cnt == 2, - "wrong number of entries"); - const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition); - version_name = image->GetVerstr(version_aux->vda_name); - } - info_.name = symbol_name; - info_.version = version_name; - info_.address = image->GetSymAddr(symbol); - info_.symbol = symbol; -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_ELF_MEM_IMAGE 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 deleted file mode 100644 index 46bfade3503e..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/elf_mem_image.h +++ /dev/null @@ -1,134 +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. - */ - -// Allow dynamic symbol lookup for in-memory Elf images. - -#ifndef ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_ -#define ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_ - -// Including this will define the __GLIBC__ macro if glibc is being -// used. -#include <climits> - -#include "absl/base/config.h" - -// Maybe one day we can rewrite this file not to require the elf -// symbol extensions in glibc, but for right now we need them. -#ifdef ABSL_HAVE_ELF_MEM_IMAGE -#error ABSL_HAVE_ELF_MEM_IMAGE cannot be directly set -#endif - -#if defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \ - !defined(__asmjs__) && !defined(__wasm__) -#define ABSL_HAVE_ELF_MEM_IMAGE 1 -#endif - -#ifdef ABSL_HAVE_ELF_MEM_IMAGE - -#include <link.h> // for ElfW - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// An in-memory ELF image (may not exist on disk). -class ElfMemImage { - private: - // Sentinel: there could never be an elf image at &kInvalidBaseSentinel. - static const int kInvalidBaseSentinel; - - public: - // Sentinel: there could never be an elf image at this address. - static constexpr const void *const kInvalidBase = - static_cast<const void*>(&kInvalidBaseSentinel); - - // Information about a single vdso symbol. - // All pointers are into .dynsym, .dynstr, or .text of the VDSO. - // Do not free() them or modify through them. - struct SymbolInfo { - const char *name; // E.g. "__vdso_getcpu" - const char *version; // E.g. "LINUX_2.6", could be "" - // for unversioned symbol. - const void *address; // Relocated symbol address. - const ElfW(Sym) *symbol; // Symbol in the dynamic symbol table. - }; - - // Supports iteration over all dynamic symbols. - class SymbolIterator { - public: - friend class ElfMemImage; - const SymbolInfo *operator->() const; - const SymbolInfo &operator*() const; - SymbolIterator& operator++(); - bool operator!=(const SymbolIterator &rhs) const; - bool operator==(const SymbolIterator &rhs) const; - private: - SymbolIterator(const void *const image, int index); - void Update(int incr); - SymbolInfo info_; - int index_; - const void *const image_; - }; - - - explicit ElfMemImage(const void *base); - void Init(const void *base); - bool IsPresent() const { return ehdr_ != nullptr; } - const ElfW(Phdr)* GetPhdr(int index) const; - const ElfW(Sym)* GetDynsym(int index) const; - const ElfW(Versym)* GetVersym(int index) const; - const ElfW(Verdef)* GetVerdef(int index) const; - const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const; - const char* GetDynstr(ElfW(Word) offset) const; - const void* GetSymAddr(const ElfW(Sym) *sym) const; - const char* GetVerstr(ElfW(Word) offset) const; - int GetNumSymbols() const; - - SymbolIterator begin() const; - SymbolIterator end() const; - - // Look up versioned dynamic symbol in the image. - // Returns false if image is not present, or doesn't contain given - // symbol/version/type combination. - // If info_out is non-null, additional details are filled in. - bool LookupSymbol(const char *name, const char *version, - int symbol_type, SymbolInfo *info_out) const; - - // Find info about symbol (if any) which overlaps given address. - // Returns true if symbol was found; false if image isn't present - // or doesn't have a symbol overlapping given address. - // If info_out is non-null, additional details are filled in. - bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; - - private: - const ElfW(Ehdr) *ehdr_; - const ElfW(Sym) *dynsym_; - const ElfW(Versym) *versym_; - const ElfW(Verdef) *verdef_; - const ElfW(Word) *hash_; - const char *dynstr_; - size_t strsize_; - size_t verdefnum_; - ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD). -}; - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_ELF_MEM_IMAGE - -#endif // ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/examine_stack.cc b/third_party/abseil_cpp/absl/debugging/internal/examine_stack.cc deleted file mode 100644 index 6e5ff1fbd836..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/examine_stack.cc +++ /dev/null @@ -1,187 +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/debugging/internal/examine_stack.h" - -#ifndef _WIN32 -#include <unistd.h> -#endif - -#ifdef __APPLE__ -#include <sys/ucontext.h> -#endif - -#include <csignal> -#include <cstdio> - -#include "absl/base/attributes.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/symbolize.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Returns the program counter from signal context, nullptr if -// unknown. vuc is a ucontext_t*. We use void* to avoid the use of -// ucontext_t on non-POSIX systems. -void* GetProgramCounter(void* vuc) { -#ifdef __linux__ - if (vuc != nullptr) { - ucontext_t* context = reinterpret_cast<ucontext_t*>(vuc); -#if defined(__aarch64__) - return reinterpret_cast<void*>(context->uc_mcontext.pc); -#elif defined(__arm__) - return reinterpret_cast<void*>(context->uc_mcontext.arm_pc); -#elif defined(__i386__) - if (14 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs)) - return reinterpret_cast<void*>(context->uc_mcontext.gregs[14]); -#elif defined(__mips__) - return reinterpret_cast<void*>(context->uc_mcontext.pc); -#elif defined(__powerpc64__) - return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]); -#elif defined(__powerpc__) - return reinterpret_cast<void*>(context->uc_mcontext.regs->nip); -#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(__x86_64__) - if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs)) - return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]); -#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)); -#endif - static_cast<void>(vuc); - return nullptr; -} - -// The %p field width for printf() functions is two characters per byte, -// and two extra for the leading "0x". -static constexpr int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*); - -// Print a program counter, its stack frame size, and its symbol name. -// Note that there is a separate symbolize_pc argument. Return addresses may be -// at the end of the function, and this allows the caller to back up from pc if -// appropriate. -static void DumpPCAndFrameSizeAndSymbol(void (*writerfn)(const char*, void*), - void* writerfn_arg, void* pc, - void* symbolize_pc, int framesize, - const char* const prefix) { - char tmp[1024]; - const char* symbol = "(unknown)"; - if (absl::Symbolize(symbolize_pc, tmp, sizeof(tmp))) { - symbol = tmp; - } - char buf[1024]; - if (framesize <= 0) { - snprintf(buf, sizeof(buf), "%s@ %*p (unknown) %s\n", prefix, - kPrintfPointerFieldWidth, pc, symbol); - } else { - snprintf(buf, sizeof(buf), "%s@ %*p %9d %s\n", prefix, - kPrintfPointerFieldWidth, pc, framesize, symbol); - } - writerfn(buf, writerfn_arg); -} - -// Print a program counter and the corresponding stack frame size. -static void DumpPCAndFrameSize(void (*writerfn)(const char*, void*), - void* writerfn_arg, void* pc, int framesize, - const char* const prefix) { - char buf[100]; - if (framesize <= 0) { - snprintf(buf, sizeof(buf), "%s@ %*p (unknown)\n", prefix, - kPrintfPointerFieldWidth, pc); - } else { - snprintf(buf, sizeof(buf), "%s@ %*p %9d\n", prefix, - kPrintfPointerFieldWidth, pc, framesize); - } - writerfn(buf, writerfn_arg); -} - -void DumpPCAndFrameSizesAndStackTrace( - void* pc, void* const stack[], int frame_sizes[], int depth, - int min_dropped_frames, bool symbolize_stacktrace, - void (*writerfn)(const char*, void*), void* writerfn_arg) { - if (pc != nullptr) { - // We don't know the stack frame size for PC, use 0. - if (symbolize_stacktrace) { - DumpPCAndFrameSizeAndSymbol(writerfn, writerfn_arg, pc, pc, 0, "PC: "); - } else { - DumpPCAndFrameSize(writerfn, writerfn_arg, pc, 0, "PC: "); - } - } - for (int i = 0; i < depth; i++) { - if (symbolize_stacktrace) { - // Pass the previous address of pc as the symbol address because pc is a - // return address, and an overrun may occur when the function ends with a - // call to a function annotated noreturn (e.g. CHECK). Note that we don't - // do this for pc above, as the adjustment is only correct for return - // addresses. - DumpPCAndFrameSizeAndSymbol(writerfn, writerfn_arg, stack[i], - reinterpret_cast<char*>(stack[i]) - 1, - frame_sizes[i], " "); - } else { - DumpPCAndFrameSize(writerfn, writerfn_arg, stack[i], frame_sizes[i], - " "); - } - } - if (min_dropped_frames > 0) { - char buf[100]; - snprintf(buf, sizeof(buf), " @ ... and at least %d more frames\n", - min_dropped_frames); - writerfn(buf, writerfn_arg); - } -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/debugging/internal/examine_stack.h b/third_party/abseil_cpp/absl/debugging/internal/examine_stack.h deleted file mode 100644 index 393369131f1e..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/examine_stack.h +++ /dev/null @@ -1,42 +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. -// - -#ifndef ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ -#define ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Returns the program counter from signal context, or nullptr if -// unknown. `vuc` is a ucontext_t*. We use void* to avoid the use of -// ucontext_t on non-POSIX systems. -void* GetProgramCounter(void* vuc); - -// Uses `writerfn` to dump the program counter, stack trace, and stack -// frame sizes. -void DumpPCAndFrameSizesAndStackTrace( - void* pc, void* const stack[], int frame_sizes[], int depth, - int min_dropped_frames, bool symbolize_stacktrace, - void (*writerfn)(const char*, void*), void* writerfn_arg); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.cc b/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.cc deleted file mode 100644 index e3dd51c355ad..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.cc +++ /dev/null @@ -1,185 +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/debugging/internal/stack_consumption.h" - -#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION - -#include <signal.h> -#include <sys/mman.h> -#include <unistd.h> - -#include <string.h> - -#include "absl/base/attributes.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -namespace { - -// This code requires that we know the direction in which the stack -// grows. It is commonly believed that this can be detected by putting -// a variable on the stack and then passing its address to a function -// that compares the address of this variable to the address of a -// variable on the function's own stack. However, this is unspecified -// behavior in C++: If two pointers p and q of the same type point to -// different objects that are not members of the same object or -// elements of the same array or to different functions, or if only -// 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__) -constexpr bool kStackGrowsDown = true; -#else -#error Need to define kStackGrowsDown -#endif - -// To measure the stack footprint of some code, we create a signal handler -// (for SIGUSR2 say) that exercises this code on an alternate stack. This -// alternate stack is initialized to some known pattern (0x55, 0x55, 0x55, -// ...). We then self-send this signal, and after the signal handler returns, -// look at the alternate stack buffer to see what portion has been touched. -// -// This trick gives us the the stack footprint of the signal handler. But the -// signal handler, even before the code for it is exercised, consumes some -// stack already. We however only want the stack usage of the code inside the -// signal handler. To measure this accurately, we install two signal handlers: -// one that does nothing and just returns, and the user-provided signal -// handler. The difference between the stack consumption of these two signals -// handlers should give us the stack foorprint of interest. - -void EmptySignalHandler(int) {} - -// This is arbitrary value, and could be increase further, at the cost of -// memset()ting it all to known sentinel value. -constexpr int kAlternateStackSize = 64 << 10; // 64KiB - -constexpr int kSafetyMargin = 32; -constexpr char kAlternateStackFillValue = 0x55; - -// These helper functions look at the alternate stack buffer, and figure -// out what portion of this buffer has been touched - this is the stack -// consumption of the signal handler running on this alternate stack. -// This function will return -1 if the alternate stack buffer has not been -// touched. It will abort the program if the buffer has overflowed or is about -// to overflow. -int GetStackConsumption(const void* const altstack) { - const char* begin; - int increment; - if (kStackGrowsDown) { - begin = reinterpret_cast<const char*>(altstack); - increment = 1; - } else { - begin = reinterpret_cast<const char*>(altstack) + kAlternateStackSize - 1; - increment = -1; - } - - for (int usage_count = kAlternateStackSize; usage_count > 0; --usage_count) { - if (*begin != kAlternateStackFillValue) { - ABSL_RAW_CHECK(usage_count <= kAlternateStackSize - kSafetyMargin, - "Buffer has overflowed or is about to overflow"); - return usage_count; - } - begin += increment; - } - - ABSL_RAW_LOG(FATAL, "Unreachable code"); - return -1; -} - -} // namespace - -int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) { - // The alt-signal-stack cannot be heap allocated because there is a - // bug in glibc-2.2 where some signal handler setup code looks at the - // current stack pointer to figure out what thread is currently running. - // Therefore, the alternate stack must be allocated from the main stack - // itself. - void* altstack = mmap(nullptr, kAlternateStackSize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ABSL_RAW_CHECK(altstack != MAP_FAILED, "mmap() failed"); - - // Set up the alt-signal-stack (and save the older one). - stack_t sigstk; - memset(&sigstk, 0, sizeof(sigstk)); - sigstk.ss_sp = altstack; - sigstk.ss_size = kAlternateStackSize; - sigstk.ss_flags = 0; - stack_t old_sigstk; - memset(&old_sigstk, 0, sizeof(old_sigstk)); - ABSL_RAW_CHECK(sigaltstack(&sigstk, &old_sigstk) == 0, - "sigaltstack() failed"); - - // Set up SIGUSR1 and SIGUSR2 signal handlers (and save the older ones). - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - struct sigaction old_sa1, old_sa2; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_ONSTACK; - - // SIGUSR1 maps to EmptySignalHandler. - sa.sa_handler = EmptySignalHandler; - ABSL_RAW_CHECK(sigaction(SIGUSR1, &sa, &old_sa1) == 0, "sigaction() failed"); - - // SIGUSR2 maps to signal_handler. - sa.sa_handler = signal_handler; - ABSL_RAW_CHECK(sigaction(SIGUSR2, &sa, &old_sa2) == 0, "sigaction() failed"); - - // Send SIGUSR1 signal and measure the stack consumption of the empty - // signal handler. - // The first signal might use more stack space. Run once and ignore the - // results to get that out of the way. - ABSL_RAW_CHECK(kill(getpid(), SIGUSR1) == 0, "kill() failed"); - - memset(altstack, kAlternateStackFillValue, kAlternateStackSize); - ABSL_RAW_CHECK(kill(getpid(), SIGUSR1) == 0, "kill() failed"); - int base_stack_consumption = GetStackConsumption(altstack); - - // Send SIGUSR2 signal and measure the stack consumption of signal_handler. - ABSL_RAW_CHECK(kill(getpid(), SIGUSR2) == 0, "kill() failed"); - int signal_handler_stack_consumption = GetStackConsumption(altstack); - - // Now restore the old alt-signal-stack and signal handlers. - if (old_sigstk.ss_sp == nullptr && old_sigstk.ss_size == 0 && - (old_sigstk.ss_flags & SS_DISABLE)) { - // https://git.musl-libc.org/cgit/musl/commit/src/signal/sigaltstack.c?id=7829f42a2c8944555439380498ab8b924d0f2070 - // The original stack has ss_size==0 and ss_flags==SS_DISABLE, but some - // versions of musl have a bug that rejects ss_size==0. Work around this by - // setting ss_size to MINSIGSTKSZ, which should be ignored by the kernel - // when SS_DISABLE is set. - old_sigstk.ss_size = MINSIGSTKSZ; - } - ABSL_RAW_CHECK(sigaltstack(&old_sigstk, nullptr) == 0, - "sigaltstack() failed"); - ABSL_RAW_CHECK(sigaction(SIGUSR1, &old_sa1, nullptr) == 0, - "sigaction() failed"); - ABSL_RAW_CHECK(sigaction(SIGUSR2, &old_sa2, nullptr) == 0, - "sigaction() failed"); - - ABSL_RAW_CHECK(munmap(altstack, kAlternateStackSize) == 0, "munmap() failed"); - if (signal_handler_stack_consumption != -1 && base_stack_consumption != -1) { - return signal_handler_stack_consumption - base_stack_consumption; - } - return -1; -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION diff --git a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.h b/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.h deleted file mode 100644 index 2b5e7151667c..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption.h +++ /dev/null @@ -1,50 +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. - -// Helper function for measuring stack consumption of signal handlers. - -#ifndef ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_ -#define ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_ - -#include "absl/base/config.h" - -// The code in this module is not portable. -// Use this feature test macro to detect its availability. -#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION -#error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly -#elif !defined(__APPLE__) && !defined(_WIN32) && \ - (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \ - defined(__aarch64__)) -#define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1 - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Returns the stack consumption in bytes for the code exercised by -// signal_handler. To measure stack consumption, signal_handler is registered -// as a signal handler, so the code that it exercises must be async-signal -// safe. The argument of signal_handler is an implementation detail of signal -// handlers and should ignored by the code for signal_handler. Use global -// variables to pass information between your test code and signal_handler. -int GetSignalHandlerStackConsumption(void (*signal_handler)(int)); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION - -#endif // ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption_test.cc b/third_party/abseil_cpp/absl/debugging/internal/stack_consumption_test.cc deleted file mode 100644 index 80445bf43aab..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stack_consumption_test.cc +++ /dev/null @@ -1,50 +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/debugging/internal/stack_consumption.h" - -#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION - -#include <string.h> - -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -namespace { - -static void SimpleSignalHandler(int signo) { - char buf[100]; - memset(buf, 'a', sizeof(buf)); - - // Never true, but prevents compiler from optimizing buf out. - if (signo == 0) { - ABSL_RAW_LOG(INFO, "%p", static_cast<void*>(buf)); - } -} - -TEST(SignalHandlerStackConsumptionTest, MeasuresStackConsumption) { - // Our handler should consume reasonable number of bytes. - EXPECT_GE(GetSignalHandlerStackConsumption(SimpleSignalHandler), 100); -} - -} // namespace -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 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 deleted file mode 100644 index f4859d7c210a..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_ - -// Generate stack tracer for aarch64 - -#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" // a no-op on non-elf or non-glibc systems -#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 = 1; - 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); - -#ifdef ABSL_HAVE_VDSO_SUPPORT - 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)) || - 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) { - void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer); - 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[0] is not suitable for unwinding, look at - // ucontext to discover frame pointer before signal. - void **const pre_signal_frame_pointer = - reinterpret_cast<void **>(ucv->uc_mcontext.regs[29]); - - // Check that alleged frame pointer is actually readable. This is to - // prevent "double fault" in case we hit the first fault due to e.g. - // 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 a - // an alternate stack for signals. - check_frame_size = false; - } - } -#endif - - // aarch64 ABI requires stack pointer to be 16-byte-aligned. - 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) { -#ifdef __GNUC__ - void **frame_pointer = reinterpret_cast<void**>(__builtin_frame_address(0)); -#else -# error reading stack point not yet supported on this platform. -#endif - - skip_count++; // Skip the frame for this function. - int n = 0; - - // The frame pointer points to low address of a frame. The first 64-bit - // word of a frame points to the next frame up the call chain, which normally - // is just after the high address of the current frame. The second word of - // a frame contains return adress of to the caller. To find a pc value - // associated with the current frame, we need to go down a level in the call - // chain. So we remember return the 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 is 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 // ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_ 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 deleted file mode 100644 index 2a1bf2e88694..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_arm-inl.inc +++ /dev/null @@ -1,134 +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 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_ - -#include <cstdint> - -#include "absl/debugging/stacktrace.h" - -// WARNING: -// This only works if all your code is in either ARM or THUMB mode. With -// interworking, the frame pointer of the caller can either be in r11 (ARM -// mode) or r7 (THUMB mode). A callee only saves the frame pointer of its -// mode in a fixed location on its stack frame. If the caller is a different -// mode, there is no easy way to find the frame pointer. It can either be -// still in the designated register or saved on stack along with other callee -// saved registers. - -// Given a pointer to a stack frame, locate and return the calling -// stackframe, or return nullptr 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> -static void **NextStackFrame(void **old_sp) { - void **new_sp = (void**) old_sp[-1]; - - // Check that the transition from frame pointer old_sp to frame - // pointer new_sp isn't clearly bogus - if (STRICT_UNWINDING) { - // With the stack growing downwards, older stack frame must be - // at a greater address that the current one. - if (new_sp <= old_sp) return nullptr; - // Assume stack frames larger than 100,000 bytes are bogus. - if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return nullptr; - } else { - // In the non-strict mode, allow discontiguous stack frames. - // (alternate-signal-stacks for example). - if (new_sp == old_sp) return nullptr; - // And allow frames upto about 1MB. - if ((new_sp > old_sp) - && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return nullptr; - } - if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return nullptr; - return new_sp; -} - -// This ensures that absl::GetStackTrace sets up the Link Register properly. -#ifdef __GNUC__ -void StacktraceArmDummyFunction() __attribute__((noinline)); -void StacktraceArmDummyFunction() { __asm__ volatile(""); } -#else -# error StacktraceArmDummyFunction() needs to be ported to this platform. -#endif - -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) { -#ifdef __GNUC__ - void **sp = reinterpret_cast<void**>(__builtin_frame_address(0)); -#else -# error reading stack point not yet supported on this platform. -#endif - - // On ARM, the return address is stored in the link register (r14). - // This is not saved on the stack frame of a leaf function. To - // simplify code that reads return addresses, we call a dummy - // function so that the return address of this function is also - // stored in the stack frame. This works at least for gcc. - StacktraceArmDummyFunction(); - - int n = 0; - while (sp && n < max_depth) { - // The absl::GetStackFrames routine is 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_sp = NextStackFrame<!IS_STACK_FRAMES>(sp); - - if (skip_count > 0) { - skip_count--; - } else { - result[n] = *sp; - - if (IS_STACK_FRAMES) { - if (next_sp > sp) { - sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; - } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } - } - n++; - } - sp = next_sp; - } - 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 (; sp != nullptr && j < kMaxUnwind; j++) { - sp = NextStackFrame<!IS_STACK_FRAMES>(sp); - } - *min_dropped_frames = j; - } - return n; -} - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -bool StackTraceWorksForTest() { - return false; -} -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_config.h b/third_party/abseil_cpp/absl/debugging/internal/stacktrace_config.h deleted file mode 100644 index 90af852818e7..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_config.h +++ /dev/null @@ -1,89 +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. - - * Defines ABSL_STACKTRACE_INL_HEADER to the *-inl.h containing - * actual unwinder implementation. - * This header is "private" to stacktrace.cc. - * DO NOT include it into any other files. -*/ -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_ - -#if defined(ABSL_STACKTRACE_INL_HEADER) -#error ABSL_STACKTRACE_INL_HEADER cannot be directly set - -#elif defined(_WIN32) -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_win32-inl.inc" - -#elif defined(__APPLE__) -// Thread local support required for UnwindImpl. -// Notes: -// * Xcode's clang did not support `thread_local` until version 8, and -// even then not for all iOS < 9.0. -// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator -// targeting iOS 9.x. -// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time -// making __has_feature unreliable there. -// -// 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_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_generic-inl.inc" -#endif - -#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. -#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>) -// 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 -#elif 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_powerpc-inl.inc" -#elif defined(__aarch64__) -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_aarch64-inl.inc" -#elif defined(__has_include) -#if __has_include(<execinfo.h>) -// Note: When using glibc this may require -funwind-tables to function properly. -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_generic-inl.inc" -#endif -#endif - -#endif - -// Fallback to the empty implementation. -#if !defined(ABSL_STACKTRACE_INL_HEADER) -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_unimplemented-inl.inc" -#endif - -#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_generic-inl.inc b/third_party/abseil_cpp/absl/debugging/internal/stacktrace_generic-inl.inc deleted file mode 100644 index b2792a1f3ada..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_generic-inl.inc +++ /dev/null @@ -1,108 +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_GENERIC_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_ - -#include <execinfo.h> -#include <atomic> -#include <cstring> - -#include "absl/debugging/stacktrace.h" -#include "absl/base/attributes.h" - -// Sometimes, we can try to get a stack trace from within a stack -// trace, because we don't block signals inside this code (which would be too -// expensive: the two extra system calls per stack trace do matter here). -// That can cause a self-deadlock. -// Protect against such reentrant call by failing to get a stack trace. -// -// We use __thread here because the code here is extremely low level -- it is -// called while collecting stack traces from within malloc and mmap, and thus -// can not call anything which might call malloc or mmap itself. -static __thread int recursive = 0; - -// The stack trace function might be invoked very early in the program's -// execution (e.g. from the very first malloc if using tcmalloc). Also, the -// glibc implementation itself will trigger malloc the first time it is called. -// As such, we suppress usage of backtrace during this early stage of execution. -static std::atomic<bool> disable_stacktraces(true); // Disabled until healthy. -// Waiting until static initializers run seems to be late enough. -// This file is included into stacktrace.cc so this will only run once. -ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() { - void* unused_stack[1]; - // Force the first backtrace to happen early to get the one-time shared lib - // loading (allocation) out of the way. After the first call it is much safer - // to use backtrace from a signal handler if we crash somewhere later. - backtrace(unused_stack, 1); - disable_stacktraces.store(false, std::memory_order_relaxed); - return 0; -}(); - -template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> -static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, - const void *ucp, int *min_dropped_frames) { - if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) { - return 0; - } - ++recursive; - - static_cast<void>(ucp); // Unused. - static const int kStackLength = 64; - void * stack[kStackLength]; - int size; - - size = backtrace(stack, kStackLength); - skip_count++; // we want to skip the current frame as well - 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_GENERIC_INL_H_ 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 deleted file mode 100644 index 2e7c2f404f20..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +++ /dev/null @@ -1,248 +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. -// -// Produce stack trace. I'm guessing (hoping!) the code is much like -// for x86. For apple machines, at least, it seems to be; see -// https://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html -// https://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK -// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882 - -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_ - -#if defined(__linux__) -#include <asm/ptrace.h> // for PT_NIP. -#include <ucontext.h> // for ucontext_t -#endif - -#include <unistd.h> -#include <cassert> -#include <cstdint> -#include <cstdio> - -#include "absl/base/attributes.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/internal/address_is_readable.h" -#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems - -// Given a stack pointer, return the saved link register value. -// Note that this is the link register for a callee. -static inline void *StacktracePowerPCGetLR(void **sp) { - // PowerPC has 3 main ABIs, which say where in the stack the - // Link Register is. For DARWIN and AIX (used by apple and - // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc), - // it's in sp[1]. -#if defined(_CALL_AIX) || defined(_CALL_DARWIN) - return *(sp+2); -#elif defined(_CALL_SYSV) - return *(sp+1); -#elif defined(__APPLE__) || defined(__FreeBSD__) || \ - (defined(__linux__) && defined(__PPC64__)) - // This check is in case the compiler doesn't define _CALL_AIX/etc. - return *(sp+2); -#elif defined(__linux) - // This check is in case the compiler doesn't define _CALL_SYSV. - return *(sp+1); -#else -#error Need to specify the PPC ABI for your archiecture. -#endif -} - -// 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 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 void **NextStackFrame(void **old_sp, const void *uc) { - void **new_sp = (void **) *old_sp; - enum { kStackAlignment = 16 }; - - // Check that the transition from frame pointer old_sp to frame - // pointer new_sp isn't clearly bogus - if (STRICT_UNWINDING) { - // With the stack growing downwards, older stack frame must be - // at a greater address that the current one. - if (new_sp <= old_sp) return nullptr; - // Assume stack frames larger than 100,000 bytes are bogus. - if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return nullptr; - } else { - // In the non-strict mode, allow discontiguous stack frames. - // (alternate-signal-stacks for example). - if (new_sp == old_sp) return nullptr; - // And allow frames upto about 1MB. - if ((new_sp > old_sp) - && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return nullptr; - } - if ((uintptr_t)new_sp % kStackAlignment != 0) return nullptr; - -#if defined(__linux__) - enum StackTraceKernelSymbolStatus { - kNotInitialized = 0, kAddressValid, kAddressInvalid }; - - if (IS_WITH_CONTEXT && uc != nullptr) { - static StackTraceKernelSymbolStatus kernel_symbol_status = - kNotInitialized; // Sentinel: not computed yet. - // Initialize with sentinel value: __kernel_rt_sigtramp_rt64 can not - // possibly be there. - static const unsigned char *kernel_sigtramp_rt64_address = nullptr; - if (kernel_symbol_status == kNotInitialized) { - absl::debugging_internal::VDSOSupport vdso; - if (vdso.IsPresent()) { - absl::debugging_internal::VDSOSupport::SymbolInfo - sigtramp_rt64_symbol_info; - if (!vdso.LookupSymbol( - "__kernel_sigtramp_rt64", "LINUX_2.6.15", - absl::debugging_internal::VDSOSupport::kVDSOSymbolType, - &sigtramp_rt64_symbol_info) || - sigtramp_rt64_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"); - kernel_symbol_status = kAddressInvalid; - } else { - kernel_sigtramp_rt64_address = - reinterpret_cast<const unsigned char *>( - sigtramp_rt64_symbol_info.address); - kernel_symbol_status = kAddressValid; - } - } else { - kernel_symbol_status = kAddressInvalid; - } - } - - if (new_sp != nullptr && - kernel_symbol_status == kAddressValid && - StacktracePowerPCGetLR(new_sp) == kernel_sigtramp_rt64_address) { - const ucontext_t* signal_context = - reinterpret_cast<const ucontext_t*>(uc); - void **const sp_before_signal = - reinterpret_cast<void**>(signal_context->uc_mcontext.gp_regs[PT_R1]); - // Check that alleged sp before signal is nonnull and is reasonably - // aligned. - if (sp_before_signal != nullptr && - ((uintptr_t)sp_before_signal % kStackAlignment) == 0) { - // Check that alleged stack pointer is actually readable. This is to - // prevent a "double fault" in case we hit the first fault due to e.g. - // a stack corruption. - if (absl::debugging_internal::AddressIsReadable(sp_before_signal)) { - // Alleged stack pointer is readable, use it for further unwinding. - new_sp = sp_before_signal; - } - } - } - } -#endif - - return new_sp; -} - -// This ensures that absl::GetStackTrace sets up the Link Register properly. -ABSL_ATTRIBUTE_NOINLINE static void AbslStacktracePowerPCDummyFunction() { - ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -} - -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) { - void **sp; - // Apple macOS uses an old version of gnu as -- both Darwin 7.9.0 (Panther) - // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a - // different asm syntax. I don't know quite the best way to discriminate - // systems using the old as from the new one; I've gone with __APPLE__. -#ifdef __APPLE__ - __asm__ volatile ("mr %0,r1" : "=r" (sp)); -#else - __asm__ volatile ("mr %0,1" : "=r" (sp)); -#endif - - // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack - // entry that holds the return address of the subroutine call (what - // instruction we run after our function finishes). This is the - // same as the stack-pointer of our parent routine, which is what we - // want here. While the compiler will always(?) set up LR for - // subroutine calls, it may not for leaf functions (such as this one). - // This routine forces the compiler (at least gcc) to push it anyway. - AbslStacktracePowerPCDummyFunction(); - - // The LR save area is used by the callee, so the top entry is bogus. - skip_count++; - - int n = 0; - - // Unlike ABIs of X86 and ARM, PowerPC ABIs say that return address (in - // the link register) of a function call is stored in the caller's stack - // frame instead of the callee's. When we look for the return address - // associated with a stack frame, we need to make sure that there is a - // caller frame before it. So we call NextStackFrame before entering the - // loop below and check next_sp instead of sp for loop termination. - // The outermost frame is set up by runtimes and it does not have a - // caller frame, so it is skipped. - - // The absl::GetStackFrames routine is 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_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp); - - while (next_sp && n < max_depth) { - if (skip_count > 0) { - skip_count--; - } else { - result[n] = StacktracePowerPCGetLR(sp); - if (IS_STACK_FRAMES) { - if (next_sp > sp) { - sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; - } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } - } - n++; - } - - sp = next_sp; - next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp); - } - - 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 = 1000; - int j = 0; - for (; next_sp != nullptr && j < kMaxUnwind; j++) { - next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(next_sp, 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 // ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc b/third_party/abseil_cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc deleted file mode 100644 index 5b8fb191b65a..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_ - -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 (min_dropped_frames != nullptr) { - *min_dropped_frames = 0; - } - return 0; -} - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -bool StackTraceWorksForTest() { - return false; -} -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_win32-inl.inc b/third_party/abseil_cpp/absl/debugging/internal/stacktrace_win32-inl.inc deleted file mode 100644 index 1c666c8b561f..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_win32-inl.inc +++ /dev/null @@ -1,93 +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. -// -// Produces a stack trace for Windows. Normally, one could use -// stacktrace_x86-inl.h or stacktrace_x86_64-inl.h -- and indeed, that -// should work for binaries compiled using MSVC in "debug" mode. -// However, in "release" mode, Windows uses frame-pointer -// optimization, which makes getting a stack trace very difficult. -// -// There are several approaches one can take. One is to use Windows -// intrinsics like StackWalk64. These can work, but have restrictions -// on how successful they can be. Another attempt is to write a -// version of stacktrace_x86-inl.h that has heuristic support for -// dealing with FPO, similar to what WinDbg does (see -// http://www.nynaeve.net/?p=97). There are (non-working) examples of -// these approaches, complete with TODOs, in stacktrace_win32-inl.h#1 -// -// The solution we've ended up doing is to call the undocumented -// windows function RtlCaptureStackBackTrace, which probably doesn't -// work with FPO but at least is fast, and doesn't require a symbol -// server. -// -// This code is inspired by a patch from David Vitek: -// https://code.google.com/p/google-perftools/issues/detail?id=83 - -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_ - -#include <windows.h> // for GetProcAddress and GetModuleHandle -#include <cassert> - -typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( - IN ULONG frames_to_skip, - IN ULONG frames_to_capture, - 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 - -template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> -static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, - const void*, int* min_dropped_frames) { - int n = 0; - if (!RtlCaptureStackBackTrace_fn) { - // can't find a stacktrace with no function to call - } else { - n = (int)RtlCaptureStackBackTrace_fn(skip_count + 2, max_depth, result, 0); - } - if (IS_STACK_FRAMES) { - // No implementation for finding out the stack frame sizes yet. - memset(sizes, 0, sizeof(*sizes) * n); - } - if (min_dropped_frames != nullptr) { - // Not implemented. - *min_dropped_frames = 0; - } - return n; -} - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { -bool StackTraceWorksForTest() { - return false; -} -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_x86-inl.inc b/third_party/abseil_cpp/absl/debugging/internal/stacktrace_x86-inl.inc deleted file mode 100644 index bc320ff75bc5..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/stacktrace_x86-inl.inc +++ /dev/null @@ -1,346 +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. -// -// Produce stack trace - -#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_ -#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_ - -#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) -#include <ucontext.h> // for ucontext_t -#endif - -#if !defined(_WIN32) -#include <unistd.h> -#endif - -#include <cassert> -#include <cstdint> - -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/debugging/internal/address_is_readable.h" -#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems -#include "absl/debugging/stacktrace.h" - -#include "absl/base/internal/raw_logging.h" - -using absl::debugging_internal::AddressIsReadable; - -#if defined(__linux__) && defined(__i386__) -// Count "push %reg" instructions in VDSO __kernel_vsyscall(), -// preceeding "syscall" or "sysenter". -// If __kernel_vsyscall uses frame pointer, answer 0. -// -// kMaxBytes tells how many instruction bytes of __kernel_vsyscall -// to analyze before giving up. Up to kMaxBytes+1 bytes of -// instructions could be accessed. -// -// Here are known __kernel_vsyscall instruction sequences: -// -// SYSENTER (linux-2.6.26/arch/x86/vdso/vdso32/sysenter.S). -// Used on Intel. -// 0xffffe400 <__kernel_vsyscall+0>: push %ecx -// 0xffffe401 <__kernel_vsyscall+1>: push %edx -// 0xffffe402 <__kernel_vsyscall+2>: push %ebp -// 0xffffe403 <__kernel_vsyscall+3>: mov %esp,%ebp -// 0xffffe405 <__kernel_vsyscall+5>: sysenter -// -// SYSCALL (see linux-2.6.26/arch/x86/vdso/vdso32/syscall.S). -// Used on AMD. -// 0xffffe400 <__kernel_vsyscall+0>: push %ebp -// 0xffffe401 <__kernel_vsyscall+1>: mov %ecx,%ebp -// 0xffffe403 <__kernel_vsyscall+3>: syscall -// - -// The sequence below isn't actually expected in Google fleet, -// here only for completeness. Remove this comment from OSS release. - -// i386 (see linux-2.6.26/arch/x86/vdso/vdso32/int80.S) -// 0xffffe400 <__kernel_vsyscall+0>: int $0x80 -// 0xffffe401 <__kernel_vsyscall+1>: ret -// -static const int kMaxBytes = 10; - -// We use assert()s instead of DCHECK()s -- this is too low level -// for DCHECK(). - -static int CountPushInstructions(const unsigned char *const addr) { - int result = 0; - for (int i = 0; i < kMaxBytes; ++i) { - if (addr[i] == 0x89) { - // "mov reg,reg" - if (addr[i + 1] == 0xE5) { - // Found "mov %esp,%ebp". - return 0; - } - ++i; // Skip register encoding byte. - } else if (addr[i] == 0x0F && - (addr[i + 1] == 0x34 || addr[i + 1] == 0x05)) { - // Found "sysenter" or "syscall". - return result; - } else if ((addr[i] & 0xF0) == 0x50) { - // Found "push %reg". - ++result; - } else if (addr[i] == 0xCD && addr[i + 1] == 0x80) { - // Found "int $0x80" - assert(result == 0); - return 0; - } else { - // Unexpected instruction. - assert(false && "unexpected instruction in __kernel_vsyscall"); - return 0; - } - } - // Unexpected: didn't find SYSENTER or SYSCALL in - // [__kernel_vsyscall, __kernel_vsyscall + kMaxBytes) interval. - assert(false && "did not find SYSENTER or SYSCALL in __kernel_vsyscall"); - return 0; -} -#endif - -// Assume stack frames larger than 100,000 bytes are bogus. -static const int kMaxFrameBytes = 100000; - -// Returns the stack frame pointer from signal context, 0 if unknown. -// vuc is a ucontext_t *. We use void* to avoid the use -// of ucontext_t on non-POSIX systems. -static uintptr_t GetFP(const void *vuc) { -#if !defined(__linux__) - static_cast<void>(vuc); // Avoid an unused argument compiler warning. -#else - if (vuc != nullptr) { - auto *uc = reinterpret_cast<const ucontext_t *>(vuc); -#if defined(__i386__) - const auto bp = uc->uc_mcontext.gregs[REG_EBP]; - const auto sp = uc->uc_mcontext.gregs[REG_ESP]; -#elif defined(__x86_64__) - const auto bp = uc->uc_mcontext.gregs[REG_RBP]; - const auto sp = uc->uc_mcontext.gregs[REG_RSP]; -#else - const uintptr_t bp = 0; - const uintptr_t sp = 0; -#endif - // 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 - // behavior when building with clang. Talk to the C++ toolchain team about - // fixing that. - if (bp >= sp && bp - sp <= kMaxFrameBytes) return bp; - - // If bp isn't a plausible frame pointer, return the stack pointer instead. - // If we're lucky, it points to the start of a stack frame; otherwise, we'll - // get one frame of garbage in the stack trace and fail the sanity check on - // the next iteration. - return sp; - } -#endif - return 0; -} - -// 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_fp, const void *uc) { - void **new_fp = (void **)*old_fp; - -#if defined(__linux__) && defined(__i386__) - if (WITH_CONTEXT && uc != nullptr) { - // How many "push %reg" instructions are there at __kernel_vsyscall? - // This is constant for a given kernel and processor, so compute - // it only once. - static int num_push_instructions = -1; // Sentinel: not computed yet. - // Initialize with sentinel value: __kernel_rt_sigreturn can not possibly - // be there. - static const unsigned char *kernel_rt_sigreturn_address = nullptr; - static const unsigned char *kernel_vsyscall_address = nullptr; - if (num_push_instructions == -1) { -#ifdef ABSL_HAVE_VDSO_SUPPORT - absl::debugging_internal::VDSOSupport vdso; - if (vdso.IsPresent()) { - absl::debugging_internal::VDSOSupport::SymbolInfo - rt_sigreturn_symbol_info; - absl::debugging_internal::VDSOSupport::SymbolInfo vsyscall_symbol_info; - if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.5", STT_FUNC, - &rt_sigreturn_symbol_info) || - !vdso.LookupSymbol("__kernel_vsyscall", "LINUX_2.5", STT_FUNC, - &vsyscall_symbol_info) || - rt_sigreturn_symbol_info.address == nullptr || - vsyscall_symbol_info.address == nullptr) { - // Unexpected: 32-bit VDSO is present, yet one of the expected - // symbols is missing or null. - assert(false && "VDSO is present, but doesn't have expected symbols"); - num_push_instructions = 0; - } else { - kernel_rt_sigreturn_address = - reinterpret_cast<const unsigned char *>( - rt_sigreturn_symbol_info.address); - kernel_vsyscall_address = - reinterpret_cast<const unsigned char *>( - vsyscall_symbol_info.address); - num_push_instructions = - CountPushInstructions(kernel_vsyscall_address); - } - } else { - num_push_instructions = 0; - } -#else // ABSL_HAVE_VDSO_SUPPORT - num_push_instructions = 0; -#endif // ABSL_HAVE_VDSO_SUPPORT - } - if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr && - old_fp[1] == kernel_rt_sigreturn_address) { - const ucontext_t *ucv = static_cast<const ucontext_t *>(uc); - // This kernel does not use frame pointer in its VDSO code, - // and so %ebp is not suitable for unwinding. - void **const reg_ebp = - reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_EBP]); - const unsigned char *const reg_eip = - reinterpret_cast<unsigned char *>(ucv->uc_mcontext.gregs[REG_EIP]); - if (new_fp == reg_ebp && kernel_vsyscall_address <= reg_eip && - reg_eip - kernel_vsyscall_address < kMaxBytes) { - // We "stepped up" to __kernel_vsyscall, but %ebp is not usable. - // Restore from 'ucv' instead. - void **const reg_esp = - reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_ESP]); - // Check that alleged %esp is not null and is reasonably aligned. - if (reg_esp && - ((uintptr_t)reg_esp & (sizeof(reg_esp) - 1)) == 0) { - // Check that alleged %esp is actually readable. This is to prevent - // "double fault" in case we hit the first fault due to e.g. stack - // corruption. - void *const reg_esp2 = reg_esp[num_push_instructions - 1]; - if (AddressIsReadable(reg_esp2)) { - // Alleged %esp is readable, use it for further unwinding. - new_fp = reinterpret_cast<void **>(reg_esp2); - } - } - } - } - } -#endif - - const uintptr_t old_fp_u = reinterpret_cast<uintptr_t>(old_fp); - const uintptr_t new_fp_u = reinterpret_cast<uintptr_t>(new_fp); - - // Check that the transition from frame pointer old_fp to frame - // pointer new_fp isn't clearly bogus. Skip the checks if new_fp - // matches the signal context, so that we don't skip out early when - // using an alternate signal stack. - // - // TODO(bcmills): The GetFP call should be completely unnecessary when - // 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 - // it's supposed to. - if (STRICT_UNWINDING && - (!WITH_CONTEXT || uc == nullptr || new_fp_u != GetFP(uc))) { - // With the stack growing downwards, older stack frame must be - // at a greater address that the current one. - if (new_fp_u <= old_fp_u) return nullptr; - if (new_fp_u - old_fp_u > kMaxFrameBytes) return nullptr; - } else { - if (new_fp == nullptr) return nullptr; // skip AddressIsReadable() below - // In the non-strict mode, allow discontiguous stack frames. - // (alternate-signal-stacks for example). - if (new_fp == old_fp) return nullptr; - } - - if (new_fp_u & (sizeof(void *) - 1)) return nullptr; -#ifdef __i386__ - // On 32-bit machines, the stack pointer can be very close to - // 0xffffffff, so we explicitly check for a pointer into the - // last two pages in the address space - if (new_fp_u >= 0xffffe000) return nullptr; -#endif -#if !defined(_WIN32) - if (!STRICT_UNWINDING) { - // Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test - // on AMD-based machines with VDSO-enabled kernels. - // Make an extra sanity check to insure new_fp is readable. - // Note: NextStackFrame<false>() is only called while the program - // is already on its last leg, so it's ok to be slow here. - - if (!AddressIsReadable(new_fp)) { - return nullptr; - } - } -#endif - return new_fp; -} - -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. -ABSL_ATTRIBUTE_NOINLINE -static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count, - const void *ucp, int *min_dropped_frames) { - int n = 0; - void **fp = reinterpret_cast<void **>(__builtin_frame_address(0)); - - 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); - if (skip_count > 0) { - skip_count--; - } else { - result[n] = *(fp + 1); - if (IS_STACK_FRAMES) { - if (next_fp > fp) { - sizes[n] = (uintptr_t)next_fp - (uintptr_t)fp; - } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } - } - n++; - } - fp = next_fp; - } - 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 = 1000; - int j = 0; - for (; fp != nullptr && j < kMaxUnwind; j++) { - fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, 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 // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_ diff --git a/third_party/abseil_cpp/absl/debugging/internal/symbolize.h b/third_party/abseil_cpp/absl/debugging/internal/symbolize.h deleted file mode 100644 index 4f26130fbb71..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/symbolize.h +++ /dev/null @@ -1,147 +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. - -// This file contains internal parts of the Abseil symbolizer. -// Do not depend on the anything in this file, it may change at anytime. - -#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__) -#define ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 1 - -#include <elf.h> -#include <link.h> // For ElfW() macro. -#include <functional> -#include <string> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Iterates over all sections, invoking callback on each with the section name -// and the section header. -// -// Returns true on success; otherwise returns false in case of errors. -// -// This is not async-signal-safe. -bool ForEachSection(int fd, - const std::function<bool(absl::string_view name, - const ElfW(Shdr) &)>& callback); - -// Gets the section header for the given name, if it exists. Returns true on -// success. Otherwise, returns false. -bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, - ElfW(Shdr) *out); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE - -#ifdef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE -#error ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE cannot be directly set -#elif defined(__APPLE__) -#define ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -struct SymbolDecoratorArgs { - // The program counter we are getting symbolic name for. - const void *pc; - // 0 for main executable, load address for shared libraries. - ptrdiff_t relocation; - // Read-only file descriptor for ELF image covering "pc", - // or -1 if no such ELF image exists in /proc/self/maps. - int fd; - // Output buffer, size. - // Note: the buffer may not be empty -- default symbolizer may have already - // produced some output, and earlier decorators may have adorned it in - // some way. You are free to replace or augment the contents (within the - // symbol_buf_size limit). - char *const symbol_buf; - size_t symbol_buf_size; - // Temporary scratch space, size. - // Use that space in preference to allocating your own stack buffer to - // conserve stack. - char *const tmp_buf; - size_t tmp_buf_size; - // User-provided argument - void* arg; -}; -using SymbolDecorator = void (*)(const SymbolDecoratorArgs *); - -// Installs a function-pointer as a decorator. Returns a value less than zero -// if the system cannot install the decorator. Otherwise, returns a unique -// identifier corresponding to the decorator. This identifier can be used to -// uninstall the decorator - See RemoveSymbolDecorator() below. -int InstallSymbolDecorator(SymbolDecorator decorator, void* arg); - -// Removes a previously installed function-pointer decorator. Parameter "ticket" -// is the return-value from calling InstallSymbolDecorator(). -bool RemoveSymbolDecorator(int ticket); - -// Remove all installed decorators. Returns true if successful, false if -// symbolization is currently in progress. -bool RemoveAllSymbolDecorators(void); - -// Registers an address range to a file mapping. -// -// Preconditions: -// start <= end -// filename != nullptr -// -// Returns true if the file was successfully registered. -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, - 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 deleted file mode 100644 index 6be16d907275..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/vdso_support.cc +++ /dev/null @@ -1,173 +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. - -// Allow dynamic symbol lookup in the kernel VDSO page. -// -// VDSOSupport -- a class representing kernel VDSO (if present). - -#include "absl/debugging/internal/vdso_support.h" - -#ifdef ABSL_HAVE_VDSO_SUPPORT // defined in vdso_support.h - -#include <errno.h> -#include <fcntl.h> -#include <sys/syscall.h> -#include <unistd.h> - -#if __GLIBC_PREREQ(2, 16) // GLIBC-2.16 implements getauxval. -#include <sys/auxv.h> -#endif - -#include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/port.h" - -#ifndef AT_SYSINFO_EHDR -#define AT_SYSINFO_EHDR 33 // for crosstoolv10 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -ABSL_CONST_INIT -std::atomic<const void *> VDSOSupport::vdso_base_( - debugging_internal::ElfMemImage::kInvalidBase); - -std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(&InitAndGetCPU); -VDSOSupport::VDSOSupport() - // If vdso_base_ is still set to kInvalidBase, we got here - // before VDSOSupport::Init has been called. Call it now. - : image_(vdso_base_.load(std::memory_order_relaxed) == - debugging_internal::ElfMemImage::kInvalidBase - ? Init() - : vdso_base_.load(std::memory_order_relaxed)) {} - -// NOTE: we can't use GoogleOnceInit() below, because we can be -// called by tcmalloc, and none of the *once* stuff may be functional yet. -// -// In addition, we hope that the VDSOSupportHelper constructor -// causes this code to run before there are any threads, and before -// InitGoogle() has executed any chroot or setuid calls. -// -// Finally, even if there is a race here, it is harmless, because -// the operation should be idempotent. -const void *VDSOSupport::Init() { - const auto kInvalidBase = debugging_internal::ElfMemImage::kInvalidBase; -#if __GLIBC_PREREQ(2, 16) - if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { - errno = 0; - const void *const sysinfo_ehdr = - reinterpret_cast<const void *>(getauxval(AT_SYSINFO_EHDR)); - if (errno == 0) { - vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed); - } - } -#endif // __GLIBC_PREREQ(2, 16) - if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { - int fd = open("/proc/self/auxv", O_RDONLY); - if (fd == -1) { - // Kernel too old to have a VDSO. - vdso_base_.store(nullptr, std::memory_order_relaxed); - getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed); - return nullptr; - } - ElfW(auxv_t) aux; - while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { - if (aux.a_type == AT_SYSINFO_EHDR) { - vdso_base_.store(reinterpret_cast<void *>(aux.a_un.a_val), - std::memory_order_relaxed); - break; - } - } - close(fd); - if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) { - // Didn't find AT_SYSINFO_EHDR in auxv[]. - vdso_base_.store(nullptr, std::memory_order_relaxed); - } - } - GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present. - if (vdso_base_.load(std::memory_order_relaxed)) { - VDSOSupport vdso; - SymbolInfo info; - if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { - fn = reinterpret_cast<GetCpuFn>(const_cast<void *>(info.address)); - } - } - // Subtle: this code runs outside of any locks; prevent compiler - // from assigning to getcpu_fn_ more than once. - getcpu_fn_.store(fn, std::memory_order_relaxed); - return vdso_base_.load(std::memory_order_relaxed); -} - -const void *VDSOSupport::SetBase(const void *base) { - ABSL_RAW_CHECK(base != debugging_internal::ElfMemImage::kInvalidBase, - "internal error"); - const void *old_base = vdso_base_.load(std::memory_order_relaxed); - vdso_base_.store(base, std::memory_order_relaxed); - image_.Init(base); - // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. - getcpu_fn_.store(&InitAndGetCPU, std::memory_order_relaxed); - return old_base; -} - -bool VDSOSupport::LookupSymbol(const char *name, - const char *version, - int type, - SymbolInfo *info) const { - return image_.LookupSymbol(name, version, type, info); -} - -bool VDSOSupport::LookupSymbolByAddress(const void *address, - SymbolInfo *info_out) const { - return image_.LookupSymbolByAddress(address, info_out); -} - -// NOLINT on 'long' because this routine mimics kernel api. -long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, // NOLINT(runtime/int) - void *, void *) { -#ifdef SYS_getcpu - return syscall(SYS_getcpu, cpu, nullptr, nullptr); -#else - // x86_64 never implemented sys_getcpu(), except as a VDSO call. - static_cast<void>(cpu); // Avoid an unused argument compiler warning. - errno = ENOSYS; - return -1; -#endif -} - -// Use fast __vdso_getcpu if available. -long VDSOSupport::InitAndGetCPU(unsigned *cpu, // NOLINT(runtime/int) - void *x, void *y) { - Init(); - GetCpuFn fn = getcpu_fn_.load(std::memory_order_relaxed); - ABSL_RAW_CHECK(fn != &InitAndGetCPU, "Init() did not set getcpu_fn_"); - return (*fn)(cpu, x, y); -} - -// This function must be very fast, and may be called from very -// low level (e.g. tcmalloc). Hence I avoid things like -// GoogleOnceInit() and ::operator new. -ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY -int GetCPU() { - unsigned cpu; - int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, nullptr, nullptr); - return ret_code == 0 ? cpu : ret_code; -} - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_VDSO_SUPPORT diff --git a/third_party/abseil_cpp/absl/debugging/internal/vdso_support.h b/third_party/abseil_cpp/absl/debugging/internal/vdso_support.h deleted file mode 100644 index 6562c6c2350a..000000000000 --- a/third_party/abseil_cpp/absl/debugging/internal/vdso_support.h +++ /dev/null @@ -1,158 +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. -// - -// Allow dynamic symbol lookup in the kernel VDSO page. -// -// VDSO stands for "Virtual Dynamic Shared Object" -- a page of -// executable code, which looks like a shared library, but doesn't -// necessarily exist anywhere on disk, and which gets mmap()ed into -// every process by kernels which support VDSO, such as 2.6.x for 32-bit -// executables, and 2.6.24 and above for 64-bit executables. -// -// More details could be found here: -// http://www.trilithium.com/johan/2005/08/linux-gate/ -// -// VDSOSupport -- a class representing kernel VDSO (if present). -// -// Example usage: -// VDSOSupport vdso; -// VDSOSupport::SymbolInfo info; -// typedef (*FN)(unsigned *, void *, void *); -// FN fn = nullptr; -// if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { -// fn = reinterpret_cast<FN>(info.address); -// } - -#ifndef ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_ -#define ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_ - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/debugging/internal/elf_mem_image.h" - -#ifdef ABSL_HAVE_ELF_MEM_IMAGE - -#ifdef ABSL_HAVE_VDSO_SUPPORT -#error ABSL_HAVE_VDSO_SUPPORT cannot be directly set -#else -#define ABSL_HAVE_VDSO_SUPPORT 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// NOTE: this class may be used from within tcmalloc, and can not -// use any memory allocation routines. -class VDSOSupport { - public: - VDSOSupport(); - - typedef ElfMemImage::SymbolInfo SymbolInfo; - typedef ElfMemImage::SymbolIterator SymbolIterator; - - // On PowerPC64 VDSO symbols can either be of type STT_FUNC or STT_NOTYPE - // depending on how the kernel is built. The kernel is normally built with - // STT_NOTYPE type VDSO symbols. Let's make things simpler first by using a - // compile-time constant. -#ifdef __powerpc64__ - enum { kVDSOSymbolType = STT_NOTYPE }; -#else - enum { kVDSOSymbolType = STT_FUNC }; -#endif - - // Answers whether we have a vdso at all. - bool IsPresent() const { return image_.IsPresent(); } - - // Allow to iterate over all VDSO symbols. - SymbolIterator begin() const { return image_.begin(); } - SymbolIterator end() const { return image_.end(); } - - // Look up versioned dynamic symbol in the kernel VDSO. - // Returns false if VDSO is not present, or doesn't contain given - // symbol/version/type combination. - // If info_out != nullptr, additional details are filled in. - bool LookupSymbol(const char *name, const char *version, - int symbol_type, SymbolInfo *info_out) const; - - // Find info about symbol (if any) which overlaps given address. - // Returns true if symbol was found; false if VDSO isn't present - // or doesn't have a symbol overlapping given address. - // If info_out != nullptr, additional details are filled in. - bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; - - // Used only for testing. Replace real VDSO base with a mock. - // Returns previous value of vdso_base_. After you are done testing, - // you are expected to call SetBase() with previous value, in order to - // reset state to the way it was. - const void *SetBase(const void *s); - - // Computes vdso_base_ and returns it. Should be called as early as - // possible; before any thread creation, chroot or setuid. - static const void *Init(); - - private: - // image_ represents VDSO ELF image in memory. - // image_.ehdr_ == nullptr implies there is no VDSO. - ElfMemImage image_; - - // Cached value of auxv AT_SYSINFO_EHDR, computed once. - // This is a tri-state: - // kInvalidBase => value hasn't been determined yet. - // 0 => there is no VDSO. - // else => vma of VDSO Elf{32,64}_Ehdr. - // - // When testing with mock VDSO, low bit is set. - // The low bit is always available because vdso_base_ is - // page-aligned. - static std::atomic<const void *> vdso_base_; - - // NOLINT on 'long' because these routines mimic kernel api. - // The 'cache' parameter may be used by some versions of the kernel, - // and should be nullptr or point to a static buffer containing at - // least two 'long's. - static long InitAndGetCPU(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - static long GetCPUViaSyscall(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - typedef long (*GetCpuFn)(unsigned *cpu, void *cache, // NOLINT 'long'. - void *unused); - - // This function pointer may point to InitAndGetCPU, - // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization. - ABSL_CONST_INIT static std::atomic<GetCpuFn> getcpu_fn_; - - friend int GetCPU(void); // Needs access to getcpu_fn_. - - VDSOSupport(const VDSOSupport&) = delete; - VDSOSupport& operator=(const VDSOSupport&) = delete; -}; - -// Same as sched_getcpu() on later glibc versions. -// Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present, -// otherwise use syscall(SYS_getcpu,...). -// May return -1 with errno == ENOSYS if the kernel doesn't -// support SYS_getcpu. -int GetCPU(); - -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_ELF_MEM_IMAGE - -#endif // ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_ diff --git a/third_party/abseil_cpp/absl/debugging/leak_check.cc b/third_party/abseil_cpp/absl/debugging/leak_check.cc deleted file mode 100644 index ff9049559d4d..000000000000 --- a/third_party/abseil_cpp/absl/debugging/leak_check.cc +++ /dev/null @@ -1,53 +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. - -// Wrappers around lsan_interface functions. -// When lsan is not linked in, these functions are not available, -// therefore Abseil code which depends on these functions is conditioned on the -// definition of LEAK_SANITIZER. -#include "absl/debugging/leak_check.h" - -#ifndef LEAK_SANITIZER - -namespace absl { -ABSL_NAMESPACE_BEGIN -bool HaveLeakSanitizer() { return false; } -void DoIgnoreLeak(const void*) { } -void RegisterLivePointers(const void*, size_t) { } -void UnRegisterLivePointers(const void*, size_t) { } -LeakCheckDisabler::LeakCheckDisabler() { } -LeakCheckDisabler::~LeakCheckDisabler() { } -ABSL_NAMESPACE_END -} // namespace absl - -#else - -#include <sanitizer/lsan_interface.h> - -namespace absl { -ABSL_NAMESPACE_BEGIN -bool HaveLeakSanitizer() { return true; } -void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); } -void RegisterLivePointers(const void* ptr, size_t size) { - __lsan_register_root_region(ptr, size); -} -void UnRegisterLivePointers(const void* ptr, size_t size) { - __lsan_unregister_root_region(ptr, size); -} -LeakCheckDisabler::LeakCheckDisabler() { __lsan_disable(); } -LeakCheckDisabler::~LeakCheckDisabler() { __lsan_enable(); } -ABSL_NAMESPACE_END -} // namespace absl - -#endif // LEAK_SANITIZER diff --git a/third_party/abseil_cpp/absl/debugging/leak_check.h b/third_party/abseil_cpp/absl/debugging/leak_check.h deleted file mode 100644 index 7a5a22dd1caf..000000000000 --- a/third_party/abseil_cpp/absl/debugging/leak_check.h +++ /dev/null @@ -1,113 +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: leak_check.h -// ----------------------------------------------------------------------------- -// -// This file contains functions that affect leak checking behavior within -// targets built with the LeakSanitizer (LSan), a memory leak detector that is -// integrated within the AddressSanitizer (ASan) as an additional component, or -// which can be used standalone. LSan and ASan are included (or can be provided) -// as additional components for most compilers such as Clang, gcc and MSVC. -// Note: this leak checking API is not yet supported in MSVC. -// Leak checking is enabled by default in all ASan builds. -// -// See https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer -// -// ----------------------------------------------------------------------------- -#ifndef ABSL_DEBUGGING_LEAK_CHECK_H_ -#define ABSL_DEBUGGING_LEAK_CHECK_H_ - -#include <cstddef> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// HaveLeakSanitizer() -// -// Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is -// currently built into this target. -bool HaveLeakSanitizer(); - -// DoIgnoreLeak() -// -// Implements `IgnoreLeak()` below. This function should usually -// not be called directly; calling `IgnoreLeak()` is preferred. -void DoIgnoreLeak(const void* ptr); - -// IgnoreLeak() -// -// Instruct the leak sanitizer to ignore leak warnings on the object referenced -// by the passed pointer, as well as all heap objects transitively referenced -// by it. The passed object pointer can point to either the beginning of the -// object or anywhere within it. -// -// Example: -// -// static T* obj = IgnoreLeak(new T(...)); -// -// If the passed `ptr` does not point to an actively allocated object at the -// time `IgnoreLeak()` is called, the call is a no-op; if it is actively -// allocated, the object must not get deallocated later. -// -template <typename T> -T* IgnoreLeak(T* ptr) { - DoIgnoreLeak(ptr); - return ptr; -} - -// LeakCheckDisabler -// -// This helper class indicates that any heap allocations done in the code block -// covered by the scoped object, which should be allocated on the stack, will -// not be reported as leaks. Leak check disabling will occur within the code -// block and any nested function calls within the code block. -// -// Example: -// -// void Foo() { -// LeakCheckDisabler disabler; -// ... code that allocates objects whose leaks should be ignored ... -// } -// -// REQUIRES: Destructor runs in same thread as constructor -class LeakCheckDisabler { - public: - LeakCheckDisabler(); - LeakCheckDisabler(const LeakCheckDisabler&) = delete; - LeakCheckDisabler& operator=(const LeakCheckDisabler&) = delete; - ~LeakCheckDisabler(); -}; - -// RegisterLivePointers() -// -// Registers `ptr[0,size-1]` as pointers to memory that is still actively being -// referenced and for which leak checking should be ignored. This function is -// useful if you store pointers in mapped memory, for memory ranges that we know -// are correct but for which normal analysis would flag as leaked code. -void RegisterLivePointers(const void* ptr, size_t size); - -// UnRegisterLivePointers() -// -// Deregisters the pointers previously marked as active in -// `RegisterLivePointers()`, enabling leak checking of those pointers. -void UnRegisterLivePointers(const void* ptr, size_t size); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_LEAK_CHECK_H_ diff --git a/third_party/abseil_cpp/absl/debugging/leak_check_disable.cc b/third_party/abseil_cpp/absl/debugging/leak_check_disable.cc deleted file mode 100644 index 924d6e3d543b..000000000000 --- a/third_party/abseil_cpp/absl/debugging/leak_check_disable.cc +++ /dev/null @@ -1,20 +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. - -// Disable LeakSanitizer when this file is linked in. -// This function overrides __lsan_is_turned_off from sanitizer/lsan_interface.h -extern "C" int __lsan_is_turned_off(); -extern "C" int __lsan_is_turned_off() { - return 1; -} 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 deleted file mode 100644 index c49b81a9d9e2..000000000000 --- a/third_party/abseil_cpp/absl/debugging/leak_check_fail_test.cc +++ /dev/null @@ -1,41 +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 <memory> -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/leak_check.h" - -namespace { - -TEST(LeakCheckTest, LeakMemory) { - // This test is expected to cause lsan failures on program exit. Therefore the - // test will be run only by leak_check_test.sh, which will verify a - // failed exit code. - - char* foo = strdup("lsan should complain about this leaked string"); - ABSL_RAW_LOG(INFO, "Should detect leaked string %s", foo); -} - -TEST(LeakCheckTest, LeakMemoryAfterDisablerScope) { - // This test is expected to cause lsan failures on program exit. Therefore the - // test will be run only by external_leak_check_test.sh, which will verify a - // 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", - foo); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/debugging/leak_check_test.cc b/third_party/abseil_cpp/absl/debugging/leak_check_test.cc deleted file mode 100644 index b5cc4874880f..000000000000 --- a/third_party/abseil_cpp/absl/debugging/leak_check_test.cc +++ /dev/null @@ -1,42 +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 <string> - -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/leak_check.h" - -namespace { - -TEST(LeakCheckTest, DetectLeakSanitizer) { -#ifdef ABSL_EXPECT_LEAK_SANITIZER - EXPECT_TRUE(absl::HaveLeakSanitizer()); -#else - EXPECT_FALSE(absl::HaveLeakSanitizer()); -#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()); -} - -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()); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/debugging/stacktrace.cc b/third_party/abseil_cpp/absl/debugging/stacktrace.cc deleted file mode 100644 index 1f7c7d82b2d2..000000000000 --- a/third_party/abseil_cpp/absl/debugging/stacktrace.cc +++ /dev/null @@ -1,140 +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. - -// Produce stack trace. -// -// There are three different ways we can try to get the stack trace: -// -// 1) Our hand-coded stack-unwinder. This depends on a certain stack -// layout, which is used by gcc (and those systems using a -// gcc-compatible ABI) on x86 systems, at least since gcc 2.95. -// It uses the frame pointer to do its work. -// -// 2) The libunwind library. This is still in development, and as a -// separate library adds a new dependency, but doesn't need a frame -// pointer. It also doesn't call malloc. -// -// 3) The gdb unwinder -- also the one used by the c++ exception code. -// It's obviously well-tested, but has a fatal flaw: it can call -// malloc() from the unwinder. This is a problem because we're -// trying to use the unwinder to instrument malloc(). -// -// Note: if you add a new implementation here, make sure it works -// correctly when absl::GetStackTrace() is called with max_depth == 0. -// Some code may do that. - -#include "absl/debugging/stacktrace.h" - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/port.h" -#include "absl/debugging/internal/stacktrace_config.h" - -#if defined(ABSL_STACKTRACE_INL_HEADER) -#include ABSL_STACKTRACE_INL_HEADER -#else -# error Cannot calculate stack trace: will need to write for your environment - -# include "absl/debugging/internal/stacktrace_aarch64-inl.inc" -# include "absl/debugging/internal/stacktrace_arm-inl.inc" -# include "absl/debugging/internal/stacktrace_generic-inl.inc" -# include "absl/debugging/internal/stacktrace_powerpc-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" -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -typedef int (*Unwinder)(void**, int*, int, int, const void*, int*); -std::atomic<Unwinder> custom; - -template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> -ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, int* sizes, - int max_depth, int skip_count, - const void* uc, - int* min_dropped_frames) { - Unwinder f = &UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>; - Unwinder g = custom.load(std::memory_order_acquire); - if (g != nullptr) f = g; - - // Add 1 to skip count for the unwinder function itself - int size = (*f)(result, sizes, max_depth, skip_count + 1, uc, - min_dropped_frames); - // To disable tail call to (*f)(...) - ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); - return size; -} - -} // anonymous namespace - -ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames( - void** result, int* sizes, int max_depth, int skip_count) { - return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr, - nullptr); -} - -ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int -GetStackFramesWithContext(void** result, int* sizes, int max_depth, - int skip_count, const void* uc, - int* min_dropped_frames) { - return Unwind<true, true>(result, sizes, max_depth, skip_count, uc, - min_dropped_frames); -} - -ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace( - void** result, int max_depth, int skip_count) { - return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr, - nullptr); -} - -ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int -GetStackTraceWithContext(void** result, int max_depth, int skip_count, - const void* uc, int* min_dropped_frames) { - return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc, - min_dropped_frames); -} - -void SetStackUnwinder(Unwinder w) { - custom.store(w, std::memory_order_release); -} - -int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip, - const void* uc, int* min_dropped_frames) { - skip++; // For this function - Unwinder f = nullptr; - if (sizes == nullptr) { - if (uc == nullptr) { - f = &UnwindImpl<false, false>; - } else { - f = &UnwindImpl<false, true>; - } - } else { - if (uc == nullptr) { - f = &UnwindImpl<true, false>; - } else { - f = &UnwindImpl<true, true>; - } - } - volatile int x = 0; - int n = (*f)(pcs, sizes, depth, skip, uc, min_dropped_frames); - x = 1; (void) x; // To disable tail call to (*f)(...) - return n; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/debugging/stacktrace.h b/third_party/abseil_cpp/absl/debugging/stacktrace.h deleted file mode 100644 index 0ec0ffdabd42..000000000000 --- a/third_party/abseil_cpp/absl/debugging/stacktrace.h +++ /dev/null @@ -1,231 +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: stacktrace.h -// ----------------------------------------------------------------------------- -// -// This file contains routines to extract the current stack trace and associated -// stack frames. These functions are thread-safe and async-signal-safe. -// -// Note that stack trace functionality is platform dependent and requires -// additional support from the compiler/build system in most cases. (That is, -// this functionality generally only works on platforms/builds that have been -// specifically configured to support it.) -// -// Note: stack traces in Abseil that do not utilize a symbolizer will result in -// frames consisting of function addresses rather than human-readable function -// names. (See symbolize.h for information on symbolizing these values.) - -#ifndef ABSL_DEBUGGING_STACKTRACE_H_ -#define ABSL_DEBUGGING_STACKTRACE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// GetStackFrames() -// -// Records program counter values for up to `max_depth` frames, skipping the -// most recent `skip_count` stack frames, stores their corresponding values -// and sizes in `results` and `sizes` buffers, and returns the number of frames -// stored. (Note that the frame generated for the `absl::GetStackFrames()` -// routine itself is also skipped.) -// -// Example: -// -// main() { foo(); } -// foo() { bar(); } -// bar() { -// void* result[10]; -// int sizes[10]; -// int depth = absl::GetStackFrames(result, sizes, 10, 1); -// } -// -// The current stack frame would consist of three function calls: `bar()`, -// `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets -// `skip_count` to `1`, it will skip the frame for `bar()`, the most recently -// invoked function call. It will therefore return 2 and fill `result` with -// program counters within the following functions: -// -// result[0] foo() -// result[1] main() -// -// (Note: in practice, a few more entries after `main()` may be added to account -// for startup processes.) -// -// Corresponding stack frame sizes will also be recorded: -// -// sizes[0] 16 -// sizes[1] 16 -// -// (Stack frame sizes of `16` above are just for illustration purposes.) -// -// Stack frame sizes of 0 or less indicate that those frame sizes couldn't -// be identified. -// -// This routine may return fewer stack frame entries than are -// available. Also note that `result` and `sizes` must both be non-null. -extern int GetStackFrames(void** result, int* sizes, int max_depth, - int skip_count); - -// GetStackFramesWithContext() -// -// Records program counter values obtained from a signal handler. Records -// program counter values for up to `max_depth` frames, skipping the most recent -// `skip_count` stack frames, stores their corresponding values and sizes in -// `results` and `sizes` buffers, and returns the number of frames stored. (Note -// that the frame generated for the `absl::GetStackFramesWithContext()` routine -// itself is also skipped.) -// -// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value -// passed to a signal handler registered via the `sa_sigaction` field of a -// `sigaction` struct. (See -// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may -// help a stack unwinder to provide a better stack trace under certain -// conditions. `uc` may safely be null. -// -// The `min_dropped_frames` output parameter, if non-null, points to the -// location to note any dropped stack frames, if any, due to buffer limitations -// or other reasons. (This value will be set to `0` if no frames were dropped.) -// The number of total stack frames is guaranteed to be >= skip_count + -// max_depth + *min_dropped_frames. -extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth, - int skip_count, const void* uc, - int* min_dropped_frames); - -// GetStackTrace() -// -// Records program counter values for up to `max_depth` frames, skipping the -// most recent `skip_count` stack frames, stores their corresponding values -// in `results`, and returns the number of frames -// stored. Note that this function is similar to `absl::GetStackFrames()` -// except that it returns the stack trace only, and not stack frame sizes. -// -// Example: -// -// main() { foo(); } -// foo() { bar(); } -// bar() { -// void* result[10]; -// int depth = absl::GetStackTrace(result, 10, 1); -// } -// -// This produces: -// -// result[0] foo -// result[1] main -// .... ... -// -// `result` must not be null. -extern int GetStackTrace(void** result, int max_depth, int skip_count); - -// GetStackTraceWithContext() -// -// Records program counter values obtained from a signal handler. Records -// program counter values for up to `max_depth` frames, skipping the most recent -// `skip_count` stack frames, stores their corresponding values in `results`, -// and returns the number of frames stored. (Note that the frame generated for -// the `absl::GetStackFramesWithContext()` routine itself is also skipped.) -// -// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value -// passed to a signal handler registered via the `sa_sigaction` field of a -// `sigaction` struct. (See -// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may -// help a stack unwinder to provide a better stack trace under certain -// conditions. `uc` may safely be null. -// -// The `min_dropped_frames` output parameter, if non-null, points to the -// location to note any dropped stack frames, if any, due to buffer limitations -// or other reasons. (This value will be set to `0` if no frames were dropped.) -// The number of total stack frames is guaranteed to be >= skip_count + -// max_depth + *min_dropped_frames. -extern int GetStackTraceWithContext(void** result, int max_depth, - int skip_count, const void* uc, - int* min_dropped_frames); - -// SetStackUnwinder() -// -// Provides a custom function for unwinding stack frames that will be used in -// place of the default stack unwinder when invoking the static -// GetStack{Frames,Trace}{,WithContext}() functions above. -// -// The arguments passed to the unwinder function will match the -// arguments passed to `absl::GetStackFramesWithContext()` except that sizes -// will be non-null iff the caller is interested in frame sizes. -// -// If unwinder is set to null, we revert to the default stack-tracing behavior. -// -// ***************************************************************************** -// WARNING -// ***************************************************************************** -// -// absl::SetStackUnwinder is not suitable for general purpose use. It is -// provided for custom runtimes. -// Some things to watch out for when calling `absl::SetStackUnwinder()`: -// -// (a) The unwinder may be called from within signal handlers and -// therefore must be async-signal-safe. -// -// (b) Even after a custom stack unwinder has been unregistered, other -// threads may still be in the process of using that unwinder. -// Therefore do not clean up any state that may be needed by an old -// unwinder. -// ***************************************************************************** -extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes, - int max_depth, int skip_count, - const void* uc, - int* min_dropped_frames)); - -// DefaultStackUnwinder() -// -// Records program counter values of up to `max_depth` frames, skipping the most -// recent `skip_count` stack frames, and stores their corresponding values in -// `pcs`. (Note that the frame generated for this call itself is also skipped.) -// This function acts as a generic stack-unwinder; prefer usage of the more -// specific `GetStack{Trace,Frames}{,WithContext}()` functions above. -// -// If you have set your own stack unwinder (with the `SetStackUnwinder()` -// function above, you can still get the default stack unwinder by calling -// `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder -// and use the default one instead. -// -// Because this function is generic, only `pcs` is guaranteed to be non-null -// upon return. It is legal for `sizes`, `uc`, and `min_dropped_frames` to all -// be null when called. -// -// The semantics are the same as the corresponding `GetStack*()` function in the -// case where `absl::SetStackUnwinder()` was never called. Equivalents are: -// -// null sizes | non-nullptr sizes -// |==========================================================| -// null uc | GetStackTrace() | GetStackFrames() | -// non-null uc | GetStackTraceWithContext() | GetStackFramesWithContext() | -// |==========================================================| -extern int DefaultStackUnwinder(void** pcs, int* sizes, int max_depth, - int skip_count, const void* uc, - int* min_dropped_frames); - -namespace debugging_internal { -// Returns true for platforms which are expected to have functioning stack trace -// implementations. Intended to be used for tests which want to exclude -// verification of logic known to be broken because stack traces are not -// working. -extern bool StackTraceWorksForTest(); -} // namespace debugging_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_STACKTRACE_H_ diff --git a/third_party/abseil_cpp/absl/debugging/symbolize.cc b/third_party/abseil_cpp/absl/debugging/symbolize.cc deleted file mode 100644 index 5e4a25d69dce..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize.cc +++ /dev/null @@ -1,36 +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/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) -// The Windows Symbolizer only works if PDB files containing the debug info -// are available to the program at runtime. -#include "absl/debugging/symbolize_win32.inc" -#elif defined(__APPLE__) -#include "absl/debugging/symbolize_darwin.inc" -#else -#include "absl/debugging/symbolize_unimplemented.inc" -#endif diff --git a/third_party/abseil_cpp/absl/debugging/symbolize.h b/third_party/abseil_cpp/absl/debugging/symbolize.h deleted file mode 100644 index 43d93a86822e..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize.h +++ /dev/null @@ -1,99 +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: symbolize.h -// ----------------------------------------------------------------------------- -// -// This file configures the Abseil symbolizer for use in converting instruction -// pointer addresses (program counters) into human-readable names (function -// calls, etc.) within Abseil code. -// -// The symbolizer may be invoked from several sources: -// -// * Implicitly, through the installation of an Abseil failure signal handler. -// (See failure_signal_handler.h for more information.) -// * By calling `Symbolize()` directly on a program counter you obtain through -// `absl::GetStackTrace()` or `absl::GetStackFrames()`. (See stacktrace.h -// for more information. -// * By calling `Symbolize()` directly on a program counter you obtain through -// other means (which would be platform-dependent). -// -// In all of the above cases, the symbolizer must first be initialized before -// any program counter values can be symbolized. If you are installing a failure -// signal handler, initialize the symbolizer before you do so. -// -// Example: -// -// int main(int argc, char** argv) { -// // Initialize the Symbolizer before installing the failure signal handler -// absl::InitializeSymbolizer(argv[0]); -// -// // Now you may install the failure signal handler -// absl::FailureSignalHandlerOptions options; -// absl::InstallFailureSignalHandler(options); -// -// // Start running your main program -// ... -// return 0; -// } -// -#ifndef ABSL_DEBUGGING_SYMBOLIZE_H_ -#define ABSL_DEBUGGING_SYMBOLIZE_H_ - -#include "absl/debugging/internal/symbolize.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// InitializeSymbolizer() -// -// Initializes the program counter symbolizer, given the path of the program -// (typically obtained through `main()`s `argv[0]`). The Abseil symbolizer -// allows you to read program counters (instruction pointer values) using their -// human-readable names within output such as stack traces. -// -// Example: -// -// int main(int argc, char *argv[]) { -// absl::InitializeSymbolizer(argv[0]); -// // Now you can use the symbolizer -// } -void InitializeSymbolizer(const char* argv0); -// -// Symbolize() -// -// Symbolizes a program counter (instruction pointer value) `pc` and, on -// success, writes the name to `out`. The symbol name is demangled, if possible. -// Note that the symbolized name may be truncated and will be NUL-terminated. -// Demangling is supported for symbols generated by GCC 3.x or newer). Returns -// `false` on failure. -// -// Example: -// -// // Print a program counter and its symbol name. -// static void DumpPCAndSymbol(void *pc) { -// char tmp[1024]; -// const char *symbol = "(unknown)"; -// if (absl::Symbolize(pc, tmp, sizeof(tmp))) { -// symbol = tmp; -// } -// absl::PrintF("%p %s\n", pc, symbol); -// } -bool Symbolize(const void *pc, char *out, int out_size); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_DEBUGGING_SYMBOLIZE_H_ diff --git a/third_party/abseil_cpp/absl/debugging/symbolize_darwin.inc b/third_party/abseil_cpp/absl/debugging/symbolize_darwin.inc deleted file mode 100644 index 443ce9efc4ce..000000000000 --- 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 deleted file mode 100644 index f4d5727bdeb5..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize_elf.inc +++ /dev/null @@ -1,1560 +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. - -// This library provides Symbolize() function that symbolizes program -// counters to their corresponding symbol names on linux platforms. -// This library has a minimal implementation of an ELF symbol table -// reader (i.e. it doesn't depend on libelf, etc.). -// -// The algorithm used in Symbolize() is as follows. -// -// 1. Go through a list of maps in /proc/self/maps and find the map -// containing the program counter. -// -// 2. Open the mapped file and find a regular symbol table inside. -// Iterate over symbols in the symbol table and look for the symbol -// containing the program counter. If such a symbol is found, -// obtain the symbol name, and demangle the symbol if possible. -// If the symbol isn't found in the regular symbol table (binary is -// stripped), try the same thing with a dynamic symbol table. -// -// Note that Symbolize() is originally implemented to be used in -// signal handlers, hence it doesn't use malloc() and other unsafe -// operations. It should be both thread-safe and async-signal-safe. -// -// Implementation note: -// -// We don't use heaps but only use stacks. We want to reduce the -// stack consumption so that the symbolizer can run on small stacks. -// -// Here are some numbers collected with GCC 4.1.0 on x86: -// - sizeof(Elf32_Sym) = 16 -// - sizeof(Elf32_Shdr) = 40 -// - sizeof(Elf64_Sym) = 24 -// - sizeof(Elf64_Shdr) = 64 -// -// This implementation is intended to be async-signal-safe but uses some -// functions which are not guaranteed to be so, such as memchr() and -// memmove(). We assume they are async-signal-safe. - -#include <dlfcn.h> -#include <elf.h> -#include <fcntl.h> -#include <link.h> // For ElfW() macro. -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <algorithm> -#include <array> -#include <atomic> -#include <cerrno> -#include <cinttypes> -#include <climits> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> - -#include "absl/base/casts.h" -#include "absl/base/dynamic_annotations.h" -#include "absl/base/internal/low_level_alloc.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" -#include "absl/base/port.h" -#include "absl/debugging/internal/demangle.h" -#include "absl/debugging/internal/vdso_support.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Value of argv[0]. Used by MaybeInitializeObjFile(). -static char *argv0_value = nullptr; - -void InitializeSymbolizer(const char *argv0) { -#ifdef ABSL_HAVE_VDSO_SUPPORT - // We need to make sure VDSOSupport::Init() is called before any setuid or - // chroot calls, so InitializeSymbolizer() should be called very early in the - // life of a program. - absl::debugging_internal::VDSOSupport::Init(); -#endif - if (argv0_value != nullptr) { - free(argv0_value); - argv0_value = nullptr; - } - if (argv0 != nullptr && argv0[0] != '\0') { - argv0_value = strdup(argv0); - } -} - -namespace debugging_internal { -namespace { - -// Re-runs fn until it doesn't cause EINTR. -#define NO_INTR(fn) \ - do { \ - } while ((fn) < 0 && errno == EINTR) - -// On Linux, ELF_ST_* are defined in <linux/elf.h>. To make this portable -// we define our own ELF_ST_BIND and ELF_ST_TYPE if not available. -#ifndef ELF_ST_BIND -#define ELF_ST_BIND(info) (((unsigned char)(info)) >> 4) -#endif - -#ifndef ELF_ST_TYPE -#define ELF_ST_TYPE(info) (((unsigned char)(info)) & 0xF) -#endif - -// Some platforms use a special .opd section to store function pointers. -const char kOpdSectionName[] = ".opd"; - -#if (defined(__powerpc__) && !(_CALL_ELF > 1)) || defined(__ia64) -// Use opd section for function descriptors on these platforms, the function -// address is the first word of the descriptor. -enum { kPlatformUsesOPDSections = 1 }; -#else // not PPC or IA64 -enum { kPlatformUsesOPDSections = 0 }; -#endif - -// This works for PowerPC & IA64 only. A function descriptor consist of two -// pointers and the first one is the function's entry. -const size_t kFunctionDescriptorSize = sizeof(void *) * 2; - -const int kMaxDecorators = 10; // Seems like a reasonable upper limit. - -struct InstalledSymbolDecorator { - SymbolDecorator fn; - void *arg; - int ticket; -}; - -int g_num_decorators; -InstalledSymbolDecorator g_decorators[kMaxDecorators]; - -struct FileMappingHint { - const void *start; - const void *end; - uint64_t offset; - const char *filename; -}; - -// Protects g_decorators. -// We are using SpinLock and not a Mutex here, because we may be called -// from inside Mutex::Lock itself, and it prohibits recursive calls. -// This happens in e.g. base/stacktrace_syscall_unittest. -// 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); - -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); - -// Async-signal-safe function to zero a buffer. -// memset() is not guaranteed to be async-signal-safe. -static void SafeMemZero(void* p, size_t size) { - unsigned char *c = static_cast<unsigned char *>(p); - while (size--) { - *c++ = 0; - } -} - -struct ObjFile { - ObjFile() - : filename(nullptr), - start_addr(nullptr), - end_addr(nullptr), - offset(0), - fd(-1), - elf_type(-1) { - SafeMemZero(&elf_header, sizeof(elf_header)); - SafeMemZero(&phdr[0], sizeof(phdr)); - } - - char *filename; - const void *start_addr; - const void *end_addr; - uint64_t offset; - - // The following fields are initialized on the first access to the - // object file. - 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 -// are replaced in LRU order. -enum { - ASSOCIATIVITY = 4, -}; -struct SymbolCacheLine { - const void *pc[ASSOCIATIVITY]; - char *name[ASSOCIATIVITY]; - - // age[i] is incremented when a line is accessed. it's reset to zero if the - // i'th entry is read. - uint32_t age[ASSOCIATIVITY]; -}; - -// --------------------------------------------------------------- -// An async-signal-safe arena for LowLevelAlloc -static std::atomic<base_internal::LowLevelAlloc::Arena *> g_sig_safe_arena; - -static base_internal::LowLevelAlloc::Arena *SigSafeArena() { - return g_sig_safe_arena.load(std::memory_order_acquire); -} - -static void InitSigSafeArena() { - if (SigSafeArena() == nullptr) { - base_internal::LowLevelAlloc::Arena *new_arena = - base_internal::LowLevelAlloc::NewArena( - base_internal::LowLevelAlloc::kAsyncSignalSafe); - base_internal::LowLevelAlloc::Arena *old_value = nullptr; - if (!g_sig_safe_arena.compare_exchange_strong(old_value, new_arena, - std::memory_order_release, - std::memory_order_relaxed)) { - // We lost a race to allocate an arena; deallocate. - base_internal::LowLevelAlloc::DeleteArena(new_arena); - } - } -} - -// --------------------------------------------------------------- -// An AddrMap is a vector of ObjFile, using SigSafeArena() for allocation. - -class AddrMap { - public: - AddrMap() : size_(0), allocated_(0), obj_(nullptr) {} - ~AddrMap() { base_internal::LowLevelAlloc::Free(obj_); } - int Size() const { return size_; } - ObjFile *At(int i) { return &obj_[i]; } - ObjFile *Add(); - void Clear(); - - private: - int size_; // count of valid elements (<= allocated_) - int allocated_; // count of allocated elements - ObjFile *obj_; // array of allocated_ elements - AddrMap(const AddrMap &) = delete; - AddrMap &operator=(const AddrMap &) = delete; -}; - -void AddrMap::Clear() { - for (int i = 0; i != size_; i++) { - At(i)->~ObjFile(); - } - size_ = 0; -} - -ObjFile *AddrMap::Add() { - if (size_ == allocated_) { - int new_allocated = allocated_ * 2 + 50; - ObjFile *new_obj_ = - static_cast<ObjFile *>(base_internal::LowLevelAlloc::AllocWithArena( - new_allocated * sizeof(*new_obj_), SigSafeArena())); - if (obj_) { - memcpy(new_obj_, obj_, allocated_ * sizeof(*new_obj_)); - base_internal::LowLevelAlloc::Free(obj_); - } - obj_ = new_obj_; - allocated_ = new_allocated; - } - return new (&obj_[size_++]) ObjFile; -} - -// --------------------------------------------------------------- - -enum FindSymbolResult { SYMBOL_NOT_FOUND = 1, SYMBOL_TRUNCATED, SYMBOL_FOUND }; - -class Symbolizer { - public: - Symbolizer(); - ~Symbolizer(); - const char *GetSymbol(const void *const pc); - - private: - char *CopyString(const char *s) { - int len = strlen(s); - char *dst = static_cast<char *>( - base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena())); - ABSL_RAW_CHECK(dst != nullptr, "out of memory"); - memcpy(dst, s, len + 1); - return dst; - } - ObjFile *FindObjFile(const void *const start, - size_t size) ABSL_ATTRIBUTE_NOINLINE; - static bool RegisterObjFile(const char *filename, - const void *const start_addr, - const void *const end_addr, uint64_t offset, - void *arg); - SymbolCacheLine *GetCacheLine(const void *const pc); - const char *FindSymbolInCache(const void *const pc); - const char *InsertSymbolInCache(const void *const pc, const char *name); - void AgeSymbols(SymbolCacheLine *line); - void ClearAddrMap(); - FindSymbolResult GetSymbolFromObjectFile(const ObjFile &obj, - const void *const pc, - const ptrdiff_t relocation, - char *out, int out_size, - char *tmp_buf, int tmp_buf_size); - - enum { - SYMBOL_BUF_SIZE = 3072, - TMP_BUF_SIZE = 1024, - SYMBOL_CACHE_LINES = 128, - }; - - AddrMap addr_map_; - - bool ok_; - bool addr_map_read_; - - char symbol_buf_[SYMBOL_BUF_SIZE]; - - // tmp_buf_ will be used to store arrays of ElfW(Shdr) and ElfW(Sym) - // so we ensure that tmp_buf_ is properly aligned to store either. - alignas(16) char tmp_buf_[TMP_BUF_SIZE]; - static_assert(alignof(ElfW(Shdr)) <= 16, - "alignment of tmp buf too small for Shdr"); - static_assert(alignof(ElfW(Sym)) <= 16, - "alignment of tmp buf too small for Sym"); - - SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES]; -}; - -static std::atomic<Symbolizer *> g_cached_symbolizer; - -} // namespace - -static int SymbolizerSize() { -#if defined(__wasm__) || defined(__asmjs__) - int pagesize = getpagesize(); -#else - int pagesize = sysconf(_SC_PAGESIZE); -#endif - return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize; -} - -// Return (and set null) g_cached_symbolized_state if it is not null. -// Otherwise return a new symbolizer. -static Symbolizer *AllocateSymbolizer() { - InitSigSafeArena(); - Symbolizer *symbolizer = - g_cached_symbolizer.exchange(nullptr, std::memory_order_acquire); - if (symbolizer != nullptr) { - return symbolizer; - } - return new (base_internal::LowLevelAlloc::AllocWithArena( - SymbolizerSize(), SigSafeArena())) Symbolizer(); -} - -// Set g_cached_symbolize_state to s if it is null, otherwise -// delete s. -static void FreeSymbolizer(Symbolizer *s) { - Symbolizer *old_cached_symbolizer = nullptr; - if (!g_cached_symbolizer.compare_exchange_strong(old_cached_symbolizer, s, - std::memory_order_release, - std::memory_order_relaxed)) { - s->~Symbolizer(); - base_internal::LowLevelAlloc::Free(s); - } -} - -Symbolizer::Symbolizer() : ok_(true), addr_map_read_(false) { - for (SymbolCacheLine &symbol_cache_line : symbol_cache_) { - for (size_t j = 0; j < ABSL_ARRAYSIZE(symbol_cache_line.name); ++j) { - symbol_cache_line.pc[j] = nullptr; - symbol_cache_line.name[j] = nullptr; - symbol_cache_line.age[j] = 0; - } - } -} - -Symbolizer::~Symbolizer() { - for (SymbolCacheLine &symbol_cache_line : symbol_cache_) { - for (char *s : symbol_cache_line.name) { - base_internal::LowLevelAlloc::Free(s); - } - } - ClearAddrMap(); -} - -// We don't use assert() since it's not guaranteed to be -// async-signal-safe. Instead we define a minimal assertion -// macro. So far, we don't need pretty printing for __FILE__, etc. -#define SAFE_ASSERT(expr) ((expr) ? static_cast<void>(0) : abort()) - -// Read up to "count" bytes from file descriptor "fd" into the buffer -// starting at "buf" while handling short reads and EINTR. On -// success, return the number of bytes read. Otherwise, return -1. -static ssize_t ReadPersistent(int fd, void *buf, size_t count) { - SAFE_ASSERT(fd >= 0); - SAFE_ASSERT(count <= SSIZE_MAX); - char *buf0 = reinterpret_cast<char *>(buf); - size_t num_bytes = 0; - while (num_bytes < count) { - ssize_t len; - NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes)); - if (len < 0) { // There was an error other than EINTR. - ABSL_RAW_LOG(WARNING, "read failed: errno=%d", errno); - return -1; - } - if (len == 0) { // Reached EOF. - break; - } - num_bytes += len; - } - SAFE_ASSERT(num_bytes <= count); - return static_cast<ssize_t>(num_bytes); -} - -// Read up to "count" bytes from "offset" in the file pointed by file -// descriptor "fd" into the buffer starting at "buf". On success, -// return the number of bytes read. Otherwise, return -1. -static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count, - const off_t offset) { - off_t off = lseek(fd, offset, SEEK_SET); - if (off == (off_t)-1) { - ABSL_RAW_LOG(WARNING, "lseek(%d, %ju, SEEK_SET) failed: errno=%d", fd, - static_cast<uintmax_t>(offset), errno); - return -1; - } - return ReadPersistent(fd, buf, count); -} - -// Try reading exactly "count" bytes from "offset" bytes in a file -// pointed by "fd" into the buffer starting at "buf" while handling -// short reads and EINTR. On success, return true. Otherwise, return -// false. -static bool ReadFromOffsetExact(const int fd, void *buf, const size_t count, - const off_t offset) { - ssize_t len = ReadFromOffset(fd, buf, count, offset); - return len >= 0 && static_cast<size_t>(len) == count; -} - -// Returns elf_header.e_type if the file pointed by fd is an ELF binary. -static int FileGetElfType(const int fd) { - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return -1; - } - if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) { - return -1; - } - return elf_header.e_type; -} - -// Read the section headers in the given ELF binary, and if a section -// of the specified type is found, set the output to this section header -// and return true. Otherwise, return false. -// To keep stack consumption low, we would like this function to not get -// inlined. -static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType( - const int fd, ElfW(Half) sh_num, const off_t sh_offset, ElfW(Word) type, - ElfW(Shdr) * out, char *tmp_buf, int tmp_buf_size) { - ElfW(Shdr) *buf = reinterpret_cast<ElfW(Shdr) *>(tmp_buf); - const int buf_entries = tmp_buf_size / sizeof(buf[0]); - const int buf_bytes = buf_entries * sizeof(buf[0]); - - for (int i = 0; i < sh_num;) { - const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]); - const ssize_t num_bytes_to_read = - (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes; - const off_t offset = sh_offset + i * sizeof(buf[0]); - const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read, offset); - if (len % sizeof(buf[0]) != 0) { - ABSL_RAW_LOG( - WARNING, - "Reading %zd bytes from offset %ju returned %zd which is not a " - "multiple of %zu.", - num_bytes_to_read, static_cast<uintmax_t>(offset), len, - sizeof(buf[0])); - return false; - } - const ssize_t num_headers_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_headers_in_buf <= buf_entries); - for (int j = 0; j < num_headers_in_buf; ++j) { - if (buf[j].sh_type == type) { - *out = buf[j]; - return true; - } - } - i += num_headers_in_buf; - } - return false; -} - -// There is no particular reason to limit section name to 63 characters, -// but there has (as yet) been no need for anything longer either. -const int kMaxSectionNameLen = 64; - -bool ForEachSection(int fd, - const std::function<bool(absl::string_view name, - const ElfW(Shdr) &)> &callback) { - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return false; - } - - ElfW(Shdr) shstrtab; - off_t shstrtab_offset = - (elf_header.e_shoff + elf_header.e_shentsize * elf_header.e_shstrndx); - if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) { - return false; - } - - for (int i = 0; i < elf_header.e_shnum; ++i) { - ElfW(Shdr) out; - off_t section_header_offset = - (elf_header.e_shoff + elf_header.e_shentsize * i); - if (!ReadFromOffsetExact(fd, &out, sizeof(out), section_header_offset)) { - return false; - } - off_t name_offset = shstrtab.sh_offset + out.sh_name; - char header_name[kMaxSectionNameLen]; - ssize_t n_read = - ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset); - if (n_read == -1) { - return false; - } else if (n_read > kMaxSectionNameLen) { - // Long read? - return false; - } - - absl::string_view name(header_name, strnlen(header_name, n_read)); - if (!callback(name, out)) { - break; - } - } - return true; -} - -// name_len should include terminating '\0'. -bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, - ElfW(Shdr) * out) { - char header_name[kMaxSectionNameLen]; - if (sizeof(header_name) < name_len) { - ABSL_RAW_LOG(WARNING, - "Section name '%s' is too long (%zu); " - "section will not be found (even if present).", - name, name_len); - // No point in even trying. - return false; - } - - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return false; - } - - ElfW(Shdr) shstrtab; - off_t shstrtab_offset = - (elf_header.e_shoff + elf_header.e_shentsize * elf_header.e_shstrndx); - if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) { - return false; - } - - for (int i = 0; i < elf_header.e_shnum; ++i) { - off_t section_header_offset = - (elf_header.e_shoff + elf_header.e_shentsize * i); - if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) { - return false; - } - off_t name_offset = shstrtab.sh_offset + out->sh_name; - ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset); - if (n_read < 0) { - return false; - } else if (static_cast<size_t>(n_read) != name_len) { - // Short read -- name could be at end of file. - continue; - } - if (memcmp(header_name, name, name_len) == 0) { - return true; - } - } - return false; -} - -// Compare symbols at in the same address. -// Return true if we should pick symbol1. -static bool ShouldPickFirstSymbol(const ElfW(Sym) & symbol1, - const ElfW(Sym) & symbol2) { - // If one of the symbols is weak and the other is not, pick the one - // this is not a weak symbol. - char bind1 = ELF_ST_BIND(symbol1.st_info); - char bind2 = ELF_ST_BIND(symbol1.st_info); - if (bind1 == STB_WEAK && bind2 != STB_WEAK) return false; - if (bind2 == STB_WEAK && bind1 != STB_WEAK) return true; - - // If one of the symbols has zero size and the other is not, pick the - // one that has non-zero size. - if (symbol1.st_size != 0 && symbol2.st_size == 0) { - return true; - } - if (symbol1.st_size == 0 && symbol2.st_size != 0) { - return false; - } - - // If one of the symbols has no type and the other is not, pick the - // one that has a type. - char type1 = ELF_ST_TYPE(symbol1.st_info); - char type2 = ELF_ST_TYPE(symbol1.st_info); - if (type1 != STT_NOTYPE && type2 == STT_NOTYPE) { - return true; - } - if (type1 == STT_NOTYPE && type2 != STT_NOTYPE) { - return false; - } - - // Pick the first one, if we still cannot decide. - return true; -} - -// Return true if an address is inside a section. -static bool InSection(const void *address, const ElfW(Shdr) * section) { - const char *start = reinterpret_cast<const char *>(section->sh_addr); - size_t size = static_cast<size_t>(section->sh_size); - return start <= address && address < (start + size); -} - -static const char *ComputeOffset(const char *base, ptrdiff_t offset) { - // Note: cast to uintptr_t to avoid undefined behavior when base evaluates to - // zero and offset is non-zero. - return reinterpret_cast<const char *>( - reinterpret_cast<uintptr_t>(base) + offset); -} - -// Read a symbol table and look for the symbol containing the -// pc. Iterate over symbols in a symbol table and look for the symbol -// containing "pc". If the symbol is found, and its name fits in -// out_size, the name is written into out and SYMBOL_FOUND is returned. -// If the name does not fit, truncated name is written into out, -// and SYMBOL_TRUNCATED is returned. Out is NUL-terminated. -// If the symbol is not found, SYMBOL_NOT_FOUND is returned; -// To keep stack consumption low, we would like this function to not get -// inlined. -static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol( - const void *const pc, const int fd, char *out, int out_size, - ptrdiff_t relocation, const ElfW(Shdr) * strtab, const ElfW(Shdr) * symtab, - const ElfW(Shdr) * opd, char *tmp_buf, int tmp_buf_size) { - if (symtab == nullptr) { - return SYMBOL_NOT_FOUND; - } - - // Read multiple symbols at once to save read() calls. - ElfW(Sym) *buf = reinterpret_cast<ElfW(Sym) *>(tmp_buf); - const int buf_entries = tmp_buf_size / sizeof(buf[0]); - - const int num_symbols = symtab->sh_size / symtab->sh_entsize; - - // On platforms using an .opd section (PowerPC & IA64), a function symbol - // has the address of a function descriptor, which contains the real - // starting address. However, we do not always want to use the real - // starting address because we sometimes want to symbolize a function - // pointer into the .opd section, e.g. FindSymbol(&foo,...). - const bool pc_in_opd = - kPlatformUsesOPDSections && opd != nullptr && InSection(pc, opd); - const bool deref_function_descriptor_pointer = - kPlatformUsesOPDSections && opd != nullptr && !pc_in_opd; - - ElfW(Sym) best_match; - SafeMemZero(&best_match, sizeof(best_match)); - bool found_match = false; - for (int i = 0; i < num_symbols;) { - off_t offset = symtab->sh_offset + i * symtab->sh_entsize; - const int num_remaining_symbols = num_symbols - i; - const int entries_in_chunk = std::min(num_remaining_symbols, buf_entries); - const int bytes_in_chunk = entries_in_chunk * sizeof(buf[0]); - const ssize_t len = ReadFromOffset(fd, buf, bytes_in_chunk, offset); - SAFE_ASSERT(len % sizeof(buf[0]) == 0); - const ssize_t num_symbols_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_symbols_in_buf <= entries_in_chunk); - for (int j = 0; j < num_symbols_in_buf; ++j) { - const ElfW(Sym) &symbol = buf[j]; - - // For a DSO, a symbol address is relocated by the loading address. - // We keep the original address for opd redirection below. - const char *const original_start_address = - reinterpret_cast<const char *>(symbol.st_value); - const char *start_address = - ComputeOffset(original_start_address, relocation); - - if (deref_function_descriptor_pointer && - InSection(original_start_address, opd)) { - // The opd section is mapped into memory. Just dereference - // start_address to get the first double word, which points to the - // function entry. - start_address = *reinterpret_cast<const char *const *>(start_address); - } - - // If pc is inside the .opd section, it points to a function descriptor. - const size_t size = pc_in_opd ? kFunctionDescriptorSize : symbol.st_size; - const void *const end_address = ComputeOffset(start_address, size); - if (symbol.st_value != 0 && // Skip null value symbols. - symbol.st_shndx != 0 && // Skip undefined symbols. -#ifdef STT_TLS - ELF_ST_TYPE(symbol.st_info) != STT_TLS && // Skip thread-local data. -#endif // STT_TLS - ((start_address <= pc && pc < end_address) || - (start_address == pc && pc == end_address))) { - if (!found_match || ShouldPickFirstSymbol(symbol, best_match)) { - found_match = true; - best_match = symbol; - } - } - } - i += num_symbols_in_buf; - } - - if (found_match) { - const size_t off = strtab->sh_offset + best_match.st_name; - const ssize_t n_read = ReadFromOffset(fd, out, out_size, off); - if (n_read <= 0) { - // This should never happen. - ABSL_RAW_LOG(WARNING, - "Unable to read from fd %d at offset %zu: n_read = %zd", fd, - off, n_read); - return SYMBOL_NOT_FOUND; - } - ABSL_RAW_CHECK(n_read <= out_size, "ReadFromOffset read too much data."); - - // strtab->sh_offset points into .strtab-like section that contains - // NUL-terminated strings: '\0foo\0barbaz\0...". - // - // sh_offset+st_name points to the start of symbol name, but we don't know - // how long the symbol is, so we try to read as much as we have space for, - // and usually over-read (i.e. there is a NUL somewhere before n_read). - if (memchr(out, '\0', n_read) == nullptr) { - // Either out_size was too small (n_read == out_size and no NUL), or - // we tried to read past the EOF (n_read < out_size) and .strtab is - // corrupt (missing terminating NUL; should never happen for valid ELF). - out[n_read - 1] = '\0'; - return SYMBOL_TRUNCATED; - } - return SYMBOL_FOUND; - } - - return SYMBOL_NOT_FOUND; -} - -// Get the symbol name of "pc" from the file pointed by "fd". Process -// both regular and dynamic symbol tables if necessary. -// See FindSymbol() comment for description of return value. -FindSymbolResult Symbolizer::GetSymbolFromObjectFile( - const ObjFile &obj, const void *const pc, const ptrdiff_t relocation, - char *out, int out_size, char *tmp_buf, int tmp_buf_size) { - ElfW(Shdr) symtab; - ElfW(Shdr) strtab; - ElfW(Shdr) opd; - ElfW(Shdr) *opd_ptr = nullptr; - - // On platforms using an .opd sections for function descriptor, read - // the section header. The .opd section is in data segment and should be - // loaded but we check that it is mapped just to be extra careful. - if (kPlatformUsesOPDSections) { - if (GetSectionHeaderByName(obj.fd, kOpdSectionName, - sizeof(kOpdSectionName) - 1, &opd) && - FindObjFile(reinterpret_cast<const char *>(opd.sh_addr) + relocation, - opd.sh_size) != nullptr) { - opd_ptr = &opd; - } else { - return SYMBOL_NOT_FOUND; - } - } - - // Consult a regular symbol table, then fall back to the dynamic symbol table. - for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) { - if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum, - obj.elf_header.e_shoff, symbol_table_type, - &symtab, tmp_buf, tmp_buf_size)) { - continue; - } - if (!ReadFromOffsetExact( - obj.fd, &strtab, sizeof(strtab), - obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) { - continue; - } - const FindSymbolResult rc = - FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab, - opd_ptr, tmp_buf, tmp_buf_size); - if (rc != SYMBOL_NOT_FOUND) { - return rc; - } - } - - return SYMBOL_NOT_FOUND; -} - -namespace { -// Thin wrapper around a file descriptor so that the file descriptor -// gets closed for sure. -class FileDescriptor { - public: - explicit FileDescriptor(int fd) : fd_(fd) {} - FileDescriptor(const FileDescriptor &) = delete; - FileDescriptor &operator=(const FileDescriptor &) = delete; - - ~FileDescriptor() { - if (fd_ >= 0) { - NO_INTR(close(fd_)); - } - } - - int get() const { return fd_; } - - private: - const int fd_; -}; - -// Helper class for reading lines from file. -// -// Note: we don't use ProcMapsIterator since the object is big (it has -// a 5k array member) and uses async-unsafe functions such as sscanf() -// and snprintf(). -class LineReader { - public: - explicit LineReader(int fd, char *buf, int buf_len) - : fd_(fd), - buf_len_(buf_len), - buf_(buf), - bol_(buf), - eol_(buf), - eod_(buf) {} - - LineReader(const LineReader &) = delete; - LineReader &operator=(const LineReader &) = delete; - - // Read '\n'-terminated line from file. On success, modify "bol" - // and "eol", then return true. Otherwise, return false. - // - // Note: if the last line doesn't end with '\n', the line will be - // dropped. It's an intentional behavior to make the code simple. - bool ReadLine(const char **bol, const char **eol) { - if (BufferIsEmpty()) { // First time. - const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_); - if (num_bytes <= 0) { // EOF or error. - return false; - } - eod_ = buf_ + num_bytes; - bol_ = buf_; - } else { - bol_ = eol_ + 1; // Advance to the next line in the buffer. - SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_". - if (!HasCompleteLine()) { - const int incomplete_line_length = eod_ - bol_; - // Move the trailing incomplete line to the beginning. - memmove(buf_, bol_, incomplete_line_length); - // Read text from file and append it. - char *const append_pos = buf_ + incomplete_line_length; - const int capacity_left = buf_len_ - incomplete_line_length; - const ssize_t num_bytes = - ReadPersistent(fd_, append_pos, capacity_left); - if (num_bytes <= 0) { // EOF or error. - return false; - } - eod_ = append_pos + num_bytes; - bol_ = buf_; - } - } - eol_ = FindLineFeed(); - if (eol_ == nullptr) { // '\n' not found. Malformed line. - return false; - } - *eol_ = '\0'; // Replace '\n' with '\0'. - - *bol = bol_; - *eol = eol_; - return true; - } - - private: - char *FindLineFeed() const { - return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_)); - } - - bool BufferIsEmpty() const { return buf_ == eod_; } - - bool HasCompleteLine() const { - return !BufferIsEmpty() && FindLineFeed() != nullptr; - } - - const int fd_; - const int buf_len_; - char *const buf_; - char *bol_; - char *eol_; - const char *eod_; // End of data in "buf_". -}; -} // namespace - -// Place the hex number read from "start" into "*hex". The pointer to -// the first non-hex character or "end" is returned. -static const char *GetHex(const char *start, const char *end, - uint64_t *const value) { - uint64_t hex = 0; - const char *p; - for (p = start; p < end; ++p) { - int ch = *p; - if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')) { - hex = (hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9); - } else { // Encountered the first non-hex character. - break; - } - } - SAFE_ASSERT(p <= end); - *value = hex; - return p; -} - -static const char *GetHex(const char *start, const char *end, - const void **const addr) { - uint64_t hex = 0; - const char *p = GetHex(start, end, &hex); - *addr = reinterpret_cast<void *>(hex); - return p; -} - -// Normally we are only interested in "r?x" maps. -// On the PowerPC, function pointers point to descriptors in the .opd -// section. The descriptors themselves are not executable code, so -// we need to relax the check below to "r??". -static bool ShouldUseMapping(const char *const flags) { - return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x'); -} - -// Read /proc/self/maps and run "callback" for each mmapped file found. If -// "callback" returns false, stop scanning and return true. Else continue -// scanning /proc/self/maps. Return true if no parse error is found. -static ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap( - bool (*callback)(const char *filename, const void *const start_addr, - const void *const end_addr, uint64_t offset, void *arg), - void *arg, void *tmp_buf, int tmp_buf_size) { - // Use /proc/self/task/<pid>/maps instead of /proc/self/maps. The latter - // requires kernel to stop all threads, and is significantly slower when there - // are 1000s of threads. - char maps_path[80]; - snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid()); - - int maps_fd; - NO_INTR(maps_fd = open(maps_path, O_RDONLY)); - FileDescriptor wrapped_maps_fd(maps_fd); - if (wrapped_maps_fd.get() < 0) { - ABSL_RAW_LOG(WARNING, "%s: errno=%d", maps_path, errno); - return false; - } - - // Iterate over maps and look for the map containing the pc. Then - // look into the symbol tables inside. - LineReader reader(wrapped_maps_fd.get(), static_cast<char *>(tmp_buf), - tmp_buf_size); - while (true) { - const char *cursor; - const char *eol; - if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. - break; - } - - const char *line = cursor; - const void *start_address; - // Start parsing line in /proc/self/maps. Here is an example: - // - // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat - // - // We want start address (08048000), end address (0804c000), flags - // (r-xp) and file name (/bin/cat). - - // Read start address. - cursor = GetHex(cursor, eol, &start_address); - if (cursor == eol || *cursor != '-') { - ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps line: %s", line); - return false; - } - ++cursor; // Skip '-'. - - // Read end address. - const void *end_address; - cursor = GetHex(cursor, eol, &end_address); - if (cursor == eol || *cursor != ' ') { - ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps line: %s", line); - return false; - } - ++cursor; // Skip ' '. - - // Read flags. Skip flags until we encounter a space or eol. - const char *const flags_start = cursor; - while (cursor < eol && *cursor != ' ') { - ++cursor; - } - // We expect at least four letters for flags (ex. "r-xp"). - if (cursor == eol || cursor < flags_start + 4) { - ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps: %s", line); - return false; - } - - // Check flags. - if (!ShouldUseMapping(flags_start)) { - continue; // We skip this map. - } - ++cursor; // Skip ' '. - - // Read file offset. - uint64_t offset; - cursor = GetHex(cursor, eol, &offset); - ++cursor; // Skip ' '. - - // Skip to file name. "cursor" now points to dev. We need to skip at least - // two spaces for dev and inode. - int num_spaces = 0; - while (cursor < eol) { - if (*cursor == ' ') { - ++num_spaces; - } else if (num_spaces >= 2) { - // The first non-space character after skipping two spaces - // is the beginning of the file name. - break; - } - ++cursor; - } - - // Check whether this entry corresponds to our hint table for the true - // filename. - bool hinted = - GetFileMappingHint(&start_address, &end_address, &offset, &cursor); - if (!hinted && (cursor == eol || cursor[0] == '[')) { - // not an object file, typically [vdso] or [vsyscall] - continue; - } - if (!callback(cursor, start_address, end_address, offset, arg)) break; - } - return true; -} - -// Find the objfile mapped in address region containing [addr, addr + len). -ObjFile *Symbolizer::FindObjFile(const void *const addr, size_t len) { - for (int i = 0; i < 2; ++i) { - if (!ok_) return nullptr; - - // Read /proc/self/maps if necessary - if (!addr_map_read_) { - addr_map_read_ = true; - if (!ReadAddrMap(RegisterObjFile, this, tmp_buf_, TMP_BUF_SIZE)) { - ok_ = false; - return nullptr; - } - } - - int lo = 0; - int hi = addr_map_.Size(); - while (lo < hi) { - int mid = (lo + hi) / 2; - if (addr < addr_map_.At(mid)->end_addr) { - hi = mid; - } else { - lo = mid + 1; - } - } - if (lo != addr_map_.Size()) { - ObjFile *obj = addr_map_.At(lo); - SAFE_ASSERT(obj->end_addr > addr); - if (addr >= obj->start_addr && - reinterpret_cast<const char *>(addr) + len <= obj->end_addr) - return obj; - } - - // The address mapping may have changed since it was last read. Retry. - ClearAddrMap(); - } - return nullptr; -} - -void Symbolizer::ClearAddrMap() { - for (int i = 0; i != addr_map_.Size(); i++) { - ObjFile *o = addr_map_.At(i); - base_internal::LowLevelAlloc::Free(o->filename); - if (o->fd >= 0) { - NO_INTR(close(o->fd)); - } - } - addr_map_.Clear(); - addr_map_read_ = false; -} - -// Callback for ReadAddrMap to register objfiles in an in-memory table. -bool Symbolizer::RegisterObjFile(const char *filename, - const void *const start_addr, - const void *const end_addr, uint64_t offset, - void *arg) { - Symbolizer *impl = static_cast<Symbolizer *>(arg); - - // Files are supposed to be added in the increasing address order. Make - // sure that's the case. - int addr_map_size = impl->addr_map_.Size(); - if (addr_map_size != 0) { - ObjFile *old = impl->addr_map_.At(addr_map_size - 1); - if (old->end_addr > end_addr) { - ABSL_RAW_LOG(ERROR, - "Unsorted addr map entry: 0x%" PRIxPTR ": %s <-> 0x%" PRIxPTR - ": %s", - reinterpret_cast<uintptr_t>(end_addr), filename, - reinterpret_cast<uintptr_t>(old->end_addr), old->filename); - return true; - } else if (old->end_addr == end_addr) { - // The same entry appears twice. This sometimes happens for [vdso]. - if (old->start_addr != start_addr || - strcmp(old->filename, filename) != 0) { - ABSL_RAW_LOG(ERROR, - "Duplicate addr 0x%" PRIxPTR ": %s <-> 0x%" PRIxPTR ": %s", - reinterpret_cast<uintptr_t>(end_addr), filename, - reinterpret_cast<uintptr_t>(old->end_addr), old->filename); - } - return true; - } - } - ObjFile *obj = impl->addr_map_.Add(); - obj->filename = impl->CopyString(filename); - obj->start_addr = start_addr; - obj->end_addr = end_addr; - obj->offset = offset; - obj->elf_type = -1; // filled on demand - obj->fd = -1; // opened on demand - return true; -} - -// This function wraps the Demangle function to provide an interface -// where the input symbol is demangled in-place. -// To keep stack consumption low, we would like this function to not -// get inlined. -static ABSL_ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size, - char *tmp_buf, - int tmp_buf_size) { - if (Demangle(out, tmp_buf, tmp_buf_size)) { - // Demangling succeeded. Copy to out if the space allows. - int len = strlen(tmp_buf); - if (len + 1 <= out_size) { // +1 for '\0'. - SAFE_ASSERT(len < tmp_buf_size); - memmove(out, tmp_buf, len + 1); - } - } -} - -SymbolCacheLine *Symbolizer::GetCacheLine(const void *const pc) { - uintptr_t pc0 = reinterpret_cast<uintptr_t>(pc); - pc0 >>= 3; // drop the low 3 bits - - // Shuffle bits. - pc0 ^= (pc0 >> 6) ^ (pc0 >> 12) ^ (pc0 >> 18); - return &symbol_cache_[pc0 % SYMBOL_CACHE_LINES]; -} - -void Symbolizer::AgeSymbols(SymbolCacheLine *line) { - for (uint32_t &age : line->age) { - ++age; - } -} - -const char *Symbolizer::FindSymbolInCache(const void *const pc) { - if (pc == nullptr) return nullptr; - - SymbolCacheLine *line = GetCacheLine(pc); - for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) { - if (line->pc[i] == pc) { - AgeSymbols(line); - line->age[i] = 0; - return line->name[i]; - } - } - return nullptr; -} - -const char *Symbolizer::InsertSymbolInCache(const void *const pc, - const char *name) { - SAFE_ASSERT(pc != nullptr); - - SymbolCacheLine *line = GetCacheLine(pc); - uint32_t max_age = 0; - int oldest_index = -1; - for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) { - if (line->pc[i] == nullptr) { - AgeSymbols(line); - line->pc[i] = pc; - line->name[i] = CopyString(name); - line->age[i] = 0; - return line->name[i]; - } - if (line->age[i] >= max_age) { - max_age = line->age[i]; - oldest_index = i; - } - } - - AgeSymbols(line); - ABSL_RAW_CHECK(oldest_index >= 0, "Corrupt cache"); - base_internal::LowLevelAlloc::Free(line->name[oldest_index]); - line->pc[oldest_index] = pc; - line->name[oldest_index] = CopyString(name); - line->age[oldest_index] = 0; - return line->name[oldest_index]; -} - -static void MaybeOpenFdFromSelfExe(ObjFile *obj) { - if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) { - return; - } - int fd = open("/proc/self/exe", O_RDONLY); - if (fd == -1) { - return; - } - // Verify that contents of /proc/self/exe matches in-memory image of - // the binary. This can fail if the "deleted" binary is in fact not - // the main executable, or for binaries that have the first PT_LOAD - // segment smaller than 4K. We do it in four steps so that the - // buffer is smaller and we don't consume too much stack space. - const char *mem = reinterpret_cast<const char *>(obj->start_addr); - for (int i = 0; i < 4; ++i) { - char buf[1024]; - ssize_t n = read(fd, buf, sizeof(buf)); - if (n != sizeof(buf) || memcmp(buf, mem, sizeof(buf)) != 0) { - close(fd); - return; - } - mem += sizeof(buf); - } - obj->fd = fd; -} - -static bool MaybeInitializeObjFile(ObjFile *obj) { - if (obj->fd < 0) { - obj->fd = open(obj->filename, O_RDONLY); - - if (obj->fd < 0) { - // Getting /proc/self/exe here means that we were hinted. - if (strcmp(obj->filename, "/proc/self/exe") == 0) { - // /proc/self/exe may be inaccessible (due to setuid, etc.), so try - // accessing the binary via argv0. - if (argv0_value != nullptr) { - obj->fd = open(argv0_value, O_RDONLY); - } - } else { - MaybeOpenFdFromSelfExe(obj); - } - } - - if (obj->fd < 0) { - ABSL_RAW_LOG(WARNING, "%s: open failed: errno=%d", obj->filename, errno); - return false; - } - obj->elf_type = FileGetElfType(obj->fd); - if (obj->elf_type < 0) { - ABSL_RAW_LOG(WARNING, "%s: wrong elf type: %d", obj->filename, - obj->elf_type); - return false; - } - - if (!ReadFromOffsetExact(obj->fd, &obj->elf_header, sizeof(obj->elf_header), - 0)) { - 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; -} - -// The implementation of our symbolization routine. If it -// successfully finds the symbol containing "pc" and obtains the -// symbol name, returns pointer to that symbol. Otherwise, returns nullptr. -// If any symbol decorators have been installed via InstallSymbolDecorator(), -// they are called here as well. -// To keep stack consumption low, we would like this function to not -// get inlined. -const char *Symbolizer::GetSymbol(const void *const pc) { - const char *entry = FindSymbolInCache(pc); - if (entry != nullptr) { - return entry; - } - symbol_buf_[0] = '\0'; - - ObjFile *const obj = FindObjFile(pc, 1); - ptrdiff_t relocation = 0; - 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) { - // 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; - } - } - - 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_)); - } - } - } else { -#if ABSL_HAVE_VDSO_SUPPORT - VDSOSupport vdso; - if (vdso.IsPresent()) { - VDSOSupport::SymbolInfo symbol_info; - if (vdso.LookupSymbolByAddress(pc, &symbol_info)) { - // All VDSO symbols are known to be short. - size_t len = strlen(symbol_info.name); - ABSL_RAW_CHECK(len + 1 < sizeof(symbol_buf_), - "VDSO symbol unexpectedly long"); - memcpy(symbol_buf_, symbol_info.name, len + 1); - } - } -#endif - } - - if (g_decorators_mu.TryLock()) { - if (g_num_decorators > 0) { - SymbolDecoratorArgs decorator_args = { - pc, relocation, fd, symbol_buf_, sizeof(symbol_buf_), - tmp_buf_, sizeof(tmp_buf_), nullptr}; - for (int i = 0; i < g_num_decorators; ++i) { - decorator_args.arg = g_decorators[i].arg; - g_decorators[i].fn(&decorator_args); - } - } - g_decorators_mu.Unlock(); - } - if (symbol_buf_[0] == '\0') { - return nullptr; - } - symbol_buf_[sizeof(symbol_buf_) - 1] = '\0'; // Paranoia. - return InsertSymbolInCache(pc, symbol_buf_); -} - -bool RemoveAllSymbolDecorators(void) { - if (!g_decorators_mu.TryLock()) { - // Someone else is using decorators. Get out. - return false; - } - g_num_decorators = 0; - g_decorators_mu.Unlock(); - return true; -} - -bool RemoveSymbolDecorator(int ticket) { - if (!g_decorators_mu.TryLock()) { - // Someone else is using decorators. Get out. - return false; - } - for (int i = 0; i < g_num_decorators; ++i) { - if (g_decorators[i].ticket == ticket) { - while (i < g_num_decorators - 1) { - g_decorators[i] = g_decorators[i + 1]; - ++i; - } - g_num_decorators = i; - break; - } - } - g_decorators_mu.Unlock(); - return true; // Decorator is known to be removed. -} - -int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) { - static int ticket = 0; - - if (!g_decorators_mu.TryLock()) { - // Someone else is using decorators. Get out. - return -2; - } - int ret = ticket; - if (g_num_decorators >= kMaxDecorators) { - ret = -1; - } else { - g_decorators[g_num_decorators] = {decorator, arg, ticket++}; - ++g_num_decorators; - } - g_decorators_mu.Unlock(); - return ret; -} - -bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset, - const char *filename) { - SAFE_ASSERT(start <= end); - SAFE_ASSERT(filename != nullptr); - - InitSigSafeArena(); - - if (!g_file_mapping_mu.TryLock()) { - return false; - } - - bool ret = true; - if (g_num_file_mapping_hints >= kMaxFileMappingHints) { - ret = false; - } else { - // TODO(ckennelly): Move this into a string copy routine. - int len = strlen(filename); - char *dst = static_cast<char *>( - base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena())); - ABSL_RAW_CHECK(dst != nullptr, "out of memory"); - memcpy(dst, filename, len + 1); - - auto &hint = g_file_mapping_hints[g_num_file_mapping_hints++]; - hint.start = start; - hint.end = end; - hint.offset = offset; - hint.filename = dst; - } - - g_file_mapping_mu.Unlock(); - return ret; -} - -bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset, - const char **filename) { - if (!g_file_mapping_mu.TryLock()) { - return false; - } - bool found = false; - for (int i = 0; i < g_num_file_mapping_hints; i++) { - if (g_file_mapping_hints[i].start <= *start && - *end <= g_file_mapping_hints[i].end) { - // We assume that the start_address for the mapping is the base - // address of the ELF section, but when [start_address,end_address) is - // not strictly equal to [hint.start, hint.end), that assumption is - // invalid. - // - // This uses the hint's start address (even though hint.start is not - // necessarily equal to start_address) to ensure the correct - // relocation is computed later. - *start = g_file_mapping_hints[i].start; - *end = g_file_mapping_hints[i].end; - *offset = g_file_mapping_hints[i].offset; - *filename = g_file_mapping_hints[i].filename; - found = true; - break; - } - } - g_file_mapping_mu.Unlock(); - return found; -} - -} // namespace debugging_internal - -bool Symbolize(const void *pc, char *out, int out_size) { - // Symbolization is very slow under tsan. - ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); - SAFE_ASSERT(out_size >= 0); - debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer(); - const char *name = s->GetSymbol(pc); - bool ok = false; - if (name != nullptr && out_size > 0) { - strncpy(out, name, out_size); - ok = true; - if (out[out_size - 1] != '\0') { - // strncpy() does not '\0' terminate when it truncates. Do so, with - // trailing ellipsis. - static constexpr char kEllipsis[] = "..."; - int ellipsis_size = - std::min(implicit_cast<int>(strlen(kEllipsis)), out_size - 1); - memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size); - out[out_size - 1] = '\0'; - } - } - debugging_internal::FreeSymbolizer(s); - ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); - return ok; -} - -ABSL_NAMESPACE_END -} // namespace absl - -extern "C" bool AbslInternalGetFileMappingHint(const void **start, - const void **end, uint64_t *offset, - const char **filename) { - return absl::debugging_internal::GetFileMappingHint(start, end, offset, - filename); -} diff --git a/third_party/abseil_cpp/absl/debugging/symbolize_test.cc b/third_party/abseil_cpp/absl/debugging/symbolize_test.cc deleted file mode 100644 index a2dd4956c497..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize_test.cc +++ /dev/null @@ -1,557 +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/debugging/symbolize.h" - -#ifndef _WIN32 -#include <fcntl.h> -#include <sys/mman.h> -#endif - -#include <cstring> -#include <iostream> -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/casts.h" -#include "absl/base/config.h" -#include "absl/base/internal/per_thread_tls.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/optimization.h" -#include "absl/debugging/internal/stack_consumption.h" -#include "absl/memory/memory.h" -#include "absl/strings/string_view.h" - -using testing::Contains; - -#ifdef _WIN32 -#define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline) -#else -#define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE -#endif - -// Functions to symbolize. Use C linkage to avoid mangled names. -extern "C" { -ABSL_SYMBOLIZE_TEST_NOINLINE void nonstatic_func() { - // The next line makes this a unique function to prevent the compiler from - // folding identical functions together. - volatile int x = __LINE__; - static_cast<void>(x); - ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -} - -ABSL_SYMBOLIZE_TEST_NOINLINE static void static_func() { - // The next line makes this a unique function to prevent the compiler from - // folding identical functions together. - volatile int x = __LINE__; - static_cast<void>(x); - ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -} -} // extern "C" - -struct Foo { - static void func(int x); -}; - -// A C++ method that should have a mangled name. -ABSL_SYMBOLIZE_TEST_NOINLINE void Foo::func(int) { - // The next line makes this a unique function to prevent the compiler from - // folding identical functions together. - volatile int x = __LINE__; - static_cast<void>(x); - ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); -} - -// Create functions that will remain in different text sections in the -// final binary when linker option "-z,keep-text-section-prefix" is used. -int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.unlikely) unlikely_func() { - return 0; -} - -int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.hot) hot_func() { - return 0; -} - -int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.startup) startup_func() { - return 0; -} - -int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.exit) exit_func() { - return 0; -} - -int /*ABSL_ATTRIBUTE_SECTION_VARIABLE(.text)*/ regular_func() { - return 0; -} - -// Thread-local data may confuse the symbolizer, ensure that it does not. -// Variable sizes and order are important. -#if ABSL_PER_THREAD_TLS -static ABSL_PER_THREAD_TLS_KEYWORD char symbolize_test_thread_small[1]; -static ABSL_PER_THREAD_TLS_KEYWORD char - symbolize_test_thread_big[2 * 1024 * 1024]; -#endif - -#if !defined(__EMSCRIPTEN__) -// Used below to hopefully inhibit some compiler/linker optimizations -// that may remove kHpageTextPadding, kPadding0, and kPadding1 from -// the binary. -static volatile bool volatile_bool = false; - -// Force the binary to be large enough that a THP .text remap will succeed. -static constexpr size_t kHpageSize = 1 << 21; -const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE( - .text) = ""; -#endif // !defined(__EMSCRIPTEN__) - -static char try_symbolize_buffer[4096]; - -// A wrapper function for absl::Symbolize() to make the unit test simple. The -// limit must be < sizeof(try_symbolize_buffer). Returns null if -// absl::Symbolize() returns false, otherwise returns try_symbolize_buffer with -// the result of absl::Symbolize(). -static const char *TrySymbolizeWithLimit(void *pc, int limit) { - ABSL_RAW_CHECK(limit <= sizeof(try_symbolize_buffer), - "try_symbolize_buffer is too small"); - - // Use the heap to facilitate heap and buffer sanitizer tools. - auto heap_buffer = absl::make_unique<char[]>(sizeof(try_symbolize_buffer)); - bool found = absl::Symbolize(pc, heap_buffer.get(), limit); - if (found) { - ABSL_RAW_CHECK(strnlen(heap_buffer.get(), limit) < limit, - "absl::Symbolize() did not properly terminate the string"); - strncpy(try_symbolize_buffer, heap_buffer.get(), - sizeof(try_symbolize_buffer) - 1); - try_symbolize_buffer[sizeof(try_symbolize_buffer) - 1] = '\0'; - } - - return found ? try_symbolize_buffer : nullptr; -} - -// A wrapper for TrySymbolizeWithLimit(), with a large limit. -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) - -TEST(Symbolize, Cached) { - // Compilers should give us pointers to them. - EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func))); - - // The name of an internal linkage symbol is not specified; allow either a - // mangled or an unmangled name here. - const char *static_func_symbol = TrySymbolize((void *)(&static_func)); - EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 || - strcmp("static_func()", static_func_symbol) == 0); - - EXPECT_TRUE(nullptr == TrySymbolize(nullptr)); -} - -TEST(Symbolize, Truncation) { - constexpr char kNonStaticFunc[] = "nonstatic_func"; - EXPECT_STREQ("nonstatic_func", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) + 1)); - EXPECT_STREQ("nonstatic_...", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) + 0)); - EXPECT_STREQ("nonstatic...", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) - 1)); - EXPECT_STREQ("n...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 5)); - EXPECT_STREQ("...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 4)); - EXPECT_STREQ("..", TrySymbolizeWithLimit((void *)(&nonstatic_func), 3)); - EXPECT_STREQ(".", TrySymbolizeWithLimit((void *)(&nonstatic_func), 2)); - EXPECT_STREQ("", TrySymbolizeWithLimit((void *)(&nonstatic_func), 1)); - EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void *)(&nonstatic_func), 0)); -} - -TEST(Symbolize, SymbolizeWithDemangling) { - Foo::func(100); - EXPECT_STREQ("Foo::func()", TrySymbolize((void *)(&Foo::func))); -} - -TEST(Symbolize, SymbolizeSplitTextSections) { - EXPECT_STREQ("unlikely_func()", TrySymbolize((void *)(&unlikely_func))); - EXPECT_STREQ("hot_func()", TrySymbolize((void *)(&hot_func))); - EXPECT_STREQ("startup_func()", TrySymbolize((void *)(&startup_func))); - EXPECT_STREQ("exit_func()", TrySymbolize((void *)(&exit_func))); - EXPECT_STREQ("regular_func()", TrySymbolize((void *)(®ular_func))); -} - -// Tests that verify that Symbolize stack footprint is within some limit. -#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION - -static void *g_pc_to_symbolize; -static char g_symbolize_buffer[4096]; -static char *g_symbolize_result; - -static void SymbolizeSignalHandler(int signo) { - if (absl::Symbolize(g_pc_to_symbolize, g_symbolize_buffer, - sizeof(g_symbolize_buffer))) { - g_symbolize_result = g_symbolize_buffer; - } else { - g_symbolize_result = nullptr; - } -} - -// Call Symbolize and figure out the stack footprint of this call. -static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) { - g_pc_to_symbolize = pc; - *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption( - SymbolizeSignalHandler); - return g_symbolize_result; -} - -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) - // Account for sanitizer instrumentation requiring additional stack space. - stack_consumption_upper_limit *= 5; -#endif - return stack_consumption_upper_limit; -} - -TEST(Symbolize, SymbolizeStackConsumption) { - int stack_consumed = 0; - - const char *symbol = - SymbolizeStackConsumption((void *)(&nonstatic_func), &stack_consumed); - EXPECT_STREQ("nonstatic_func", symbol); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit()); - - // The name of an internal linkage symbol is not specified; allow either a - // mangled or an unmangled name here. - symbol = SymbolizeStackConsumption((void *)(&static_func), &stack_consumed); - EXPECT_TRUE(strcmp("static_func", symbol) == 0 || - strcmp("static_func()", symbol) == 0); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit()); -} - -TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) { - Foo::func(100); - int stack_consumed = 0; - - const char *symbol = - SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed); - - EXPECT_STREQ("Foo::func()", symbol); - EXPECT_GT(stack_consumed, 0); - EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit()); -} - -#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 -// symbolize them and other symbols after remapping them. -const char kPadding0[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = - ""; -const char kPadding1[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = - ""; - -static int FilterElfHeader(struct dl_phdr_info *info, size_t size, void *data) { - for (int i = 0; i < info->dlpi_phnum; i++) { - if (info->dlpi_phdr[i].p_type == PT_LOAD && - info->dlpi_phdr[i].p_flags == (PF_R | PF_X)) { - const void *const vaddr = - absl::bit_cast<void *>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr); - const auto segsize = info->dlpi_phdr[i].p_memsz; - - const char *self_exe; - if (info->dlpi_name != nullptr && info->dlpi_name[0] != '\0') { - self_exe = info->dlpi_name; - } else { - self_exe = "/proc/self/exe"; - } - - absl::debugging_internal::RegisterFileMappingHint( - vaddr, reinterpret_cast<const char *>(vaddr) + segsize, - info->dlpi_phdr[i].p_offset, self_exe); - - return 1; - } - } - - return 1; -} - -TEST(Symbolize, SymbolizeWithMultipleMaps) { - // Force kPadding0 and kPadding1 to be linked in. - if (volatile_bool) { - ABSL_RAW_LOG(INFO, "%s", kPadding0); - ABSL_RAW_LOG(INFO, "%s", kPadding1); - } - - // Verify we can symbolize everything. - char buf[512]; - memset(buf, 0, sizeof(buf)); - absl::Symbolize(kPadding0, buf, sizeof(buf)); - EXPECT_STREQ("kPadding0", buf); - - memset(buf, 0, sizeof(buf)); - absl::Symbolize(kPadding1, buf, sizeof(buf)); - EXPECT_STREQ("kPadding1", buf); - - // Specify a hint for the executable segment. - dl_iterate_phdr(FilterElfHeader, nullptr); - - // Reload at least one page out of kPadding0, kPadding1 - const char *ptrs[] = {kPadding0, kPadding1}; - - for (const char *ptr : ptrs) { - const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE; - void *addr = mmap(nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0); - ASSERT_NE(addr, MAP_FAILED); - - // kPadding[0-1] is full of zeroes, so we can remap anywhere within it, but - // we ensure there is at least a full page of padding. - void *remapped = reinterpret_cast<void *>( - reinterpret_cast<uintptr_t>(ptr + kPageSize) & ~(kPageSize - 1ULL)); - - const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED); - void *ret = mremap(addr, kPageSize, kPageSize, kMremapFlags, remapped); - ASSERT_NE(ret, MAP_FAILED); - } - - // Invalidate the symbolization cache so we are forced to rely on the hint. - absl::Symbolize(nullptr, buf, sizeof(buf)); - - // Verify we can still symbolize. - const char *expected[] = {"kPadding0", "kPadding1"}; - const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize}; - - for (int i = 0; i < 2; i++) { - for (size_t offset : offsets) { - memset(buf, 0, sizeof(buf)); - absl::Symbolize(ptrs[i] + offset, buf, sizeof(buf)); - EXPECT_STREQ(expected[i], buf); - } - } -} - -// Appends string(*args->arg) to args->symbol_buf. -static void DummySymbolDecorator( - const absl::debugging_internal::SymbolDecoratorArgs *args) { - std::string *message = static_cast<std::string *>(args->arg); - strncat(args->symbol_buf, message->c_str(), - args->symbol_buf_size - strlen(args->symbol_buf) - 1); -} - -TEST(Symbolize, InstallAndRemoveSymbolDecorators) { - int ticket_a; - std::string a_message("a"); - EXPECT_GE(ticket_a = absl::debugging_internal::InstallSymbolDecorator( - DummySymbolDecorator, &a_message), - 0); - - int ticket_b; - std::string b_message("b"); - EXPECT_GE(ticket_b = absl::debugging_internal::InstallSymbolDecorator( - DummySymbolDecorator, &b_message), - 0); - - int ticket_c; - std::string c_message("c"); - EXPECT_GE(ticket_c = absl::debugging_internal::InstallSymbolDecorator( - DummySymbolDecorator, &c_message), - 0); - - char *address = reinterpret_cast<char *>(1); - EXPECT_STREQ("abc", TrySymbolize(address++)); - - EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_b)); - - EXPECT_STREQ("ac", TrySymbolize(address++)); - - // Cleanup: remove all remaining decorators so other stack traces don't - // get mystery "ac" decoration. - EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_a)); - EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c)); -} - -// Some versions of Clang with optimizations enabled seem to be able -// to optimize away the .data section if no variables live in the -// section. This variable should get placed in the .data section, and -// the test below checks for the existence of a .data section. -static int in_data_section = 1; - -TEST(Symbolize, ForEachSection) { - int fd = TEMP_FAILURE_RETRY(open("/proc/self/exe", O_RDONLY)); - ASSERT_NE(fd, -1); - - std::vector<std::string> sections; - ASSERT_TRUE(absl::debugging_internal::ForEachSection( - fd, [§ions](const absl::string_view name, const ElfW(Shdr) &) { - sections.emplace_back(name); - return true; - })); - - // Check for the presence of common section names. - EXPECT_THAT(sections, Contains(".text")); - EXPECT_THAT(sections, Contains(".rodata")); - EXPECT_THAT(sections, Contains(".bss")); - ++in_data_section; - EXPECT_THAT(sections, Contains(".data")); - - close(fd); -} -#endif // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE - -// x86 specific tests. Uses some inline assembler. -extern "C" { -inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() { - void *pc = nullptr; -#if defined(__i386__) - __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc)); -#elif defined(__x86_64__) - __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc)); -#endif - return pc; -} - -void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() { - void *pc = nullptr; -#if defined(__i386__) - __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc)); -#elif defined(__x86_64__) - __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc)); -#endif - return pc; -} - -void ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() { -#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \ - (defined(__i386__) || defined(__x86_64__)) - void *pc = non_inline_func(); - const char *symbol = TrySymbolize(pc); - ABSL_RAW_CHECK(symbol != nullptr, "TestWithPCInsideNonInlineFunction failed"); - ABSL_RAW_CHECK(strcmp(symbol, "non_inline_func") == 0, - "TestWithPCInsideNonInlineFunction failed"); - std::cout << "TestWithPCInsideNonInlineFunction passed" << std::endl; -#endif -} - -void ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() { -#if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \ - (defined(__i386__) || defined(__x86_64__)) - void *pc = inline_func(); // Must be inlined. - const char *symbol = TrySymbolize(pc); - ABSL_RAW_CHECK(symbol != nullptr, "TestWithPCInsideInlineFunction failed"); - ABSL_RAW_CHECK(strcmp(symbol, __FUNCTION__) == 0, - "TestWithPCInsideInlineFunction failed"); - std::cout << "TestWithPCInsideInlineFunction passed" << std::endl; -#endif -} -} - -// 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 -} - -#elif defined(_WIN32) -#if !defined(ABSL_CONSUME_DLL) - -TEST(Symbolize, Basics) { - EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func))); - - // The name of an internal linkage symbol is not specified; allow either a - // mangled or an unmangled name here. - const char *static_func_symbol = TrySymbolize((void *)(&static_func)); - ASSERT_TRUE(static_func_symbol != nullptr); - EXPECT_TRUE(strstr(static_func_symbol, "static_func") != nullptr); - - EXPECT_TRUE(nullptr == TrySymbolize(nullptr)); -} - -TEST(Symbolize, Truncation) { - constexpr char kNonStaticFunc[] = "nonstatic_func"; - EXPECT_STREQ("nonstatic_func", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) + 1)); - EXPECT_STREQ("nonstatic_...", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) + 0)); - EXPECT_STREQ("nonstatic...", - TrySymbolizeWithLimit((void *)(&nonstatic_func), - strlen(kNonStaticFunc) - 1)); - EXPECT_STREQ("n...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 5)); - EXPECT_STREQ("...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 4)); - EXPECT_STREQ("..", TrySymbolizeWithLimit((void *)(&nonstatic_func), 3)); - EXPECT_STREQ(".", TrySymbolizeWithLimit((void *)(&nonstatic_func), 2)); - EXPECT_STREQ("", TrySymbolizeWithLimit((void *)(&nonstatic_func), 1)); - EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void *)(&nonstatic_func), 0)); -} - -TEST(Symbolize, SymbolizeWithDemangling) { - const char *result = TrySymbolize((void *)(&Foo::func)); - ASSERT_TRUE(result != nullptr); - EXPECT_TRUE(strstr(result, "Foo::func") != nullptr) << result; -} - -#endif // !defined(ABSL_CONSUME_DLL) -#else // Symbolizer unimplemented - -TEST(Symbolize, Unimplemented) { - char buf[64]; - EXPECT_FALSE(absl::Symbolize((void *)(&nonstatic_func), buf, sizeof(buf))); - EXPECT_FALSE(absl::Symbolize((void *)(&static_func), buf, sizeof(buf))); - EXPECT_FALSE(absl::Symbolize((void *)(&Foo::func), buf, sizeof(buf))); -} - -#endif - -int main(int argc, char **argv) { -#if !defined(__EMSCRIPTEN__) - // Make sure kHpageTextPadding is linked into the binary. - if (volatile_bool) { - ABSL_RAW_LOG(INFO, "%s", kHpageTextPadding); - } -#endif // !defined(__EMSCRIPTEN__) - -#if ABSL_PER_THREAD_TLS - // Touch the per-thread variables. - symbolize_test_thread_small[0] = 0; - symbolize_test_thread_big[0] = 0; -#endif - - absl::InitializeSymbolizer(argv[0]); - testing::InitGoogleTest(&argc, argv); - -#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \ - defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) - TestWithPCInsideInlineFunction(); - TestWithPCInsideNonInlineFunction(); - TestWithReturnAddress(); -#endif - - return RUN_ALL_TESTS(); -} diff --git a/third_party/abseil_cpp/absl/debugging/symbolize_unimplemented.inc b/third_party/abseil_cpp/absl/debugging/symbolize_unimplemented.inc deleted file mode 100644 index db24456b0afa..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize_unimplemented.inc +++ /dev/null @@ -1,40 +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 <cstdint> - -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace debugging_internal { - -int InstallSymbolDecorator(SymbolDecorator, void*) { return -1; } -bool RemoveSymbolDecorator(int) { return false; } -bool RemoveAllSymbolDecorators(void) { return false; } -bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) { - return false; -} -bool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) { - return false; -} - -} // namespace debugging_internal - -void InitializeSymbolizer(const char*) {} -bool Symbolize(const void *, char *, int) { return false; } - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/debugging/symbolize_win32.inc b/third_party/abseil_cpp/absl/debugging/symbolize_win32.inc deleted file mode 100644 index c3df46f606c2..000000000000 --- a/third_party/abseil_cpp/absl/debugging/symbolize_win32.inc +++ /dev/null @@ -1,81 +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. - -// See "Retrieving Symbol Information by Address": -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx - -#include <windows.h> - -// MSVC header dbghelp.h has a warning for an ignored typedef. -#pragma warning(push) -#pragma warning(disable:4091) -#include <dbghelp.h> -#pragma warning(pop) - -#pragma comment(lib, "dbghelp.lib") - -#include <algorithm> -#include <cstring> - -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -static HANDLE process = NULL; - -void InitializeSymbolizer(const char*) { - if (process != nullptr) { - return; - } - process = GetCurrentProcess(); - - // Symbols are not loaded until a reference is made requiring the - // symbols be loaded. This is the fastest, most efficient way to use - // the symbol handler. - SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME); - if (!SymInitialize(process, nullptr, true)) { - // GetLastError() returns a Win32 DWORD, but we assign to - // unsigned long long to simplify the ABSL_RAW_LOG case below. The uniform - // initialization guarantees this is not a narrowing conversion. - const unsigned long long error{GetLastError()}; // NOLINT(runtime/int) - ABSL_RAW_LOG(FATAL, "SymInitialize() failed: %llu", error); - } -} - -bool Symbolize(const void* pc, char* out, int out_size) { - if (out_size <= 0) { - return false; - } - alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; - SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf); - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) { - return false; - } - strncpy(out, symbol->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/flags/BUILD.bazel b/third_party/abseil_cpp/absl/flags/BUILD.bazel deleted file mode 100644 index 78d6da74d819..000000000000 --- a/third_party/abseil_cpp/absl/flags/BUILD.bazel +++ /dev/null @@ -1,514 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "path_util", - hdrs = [ - "internal/path_util.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/flags:__pkg__", - ], - deps = [ - "//absl/base:config", - "//absl/strings", - ], -) - -cc_library( - name = "program_name", - srcs = [ - "internal/program_name.cc", - ], - hdrs = [ - "internal/program_name.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/flags:__pkg__", - ], - deps = [ - ":path_util", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - "//absl/synchronization", - ], -) - -cc_library( - name = "config", - srcs = [ - "usage_config.cc", - ], - hdrs = [ - "config.h", - "usage_config.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":path_util", - ":program_name", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - "//absl/synchronization", - ], -) - -cc_library( - name = "marshalling", - srcs = [ - "marshalling.cc", - ], - hdrs = [ - "marshalling.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:log_severity", - "//absl/strings", - "//absl/strings:str_format", - ], -) - -cc_library( - name = "commandlineflag_internal", - srcs = [ - "internal/commandlineflag.cc", - ], - hdrs = [ - "internal/commandlineflag.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:fast_type_id", - ], -) - -cc_library( - name = "commandlineflag", - srcs = [ - "commandlineflag.cc", - ], - hdrs = [ - "commandlineflag.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":commandlineflag_internal", - "//absl/base:config", - "//absl/base:fast_type_id", - "//absl/strings", - "//absl/types:optional", - ], -) - -cc_library( - name = "private_handle_accessor", - srcs = [ - "internal/private_handle_accessor.cc", - ], - hdrs = [ - "internal/private_handle_accessor.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/flags:__pkg__", - ], - deps = [ - ":commandlineflag", - ":commandlineflag_internal", - "//absl/base:config", - "//absl/strings", - ], -) - -cc_library( - name = "reflection", - srcs = [ - "reflection.cc", - ], - hdrs = [ - "internal/registry.h", - "reflection.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":commandlineflag", - ":commandlineflag_internal", - ":config", - ":private_handle_accessor", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/container:flat_hash_map", - "//absl/strings", - "//absl/synchronization", - ], -) - -cc_library( - name = "flag_internal", - srcs = [ - "internal/flag.cc", - ], - hdrs = [ - "internal/flag.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//absl/base:__subpackages__"], - deps = [ - ":commandlineflag", - ":commandlineflag_internal", - ":config", - ":marshalling", - ":reflection", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/synchronization", - "//absl/utility", - ], -) - -cc_library( - name = "flag", - srcs = [ - "flag.cc", - ], - hdrs = [ - "declare.h", - "flag.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":flag_internal", - ":reflection", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - ], -) - -cc_library( - name = "usage_internal", - srcs = [ - "internal/usage.cc", - ], - hdrs = [ - "internal/usage.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/flags:__pkg__", - ], - deps = [ - ":commandlineflag", - ":config", - ":flag", - ":flag_internal", - ":path_util", - ":private_handle_accessor", - ":program_name", - ":reflection", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - ], -) - -cc_library( - name = "usage", - srcs = [ - "usage.cc", - ], - hdrs = [ - "usage.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":usage_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - "//absl/synchronization", - ], -) - -cc_library( - name = "parse", - srcs = ["parse.cc"], - hdrs = [ - "internal/parse.h", - "parse.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":commandlineflag", - ":commandlineflag_internal", - ":config", - ":flag", - ":flag_internal", - ":private_handle_accessor", - ":program_name", - ":reflection", - ":usage", - ":usage_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/strings", - "//absl/synchronization", - ], -) - -############################################################################ -# Unit tests in alphabetical order. - -cc_test( - name = "commandlineflag_test", - size = "small", - srcs = [ - "commandlineflag_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":commandlineflag", - ":commandlineflag_internal", - ":config", - ":flag", - ":private_handle_accessor", - ":reflection", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "config_test", - size = "small", - srcs = [ - "config_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "flag_test", - size = "small", - srcs = [ - "flag_test.cc", - "flag_test_defs.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":flag", - ":flag_internal", - ":marshalling", - ":reflection", - "//absl/base:core_headers", - "//absl/base:malloc_internal", - "//absl/strings", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_binary( - name = "flag_benchmark", - testonly = 1, - srcs = [ - "flag_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":flag", - ":marshalling", - ":parse", - ":reflection", - "//absl/strings", - "//absl/time", - "//absl/types:optional", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "marshalling_test", - size = "small", - srcs = [ - "marshalling_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":marshalling", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "parse_test", - size = "small", - srcs = [ - "parse_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":flag", - ":parse", - ":reflection", - ":usage_internal", - "//absl/base:raw_logging_internal", - "//absl/base:scoped_set_env", - "//absl/strings", - "//absl/types:span", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "path_util_test", - size = "small", - srcs = [ - "internal/path_util_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":path_util", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "program_name_test", - size = "small", - srcs = [ - "internal/program_name_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":program_name", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "reflection_test", - size = "small", - srcs = [ - "reflection_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":commandlineflag_internal", - ":flag", - ":marshalling", - ":reflection", - ":usage_internal", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "usage_config_test", - size = "small", - srcs = [ - "usage_config_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":path_util", - ":program_name", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "usage_test", - size = "small", - srcs = [ - "internal/usage_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":config", - ":flag", - ":parse", - ":path_util", - ":program_name", - ":reflection", - ":usage", - ":usage_internal", - "//absl/strings", - "@com_google_googletest//:gtest", - ], -) diff --git a/third_party/abseil_cpp/absl/flags/CMakeLists.txt b/third_party/abseil_cpp/absl/flags/CMakeLists.txt deleted file mode 100644 index e5083d7b9a87..000000000000 --- a/third_party/abseil_cpp/absl/flags/CMakeLists.txt +++ /dev/null @@ -1,451 +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. -# - -# 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 -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - flags_program_name - SRCS - "internal/program_name.cc" - HDRS - "internal/program_name.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::flags_path_util - absl::strings - absl::synchronization - PUBLIC -) - -absl_cc_library( - NAME - flags_config - SRCS - "usage_config.cc" - HDRS - "config.h" - "usage_config.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::flags_path_util - absl::flags_program_name - absl::core_headers - absl::strings - absl::synchronization -) - -absl_cc_library( - NAME - flags_marshalling - SRCS - "marshalling.cc" - HDRS - "marshalling.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::log_severity - absl::strings - absl::str_format -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - flags_commandlineflag_internal - SRCS - "internal/commandlineflag.cc" - HDRS - "internal/commandlineflag.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${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::optional - absl::strings -) - -# 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 - SRCS - "reflection.cc" - HDRS - "reflection.h" - "internal/registry.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::flags_commandlineflag - absl::flags_private_handle_accessor - absl::flags_config - 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" - 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( - NAME - flags - SRCS - "flag.cc" - HDRS - "declare.h" - "flag.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::flags_commandlineflag - absl::flags_config - absl::flags_internal - absl::flags_reflection - absl::base - absl::core_headers - absl::strings -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - flags_usage_internal - SRCS - "internal/usage.cc" - HDRS - "internal/usage.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::flags_config - absl::flags - absl::flags_commandlineflag - absl::flags_internal - absl::flags_path_util - absl::flags_private_handle_accessor - absl::flags_program_name - absl::flags_reflection - absl::strings - absl::synchronization -) - -absl_cc_library( - NAME - flags_usage - SRCS - "usage.cc" - HDRS - "usage.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::flags_usage_internal - absl::strings - absl::synchronization -) - -absl_cc_library( - NAME - flags_parse - SRCS - "parse.cc" - HDRS - "internal/parse.h" - "parse.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::flags_config - absl::flags - absl::flags_commandlineflag - absl::flags_commandlineflag_internal - absl::flags_internal - absl::flags_private_handle_accessor - absl::flags_program_name - absl::flags_reflection - absl::flags_usage - absl::strings - absl::synchronization -) - -############################################################################ -# Unit tests in alpahabetical order. - -absl_cc_test( - NAME - flags_commandlineflag_test - SRCS - "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::memory - absl::strings - gtest_main -) - -absl_cc_test( - NAME - flags_config_test - SRCS - "config_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_config - gtest_main -) - -absl_cc_test( - NAME - flags_flag_test - SRCS - "flag_test.cc" - "flag_test_defs.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::core_headers - absl::flags - absl::flags_config - absl::flags_internal - absl::flags_marshalling - absl::flags_reflection - absl::strings - absl::time - gtest_main -) - -absl_cc_test( - NAME - flags_marshalling_test - SRCS - "marshalling_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_marshalling - gtest_main -) - -absl_cc_test( - NAME - flags_parse_test - SRCS - "parse_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags - absl::flags_parse - absl::flags_reflection - absl::flags_usage_internal - absl::raw_logging_internal - absl::scoped_set_env - absl::span - absl::strings - gmock_main -) - -absl_cc_test( - NAME - flags_path_util_test - SRCS - "internal/path_util_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_path_util - gtest_main -) - -absl_cc_test( - NAME - flags_program_name_test - SRCS - "internal/program_name_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_program_name - absl::strings - gtest_main -) - -absl_cc_test( - NAME - flags_reflection_test - SRCS - "reflection_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_commandlineflag_internal - absl::flags - absl::flags_reflection - absl::flags_usage - absl::memory - absl::strings - gmock_main -) - -absl_cc_test( - NAME - flags_usage_config_test - SRCS - "usage_config_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_config - absl::flags_path_util - absl::flags_program_name - absl::strings - gtest_main -) - -absl_cc_test( - NAME - flags_usage_test - SRCS - "internal/usage_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::flags_config - absl::flags - absl::flags_path_util - absl::flags_program_name - absl::flags_parse - absl::flags_reflection - absl::flags_usage - absl::strings - 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 9f3b4a5a28ef..000000000000 --- 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 f2fa08977fd4..000000000000 --- 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 585db4ba78a0..000000000000 --- 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 deleted file mode 100644 index 813a9257000f..000000000000 --- a/third_party/abseil_cpp/absl/flags/config.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_FLAGS_CONFIG_H_ -#define ABSL_FLAGS_CONFIG_H_ - -// Determine if we should strip string literals from the Flag objects. -// By default we strip string literals on mobile platforms. -#if !defined(ABSL_FLAGS_STRIP_NAMES) - -#if defined(__ANDROID__) -#define ABSL_FLAGS_STRIP_NAMES 1 - -#elif defined(__APPLE__) -#include <TargetConditionals.h> -#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#define ABSL_FLAGS_STRIP_NAMES 1 -#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED -#define ABSL_FLAGS_STRIP_NAMES 1 -#endif // TARGET_OS_* -#endif - -#endif // !defined(ABSL_FLAGS_STRIP_NAMES) - -#if !defined(ABSL_FLAGS_STRIP_NAMES) -// If ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above, -// the default is not to strip. -#define ABSL_FLAGS_STRIP_NAMES 0 -#endif - -#if !defined(ABSL_FLAGS_STRIP_HELP) -// By default, if we strip names, we also strip help. -#define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES -#endif - -// ABSL_FLAGS_INTERNAL_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 -#error ABSL_FLAGS_INTERNAL_HAS_RTTI cannot be directly set -#elif !defined(__GNUC__) || defined(__GXX_RTTI) -#define ABSL_FLAGS_INTERNAL_HAS_RTTI 1 -#endif // !defined(__GNUC__) || defined(__GXX_RTTI) - -// These macros represent the "source of truth" for the list of supported -// built-in types. -#define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \ - A(bool, bool) \ - A(short, short) \ - A(unsigned short, unsigned_short) \ - A(int, int) \ - A(unsigned int, unsigned_int) \ - A(long, long) \ - A(unsigned long, unsigned_long) \ - A(long long, long_long) \ - A(unsigned long long, unsigned_long_long) \ - A(double, double) \ - A(float, float) - -#define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \ - ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \ - A(std::string, std_string) \ - A(std::vector<std::string>, std_vector_of_string) - -#endif // ABSL_FLAGS_CONFIG_H_ diff --git a/third_party/abseil_cpp/absl/flags/config_test.cc b/third_party/abseil_cpp/absl/flags/config_test.cc deleted file mode 100644 index 638998667e70..000000000000 --- a/third_party/abseil_cpp/absl/flags/config_test.cc +++ /dev/null @@ -1,61 +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/config.h" - -#ifdef __APPLE__ -#include <TargetConditionals.h> -#endif - -#include "gtest/gtest.h" - -#ifndef ABSL_FLAGS_STRIP_NAMES -#error ABSL_FLAGS_STRIP_NAMES is not defined -#endif - -#ifndef ABSL_FLAGS_STRIP_HELP -#error ABSL_FLAGS_STRIP_HELP is not defined -#endif - -namespace { - -// Test that ABSL_FLAGS_STRIP_NAMES and ABSL_FLAGS_STRIP_HELP are configured how -// we expect them to be configured by default. If you override this -// configuration, this test will fail, but the code should still be safe to use. -TEST(FlagsConfigTest, Test) { -#if defined(__ANDROID__) - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); -#elif defined(__myriad2__) - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); -#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); -#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1); -#elif defined(__APPLE__) - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); -#elif defined(_WIN32) - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); -#elif defined(__linux__) - EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0); - EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0); -#endif -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/flags/declare.h b/third_party/abseil_cpp/absl/flags/declare.h deleted file mode 100644 index b9794d8b85ac..000000000000 --- a/third_party/abseil_cpp/absl/flags/declare.h +++ /dev/null @@ -1,65 +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. -// -// ----------------------------------------------------------------------------- -// File: declare.h -// ----------------------------------------------------------------------------- -// -// This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an -// `absl::Flag` for use within a translation unit. You should place this -// declaration within the header file associated with the .cc file that defines -// and owns the `Flag`. - -#ifndef ABSL_FLAGS_DECLARE_H_ -#define ABSL_FLAGS_DECLARE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG. -template <typename T> -class Flag; - -} // namespace flags_internal - -// Flag -// -// Forward declaration of the `absl::Flag` type for use in defining the macro. -#if defined(_MSC_VER) && !defined(__clang__) -template <typename T> -class Flag; -#else -template <typename T> -using Flag = flags_internal::Flag<T>; -#endif - -ABSL_NAMESPACE_END -} // namespace absl - -// ABSL_DECLARE_FLAG() -// -// This macro is a convenience for declaring use of an `absl::Flag` within a -// translation unit. This macro should be used within a header file to -// declare usage of the flag within any .cc file including that header file. -// -// The ABSL_DECLARE_FLAG(type, name) macro expands to: -// -// extern absl::Flag<type> FLAGS_name; -#define ABSL_DECLARE_FLAG(type, name) extern ::absl::Flag<type> FLAGS_##name - -#endif // ABSL_FLAGS_DECLARE_H_ diff --git a/third_party/abseil_cpp/absl/flags/flag.cc b/third_party/abseil_cpp/absl/flags/flag.cc deleted file mode 100644 index 531df1287a17..000000000000 --- a/third_party/abseil_cpp/absl/flags/flag.cc +++ /dev/null @@ -1,38 +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/flag.h" - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// This global mutex protects on-demand construction of flag objects in MSVC -// builds. -#if defined(_MSC_VER) && !defined(__clang__) - -namespace flags_internal { - -ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit); - -absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; } - -} // namespace flags_internal - -#endif - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/flag.h b/third_party/abseil_cpp/absl/flags/flag.h deleted file mode 100644 index a9cb2b7994d1..000000000000 --- a/third_party/abseil_cpp/absl/flags/flag.h +++ /dev/null @@ -1,396 +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. -// -// ----------------------------------------------------------------------------- -// File: flag.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::Flag<T>` type for holding command-line -// flag data, and abstractions to create, get and set such flag data. -// -// It is important to note that this type is **unspecified** (an implementation -// detail) and you do not construct or manipulate actual `absl::Flag<T>` -// instances. Instead, you define and declare flags using the -// `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values -// using the `absl::GetFlag()` and `absl::SetFlag()` functions. - -#ifndef ABSL_FLAGS_FLAG_H_ -#define ABSL_FLAGS_FLAG_H_ - -#include <string> -#include <type_traits> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/optimization.h" -#include "absl/flags/config.h" -#include "absl/flags/internal/flag.h" -#include "absl/flags/internal/registry.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Flag -// -// An `absl::Flag` holds a command-line flag value, providing a runtime -// parameter to a binary. Such flags should be defined in the global namespace -// and (preferably) in the module containing the binary's `main()` function. -// -// You should not construct and cannot use the `absl::Flag` type directly; -// instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro -// within a header file, and define your flag using `ABSL_FLAG()` within your -// header's associated `.cc` file. Such flags will be named `FLAGS_name`. -// -// Example: -// -// .h file -// -// // Declares usage of a flag named "FLAGS_count" -// ABSL_DECLARE_FLAG(int, count); -// -// .cc file -// -// // Defines a flag named "FLAGS_count" with a default `int` value of 0. -// ABSL_FLAG(int, count, 0, "Count of items to process"); -// -// No public methods of `absl::Flag<T>` are part of the Abseil Flags API. -#if !defined(_MSC_VER) || defined(__clang__) -template <typename T> -using Flag = flags_internal::Flag<T>; -#else -// MSVC debug builds do not implement initialization with constexpr constructors -// correctly. To work around this we add a level of indirection, so that the -// class `absl::Flag` contains an `internal::Flag*` (instead of being an alias -// to that class) and dynamically allocates an instance when necessary. We also -// forward all calls to internal::Flag methods via trampoline methods. In this -// setup the `absl::Flag` class does not have constructor and virtual methods, -// all the data members are public and thus MSVC is able to initialize it at -// link time. To deal with multiple threads accessing the flag for the first -// time concurrently we use an atomic boolean indicating if flag object is -// initialized. We also employ the double-checked locking pattern where the -// second level of protection is a global Mutex, so if two threads attempt to -// construct the flag concurrently only one wins. -// This solution is based on a recomendation here: -// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454 - -namespace flags_internal { -absl::Mutex* GetGlobalConstructionGuard(); -} // namespace flags_internal - -template <typename T> -class Flag { - public: - // No constructor and destructor to ensure this is an aggregate type. - // Visual Studio 2015 still requires the constructor for class to be - // constexpr initializable. -#if _MSC_VER <= 1900 - constexpr Flag(const char* name, const char* filename, - const flags_internal::HelpGenFunc help_gen, - const flags_internal::FlagDfltGenFunc default_value_gen) - : name_(name), - filename_(filename), - help_gen_(help_gen), - default_value_gen_(default_value_gen), - inited_(false), - impl_(nullptr) {} -#endif - - flags_internal::Flag<T>& GetImpl() const { - if (!inited_.load(std::memory_order_acquire)) { - absl::MutexLock l(flags_internal::GetGlobalConstructionGuard()); - - if (inited_.load(std::memory_order_acquire)) { - return *impl_; - } - - impl_ = new flags_internal::Flag<T>( - name_, filename_, - {flags_internal::FlagHelpMsg(help_gen_), - flags_internal::FlagHelpKind::kGenFunc}, - {flags_internal::FlagDefaultSrc(default_value_gen_), - flags_internal::FlagDefaultKind::kGenFunc}); - inited_.store(true, std::memory_order_release); - } - - return *impl_; - } - - // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API. - // See https://abseil.io/docs/cpp/guides/flags - bool IsRetired() const { return GetImpl().IsRetired(); } - absl::string_view Name() const { return GetImpl().Name(); } - std::string Help() const { return GetImpl().Help(); } - bool IsModified() const { return GetImpl().IsModified(); } - bool IsSpecifiedOnCommandLine() const { - return GetImpl().IsSpecifiedOnCommandLine(); - } - std::string Filename() const { return GetImpl().Filename(); } - std::string DefaultValue() const { return GetImpl().DefaultValue(); } - std::string CurrentValue() const { return GetImpl().CurrentValue(); } - template <typename U> - inline bool IsOfType() const { - return GetImpl().template IsOfType<U>(); - } - T Get() const { - return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl()); - } - void Set(const T& v) { - flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v); - } - void InvokeCallback() { GetImpl().InvokeCallback(); } - - const CommandLineFlag& Reflect() const { - return flags_internal::FlagImplPeer::InvokeReflect(GetImpl()); - } - - // The data members are logically private, but they need to be public for - // this to be an aggregate type. - const char* name_; - const char* filename_; - const flags_internal::HelpGenFunc help_gen_; - const flags_internal::FlagDfltGenFunc default_value_gen_; - - mutable std::atomic<bool> inited_; - mutable flags_internal::Flag<T>* impl_; -}; -#endif - -// GetFlag() -// -// Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do -// not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`; -// instead, refer to flag's constructed variable name (e.g. `FLAGS_name`). -// Because this function returns by value and not by reference, it is -// thread-safe, but note that the operation may be expensive; as a result, avoid -// `absl::GetFlag()` within any tight loops. -// -// Example: -// -// // FLAGS_count is a Flag of type `int` -// int my_count = absl::GetFlag(FLAGS_count); -// -// // FLAGS_firstname is a Flag of type `std::string` -// std::string first_name = absl::GetFlag(FLAGS_firstname); -template <typename T> -ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) { - return flags_internal::FlagImplPeer::InvokeGet<T>(flag); -} - -// SetFlag() -// -// Sets the value of an `absl::Flag` to the value `v`. Do not construct an -// `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the -// flag's variable name (e.g. `FLAGS_name`). This function is -// thread-safe, but is potentially expensive. Avoid setting flags in general, -// but especially within performance-critical code. -template <typename T> -void SetFlag(absl::Flag<T>* flag, const T& v) { - flags_internal::FlagImplPeer::InvokeSet(*flag, v); -} - -// Overload of `SetFlag()` to allow callers to pass in a value that is -// convertible to `T`. E.g., use this overload to pass a "const char*" when `T` -// is `std::string`. -template <typename T, typename V> -void SetFlag(absl::Flag<T>* flag, const V& v) { - T value(v); - flags_internal::FlagImplPeer::InvokeSet(*flag, value); -} - -// GetFlagReflectionHandle() -// -// Returns the reflection handle corresponding to specified Abseil Flag -// instance. Use this handle to access flag's reflection information, like name, -// location, default value etc. -// -// Example: -// -// std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue(); - -template <typename T> -const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) { - return flags_internal::FlagImplPeer::InvokeReflect(f); -} - -ABSL_NAMESPACE_END -} // namespace absl - - -// ABSL_FLAG() -// -// This macro defines an `absl::Flag<T>` instance of a specified type `T`: -// -// ABSL_FLAG(T, name, default_value, help); -// -// where: -// -// * `T` is a supported flag type (see the list of types in `marshalling.h`), -// * `name` designates the name of the flag (as a global variable -// `FLAGS_name`), -// * `default_value` is an expression holding the default value for this flag -// (which must be implicitly convertible to `T`), -// * `help` is the help text, which can also be an expression. -// -// This macro expands to a flag named 'FLAGS_name' of type 'T': -// -// absl::Flag<T> FLAGS_name = ...; -// -// Note that all such instances are created as global variables. -// -// For `ABSL_FLAG()` values that you wish to expose to other translation units, -// it is recommended to define those flags within the `.cc` file associated with -// the header where the flag is declared. -// -// Note: do not construct objects of type `absl::Flag<T>` directly. Only use the -// `ABSL_FLAG()` macro for such construction. -#define ABSL_FLAG(Type, name, default_value, help) \ - ABSL_FLAG_IMPL(Type, name, default_value, help) - -// ABSL_FLAG().OnUpdate() -// -// Defines a flag of type `T` with a callback attached: -// -// ABSL_FLAG(T, name, default_value, help).OnUpdate(callback); -// -// After any setting of the flag value, the callback will be called at least -// once. A rapid sequence of changes may be merged together into the same -// callback. No concurrent calls to the callback will be made for the same -// flag. Callbacks are allowed to read the current value of the flag but must -// not mutate that flag. -// -// The update mechanism guarantees "eventual consistency"; if the callback -// derives an auxiliary data structure from the flag value, it is guaranteed -// that eventually the flag value and the derived data structure will be -// consistent. -// -// Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this -// comment serves as its API documentation. - - -// ----------------------------------------------------------------------------- -// Implementation details below this section -// ----------------------------------------------------------------------------- - -// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES -#if !defined(_MSC_VER) || defined(__clang__) -#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag -#define ABSL_FLAG_IMPL_HELP_ARG(name) \ - absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \ - FLAGS_help_storage_##name) -#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \ - absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0) -#else -#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl() -#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst -#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen -#endif - -#if ABSL_FLAGS_STRIP_NAMES -#define ABSL_FLAG_IMPL_FLAGNAME(txt) "" -#define ABSL_FLAG_IMPL_FILENAME() "" -#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ - absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag)) -#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)) -#endif - -// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP - -#if ABSL_FLAGS_STRIP_HELP -#define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp -#else -#define ABSL_FLAG_IMPL_FLAGHELP(txt) txt -#endif - -// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const) -// and lazy (method NonConst) evaluation of help message expression. We choose -// between the two via the call to HelpArg in absl::Flag instantiation below. -// If help message expression is constexpr evaluable compiler will optimize -// away this whole struct. -// TODO(rogeeff): place these generated structs into local namespace and apply -// ABSL_INTERNAL_UNIQUE_SHORT_NAME. -// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name -#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \ - struct AbslFlagHelpGenFor##name { \ - /* The expression is run in the caller as part of the */ \ - /* default value argument. That keeps temporaries alive */ \ - /* long enough for NonConst to work correctly. */ \ - static constexpr absl::string_view Value( \ - absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \ - return v; \ - } \ - static std::string NonConst() { return std::string(Value()); } \ - }; \ - constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \ - ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \ - absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \ - 0); - -#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ - struct AbslFlagDefaultGenFor##name { \ - Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \ - static void Gen(void* p) { \ - new (p) Type(AbslFlagDefaultGenFor##name{}.value); \ - } \ - }; - -// ABSL_FLAG_IMPL -// -// Note: Name of registrar object is not arbitrary. It is used to "grab" -// global name for FLAGS_no<flag_name> symbol, thus preventing the possibility -// of defining two flags with names foo and nofoo. -#define ABSL_FLAG_IMPL(Type, name, default_value, help) \ - namespace absl /* block flags in namespaces */ {} \ - ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ - ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \ - ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \ - ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \ - extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \ - absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \ - ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) - -// ABSL_RETIRED_FLAG -// -// Designates the flag (which is usually pre-existing) as "retired." A retired -// flag is a flag that is now unused by the program, but may still be passed on -// the command line, usually by production scripts. A retired flag is ignored -// and code can't access it at runtime. -// -// This macro registers a retired flag with given name and type, with a name -// identical to the name of the original flag you are retiring. The retired -// flag's type can change over time, so that you can retire code to support a -// custom flag type. -// -// This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply -// replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the -// arguments unchanged (unless of course you actually want to retire the flag -// type at this time as well). -// -// `default_value` is only used as a double check on the type. `explanation` is -// unused. -// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of -// retired flags are cleaned up. -#define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \ - static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \ - ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \ - (RETIRED_FLAGS_##name.Retire(#name), \ - ::absl::flags_internal::FlagRegistrarEmpty{}) - -#endif // ABSL_FLAGS_FLAG_H_ diff --git a/third_party/abseil_cpp/absl/flags/flag_benchmark.cc b/third_party/abseil_cpp/absl/flags/flag_benchmark.cc deleted file mode 100644 index 9982b604b3b5..000000000000 --- a/third_party/abseil_cpp/absl/flags/flag_benchmark.cc +++ /dev/null @@ -1,159 +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 <stdint.h> - -#include <string> -#include <vector> - -#include "absl/flags/flag.h" -#include "absl/flags/marshalling.h" -#include "absl/flags/parse.h" -#include "absl/flags/reflection.h" -#include "absl/strings/string_view.h" -#include "absl/time/time.h" -#include "absl/types/optional.h" -#include "benchmark/benchmark.h" - -namespace { -using String = std::string; -using VectorOfStrings = std::vector<std::string>; -using AbslDuration = absl::Duration; - -// We do not want to take over marshalling for the types absl::optional<int>, -// absl::optional<std::string> which we do not own. Instead we introduce unique -// "aliases" to these types, which we do. -using AbslOptionalInt = absl::optional<int>; -struct OptionalInt : AbslOptionalInt { - using AbslOptionalInt::AbslOptionalInt; -}; -// Next two functions represent Abseil Flags marshalling for OptionalInt. -bool AbslParseFlag(absl::string_view src, OptionalInt* flag, - std::string* error) { - int val; - if (src.empty()) - flag->reset(); - else if (!absl::ParseFlag(src, &val, error)) - return false; - *flag = val; - return true; -} -std::string AbslUnparseFlag(const OptionalInt& flag) { - return !flag ? "" : absl::UnparseFlag(*flag); -} - -using AbslOptionalString = absl::optional<std::string>; -struct OptionalString : AbslOptionalString { - using AbslOptionalString::AbslOptionalString; -}; -// Next two functions represent Abseil Flags marshalling for OptionalString. -bool AbslParseFlag(absl::string_view src, OptionalString* flag, - std::string* error) { - std::string val; - if (src.empty()) - flag->reset(); - else if (!absl::ParseFlag(src, &val, error)) - return false; - *flag = val; - return true; -} -std::string AbslUnparseFlag(const OptionalString& flag) { - return !flag ? "" : absl::UnparseFlag(*flag); -} - -struct UDT { - UDT() = default; - UDT(const UDT&) {} - UDT& operator=(const UDT&) { return *this; } -}; -// Next two functions represent Abseil Flags marshalling for UDT. -bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } -std::string AbslUnparseFlag(const UDT&) { return ""; } - -} // namespace - -#define BENCHMARKED_TYPES(A) \ - A(bool) \ - A(int16_t) \ - A(uint16_t) \ - A(int32_t) \ - A(uint32_t) \ - A(int64_t) \ - A(uint64_t) \ - A(double) \ - A(float) \ - A(String) \ - A(VectorOfStrings) \ - A(OptionalInt) \ - A(OptionalString) \ - A(AbslDuration) \ - A(UDT) - -#define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, ""); - -BENCHMARKED_TYPES(FLAG_DEF) - -// Register thousands of flags to bloat up the size of the registry. -// This mimics real life production binaries. -#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, ""); -#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1) -#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1) -#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1) -#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1) -#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1) -#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1) -#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1) -#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1) -#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1) -#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1) -#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1) -#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1) -DEFINE_FLAG_12(bloat_flag_); - -namespace { - -#define BM_GetFlag(T) \ - void BM_GetFlag_##T(benchmark::State& state) { \ - for (auto _ : state) { \ - benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \ - } \ - } \ - BENCHMARK(BM_GetFlag_##T); - -BENCHMARKED_TYPES(BM_GetFlag) - -void BM_ThreadedFindCommandLineFlag(benchmark::State& state) { - char dummy[] = "dummy"; - char* argv[] = {dummy}; - // We need to ensure that flags have been parsed. That is where the registry - // is finalized. - absl::ParseCommandLine(1, argv); - - for (auto s : state) { - benchmark::DoNotOptimize( - absl::FindCommandLineFlag("bloat_flag_010101010101")); - } -} -BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16); - -} // namespace - -#define InvokeGetFlag(T) \ - T AbslInvokeGetFlag##T() { return absl::GetFlag(FLAGS_##T##_flag); } \ - int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1); - -BENCHMARKED_TYPES(InvokeGetFlag) - -// To veiw disassembly use: gdb ${BINARY} -batch -ex "disassemble /s $FUNC" diff --git a/third_party/abseil_cpp/absl/flags/flag_test.cc b/third_party/abseil_cpp/absl/flags/flag_test.cc deleted file mode 100644 index 654c8122215c..000000000000 --- a/third_party/abseil_cpp/absl/flags/flag_test.cc +++ /dev/null @@ -1,906 +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/flag.h" - -#include <stddef.h> -#include <stdint.h> - -#include <cmath> -#include <new> -#include <string> -#include <thread> // NOLINT -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/flags/config.h" -#include "absl/flags/declare.h" -#include "absl/flags/internal/flag.h" -#include "absl/flags/marshalling.h" -#include "absl/flags/reflection.h" -#include "absl/flags/usage_config.h" -#include "absl/strings/match.h" -#include "absl/strings/numbers.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" -#include "absl/time/time.h" - -ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag); -ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag); - -namespace { - -namespace flags = absl::flags_internal; - -std::string TestHelpMsg() { return "dynamic help"; } -#if defined(_MSC_VER) && !defined(__clang__) -std::string TestLiteralHelpMsg() { return "literal help"; } -#endif -template <typename T> -void TestMakeDflt(void* dst) { - new (dst) T{}; -} -void TestCallback() {} - -struct UDT { - UDT() = default; - UDT(const UDT&) = default; -}; -bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } -std::string AbslUnparseFlag(const UDT&) { return ""; } - -class FlagTest : public testing::Test { - protected: - static void SetUpTestSuite() { - // Install a function to normalize filenames before this test is run. - absl::FlagsUsageConfig default_config; - default_config.normalize_filename = &FlagTest::NormalizeFileName; - absl::SetFlagsUsageConfig(default_config); - } - - private: - static std::string NormalizeFileName(absl::string_view fname) { -#ifdef _WIN32 - std::string normalized(fname); - std::replace(normalized.begin(), normalized.end(), '\\', '/'); - fname = normalized; -#endif - return std::string(fname); - } - absl::FlagSaver flag_saver_; -}; - -struct S1 { - S1() = default; - S1(const S1&) = default; - int32_t f1; - int64_t f2; -}; - -struct S2 { - S2() = default; - S2(const S2&) = default; - int64_t f1; - double f2; -}; - -TEST_F(FlagTest, Traits) { - EXPECT_EQ(flags::StorageKind<int>(), - flags::FlagValueStorageKind::kOneWordAtomic); - EXPECT_EQ(flags::StorageKind<bool>(), - flags::FlagValueStorageKind::kOneWordAtomic); - EXPECT_EQ(flags::StorageKind<double>(), - flags::FlagValueStorageKind::kOneWordAtomic); - EXPECT_EQ(flags::StorageKind<int64_t>(), - flags::FlagValueStorageKind::kOneWordAtomic); - -#if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD) - EXPECT_EQ(flags::StorageKind<S1>(), - flags::FlagValueStorageKind::kTwoWordsAtomic); - EXPECT_EQ(flags::StorageKind<S2>(), - flags::FlagValueStorageKind::kTwoWordsAtomic); -#else - EXPECT_EQ(flags::StorageKind<S1>(), - flags::FlagValueStorageKind::kAlignedBuffer); - EXPECT_EQ(flags::StorageKind<S2>(), - flags::FlagValueStorageKind::kAlignedBuffer); -#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)) - .OnUpdate(TestCallback); - - EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2"); - EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help"); - EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file"); - - return true; -} - -#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T); - -TEST_F(FlagTest, TestConstruction) { - TEST_CONSTRUCTED_FLAG(bool); - TEST_CONSTRUCTED_FLAG(int16_t); - TEST_CONSTRUCTED_FLAG(uint16_t); - TEST_CONSTRUCTED_FLAG(int32_t); - TEST_CONSTRUCTED_FLAG(uint32_t); - TEST_CONSTRUCTED_FLAG(int64_t); - TEST_CONSTRUCTED_FLAG(uint64_t); - TEST_CONSTRUCTED_FLAG(float); - TEST_CONSTRUCTED_FLAG(double); - TEST_CONSTRUCTED_FLAG(String); - TEST_CONSTRUCTED_FLAG(UDT); -} - -// -------------------------------------------------------------------- - -} // namespace - -ABSL_DECLARE_FLAG(bool, test_flag_01); -ABSL_DECLARE_FLAG(int, test_flag_02); -ABSL_DECLARE_FLAG(int16_t, test_flag_03); -ABSL_DECLARE_FLAG(uint16_t, test_flag_04); -ABSL_DECLARE_FLAG(int32_t, test_flag_05); -ABSL_DECLARE_FLAG(uint32_t, test_flag_06); -ABSL_DECLARE_FLAG(int64_t, test_flag_07); -ABSL_DECLARE_FLAG(uint64_t, test_flag_08); -ABSL_DECLARE_FLAG(double, test_flag_09); -ABSL_DECLARE_FLAG(float, test_flag_10); -ABSL_DECLARE_FLAG(std::string, test_flag_11); -ABSL_DECLARE_FLAG(absl::Duration, test_flag_12); - -namespace { - -#if !ABSL_FLAGS_STRIP_NAMES - -TEST_F(FlagTest, TestFlagDeclaration) { - // test that we can access flag objects. - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(), - "test_flag_01"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(), - "test_flag_02"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(), - "test_flag_03"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(), - "test_flag_04"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(), - "test_flag_05"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(), - "test_flag_06"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(), - "test_flag_07"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(), - "test_flag_08"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(), - "test_flag_09"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(), - "test_flag_10"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(), - "test_flag_11"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(), - "test_flag_12"); -} -#endif // !ABSL_FLAGS_STRIP_NAMES - -// -------------------------------------------------------------------- - -} // namespace - -ABSL_FLAG(bool, test_flag_01, true, "test flag 01"); -ABSL_FLAG(int, test_flag_02, 1234, "test flag 02"); -ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03"); -ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04"); -ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05"); -ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06"); -ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07"); -ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08"); -ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09"); -ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10"); -ABSL_FLAG(std::string, test_flag_11, "", "test flag 11"); -ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12"); - -namespace { - -#if !ABSL_FLAGS_STRIP_NAMES -TEST_F(FlagTest, TestFlagDefinition) { - absl::string_view expected_file_name = "absl/flags/flag_test.cc"; - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(), - "test_flag_01"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(), - "test flag 01"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(), - "test_flag_02"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(), - "test flag 02"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(), - "test_flag_03"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(), - "test flag 03"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(), - "test_flag_04"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(), - "test flag 04"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(), - "test_flag_05"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(), - "test flag 05"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(), - "test_flag_06"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(), - "test flag 06"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(), - "test_flag_07"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(), - "test flag 07"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(), - "test_flag_08"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(), - "test flag 08"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(), - "test_flag_09"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(), - "test flag 09"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(), - "test_flag_10"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(), - "test flag 10"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(), - "test_flag_11"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(), - "test flag 11"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(), - "test_flag_12"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(), - "test flag 12"); - EXPECT_TRUE(absl::EndsWith( - absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(), - expected_file_name)) - << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(); -} -#endif // !ABSL_FLAGS_STRIP_NAMES - -// -------------------------------------------------------------------- - -TEST_F(FlagTest, TestDefault) { - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(), - "true"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(), - "1234"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(), - "-34"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(), - "189"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(), - "10765"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(), - "40000"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(), - "-1234567"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(), - "9876543"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(), - "-9.876e-50"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(), - "1.234e+12"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(), - ""); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(), - "10m"); - - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(), - "true"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(), - "1234"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(), - "-34"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(), - "189"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(), - "10765"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(), - "40000"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(), - "-1234567"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(), - "9876543"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(), - "-9.876e-50"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(), - "1.234e+12"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(), - ""); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(), - "10m"); - - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543); - EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); - EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10)); -} - -// -------------------------------------------------------------------- - -struct NonTriviallyCopyableAggregate { - NonTriviallyCopyableAggregate() = default; - NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs) - : value(rhs.value) {} - NonTriviallyCopyableAggregate& operator=( - const NonTriviallyCopyableAggregate& rhs) { - value = rhs.value; - return *this; - } - - int value; -}; -bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f, - std::string* e) { - return absl::ParseFlag(src, &f->value, e); -} -std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) { - return absl::StrCat(ntc.value); -} - -bool operator==(const NonTriviallyCopyableAggregate& ntc1, - const NonTriviallyCopyableAggregate& ntc2) { - return ntc1.value == ntc2.value; -} - -} // namespace - -ABSL_FLAG(bool, test_flag_eb_01, {}, ""); -ABSL_FLAG(int32_t, test_flag_eb_02, {}, ""); -ABSL_FLAG(int64_t, test_flag_eb_03, {}, ""); -ABSL_FLAG(double, test_flag_eb_04, {}, ""); -ABSL_FLAG(std::string, test_flag_eb_05, {}, ""); -ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, ""); - -namespace { - -TEST_F(FlagTest, TestEmptyBracesDefault) { - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(), - "false"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(), - "0"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(), - "0"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(), - "0"); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(), - ""); - EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(), - "0"); - - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), ""); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06), - NonTriviallyCopyableAggregate{}); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagTest, TestGetSet) { - absl::SetFlag(&FLAGS_test_flag_01, false); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false); - - absl::SetFlag(&FLAGS_test_flag_02, 321); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321); - - absl::SetFlag(&FLAGS_test_flag_03, 67); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67); - - absl::SetFlag(&FLAGS_test_flag_04, 1); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1); - - absl::SetFlag(&FLAGS_test_flag_05, -908); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908); - - absl::SetFlag(&FLAGS_test_flag_06, 4001); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001); - - absl::SetFlag(&FLAGS_test_flag_07, -23456); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456); - - absl::SetFlag(&FLAGS_test_flag_08, 975310); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310); - - absl::SetFlag(&FLAGS_test_flag_09, 1.00001); - EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10); - - absl::SetFlag(&FLAGS_test_flag_10, -3.54f); - EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f); - - absl::SetFlag(&FLAGS_test_flag_11, "asdf"); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf"); - - absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110)); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110)); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagTest, TestGetViaReflection) { - auto* handle = absl::FindCommandLineFlag("test_flag_01"); - EXPECT_EQ(*handle->TryGet<bool>(), true); - handle = absl::FindCommandLineFlag("test_flag_02"); - EXPECT_EQ(*handle->TryGet<int>(), 1234); - handle = absl::FindCommandLineFlag("test_flag_03"); - EXPECT_EQ(*handle->TryGet<int16_t>(), -34); - handle = absl::FindCommandLineFlag("test_flag_04"); - EXPECT_EQ(*handle->TryGet<uint16_t>(), 189); - handle = absl::FindCommandLineFlag("test_flag_05"); - EXPECT_EQ(*handle->TryGet<int32_t>(), 10765); - handle = absl::FindCommandLineFlag("test_flag_06"); - EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000); - handle = absl::FindCommandLineFlag("test_flag_07"); - EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567); - handle = absl::FindCommandLineFlag("test_flag_08"); - EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543); - handle = absl::FindCommandLineFlag("test_flag_09"); - EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55); - handle = absl::FindCommandLineFlag("test_flag_10"); - EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f); - handle = absl::FindCommandLineFlag("test_flag_11"); - EXPECT_EQ(*handle->TryGet<std::string>(), ""); - handle = absl::FindCommandLineFlag("test_flag_12"); - EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10)); -} - -// -------------------------------------------------------------------- - -int GetDflt1() { return 1; } - -} // namespace - -ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(), - "test int flag non const default"); -ABSL_FLAG(std::string, test_string_flag_with_non_const_default, - absl::StrCat("AAA", "BBB"), "test string flag non const default"); - -namespace { - -TEST_F(FlagTest, TestNonConstexprDefault) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1); - EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default), - "AAABBB"); -} - -// -------------------------------------------------------------------- - -} // namespace - -ABSL_FLAG(bool, test_flag_with_non_const_help, true, - absl::StrCat("test ", "flag ", "non const help")); - -namespace { - -#if !ABSL_FLAGS_STRIP_HELP -TEST_F(FlagTest, TestNonConstexprHelp) { - EXPECT_EQ( - absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(), - "test flag non const help"); -} -#endif //! ABSL_FLAGS_STRIP_HELP - -// -------------------------------------------------------------------- - -int cb_test_value = -1; -void TestFlagCB(); - -} // namespace - -ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB); - -ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() { - cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) + - absl::GetFlag(FLAGS_test_flag_with_cb); -}); - -namespace { - -void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); } - -// Tests side-effects of callback invocation. -TEST_F(FlagTest, CallbackInvocation) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200); - EXPECT_EQ(cb_test_value, 300); - - absl::SetFlag(&FLAGS_test_flag_with_cb, 1); - EXPECT_EQ(cb_test_value, 1); - - absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3); - EXPECT_EQ(cb_test_value, 4); -} - -// -------------------------------------------------------------------- - -struct CustomUDT { - CustomUDT() : a(1), b(1) {} - CustomUDT(int a_, int b_) : a(a_), b(b_) {} - - friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) { - return f1.a == f2.a && f1.b == f2.b; - } - - int a; - int b; -}; -bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) { - std::vector<absl::string_view> parts = - absl::StrSplit(in, ':', absl::SkipWhitespace()); - - if (parts.size() != 2) return false; - - if (!absl::SimpleAtoi(parts[0], &f->a)) return false; - - if (!absl::SimpleAtoi(parts[1], &f->b)) return false; - - return true; -} -std::string AbslUnparseFlag(const CustomUDT& f) { - return absl::StrCat(f.a, ":", f.b); -} - -} // namespace - -ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT"); - -namespace { - -TEST_F(FlagTest, TestCustomUDT) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1)); - absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3)); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3)); -} - -// MSVC produces link error on the type mismatch. -// Linux does not have build errors and validations work as expected. -#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST - -using FlagDeathTest = FlagTest; - -TEST_F(FlagDeathTest, TestTypeMismatchValidations) { -#if !defined(NDEBUG) - EXPECT_DEATH_IF_SUPPORTED( - static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)), - "Flag 'mistyped_int_flag' is defined as one type and declared " - "as another"); - EXPECT_DEATH_IF_SUPPORTED( - static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)), - "Flag 'mistyped_string_flag' is defined as one type and " - "declared as another"); -#endif - - EXPECT_DEATH_IF_SUPPORTED( - absl::SetFlag(&FLAGS_mistyped_int_flag, 1), - "Flag 'mistyped_int_flag' is defined as one type and declared " - "as another"); - EXPECT_DEATH_IF_SUPPORTED( - absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}), - "Flag 'mistyped_string_flag' is defined as one type and declared as " - "another"); -} - -#endif - -// -------------------------------------------------------------------- - -// A contrived type that offers implicit and explicit conversion from specific -// source types. -struct ConversionTestVal { - ConversionTestVal() = default; - explicit ConversionTestVal(int a_in) : a(a_in) {} - - enum class ViaImplicitConv { kTen = 10, kEleven }; - // NOLINTNEXTLINE - ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {} - - int a; -}; - -bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out, - std::string*) { - if (!absl::SimpleAtoi(in, &val_out->a)) { - return false; - } - return true; -} -std::string AbslUnparseFlag(const ConversionTestVal& val) { - return absl::StrCat(val.a); -} - -} // namespace - -// Flag default values can be specified with a value that converts to the flag -// value type implicitly. -ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv, - ConversionTestVal::ViaImplicitConv::kTen, - "test flag init via implicit conversion"); - -namespace { - -TEST_F(FlagTest, CanSetViaImplicitConversion) { - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10); - absl::SetFlag(&FLAGS_test_flag_implicit_conv, - ConversionTestVal::ViaImplicitConv::kEleven); - EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11); -} - -// -------------------------------------------------------------------- - -struct NonDfltConstructible { - public: - // This constructor tests that we can initialize the flag with int value - NonDfltConstructible(int i) : value(i) {} // NOLINT - - // This constructor tests that we can't initialize the flag with char value - // but can with explicitly constructed NonDfltConstructible. - explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {} - - int value; -}; - -bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out, - std::string*) { - return absl::SimpleAtoi(in, &ndc_out->value); -} -std::string AbslUnparseFlag(const NonDfltConstructible& ndc) { - return absl::StrCat(ndc.value); -} - -} // namespace - -ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'), - "Flag with non default constructible type"); -ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0, - "Flag with non default constructible type"); - -namespace { - -TEST_F(FlagTest, TestNonDefaultConstructibleType) { - EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100); - EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0); - - absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A')); - absl::SetFlag(&FLAGS_ndc_flag2, 25); - - EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100); - EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25); -} - -} // namespace - -// -------------------------------------------------------------------- - -ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr"); -ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr"); -ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr")); - -bool initializaion_order_fiasco_test = [] { - // Iterate over all the flags during static initialization. - // This should not trigger ASan's initialization-order-fiasco. - auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file"); - auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file"); - if (handle1 != nullptr && handle2 != nullptr) { - return handle1->Name() == handle2->Name(); - } - return true; -}(); - -namespace { - -TEST_F(FlagTest, TestRetiredFlagRegistration) { - auto* handle = absl::FindCommandLineFlag("old_bool_flag"); - EXPECT_TRUE(handle->IsOfType<bool>()); - EXPECT_TRUE(handle->IsRetired()); - handle = absl::FindCommandLineFlag("old_int_flag"); - EXPECT_TRUE(handle->IsOfType<int>()); - EXPECT_TRUE(handle->IsRetired()); - handle = absl::FindCommandLineFlag("old_str_flag"); - EXPECT_TRUE(handle->IsOfType<std::string>()); - EXPECT_TRUE(handle->IsRetired()); -} - -} // namespace - -// -------------------------------------------------------------------- - -namespace { - -// User-defined type with small alignment, but size exceeding 16. -struct SmallAlignUDT { - SmallAlignUDT() : c('A'), s(12) {} - char c; - int16_t s; - char bytes[14]; -}; - -bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) { - return true; -} -std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; } - -// User-defined type with small size, but not trivially copyable. -struct NonTriviallyCopyableUDT { - NonTriviallyCopyableUDT() : c('A') {} - NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {} - NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) { - c = rhs.c; - return *this; - } - - char c; -}; - -bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) { - return true; -} -std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; } - -} // namespace - -ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help"); -ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help"); - -namespace { - -TEST_F(FlagTest, TestSmallAlignUDT) { - SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt); - EXPECT_EQ(value.c, 'A'); - EXPECT_EQ(value.s, 12); - - value.c = 'B'; - value.s = 45; - absl::SetFlag(&FLAGS_test_flag_sa_udt, value); - value = absl::GetFlag(FLAGS_test_flag_sa_udt); - EXPECT_EQ(value.c, 'B'); - EXPECT_EQ(value.s, 45); -} - -TEST_F(FlagTest, TestNonTriviallyCopyableUDT) { - NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt); - EXPECT_EQ(value.c, 'A'); - - value.c = 'B'; - absl::SetFlag(&FLAGS_test_flag_ntc_udt, value); - value = absl::GetFlag(FLAGS_test_flag_ntc_udt); - EXPECT_EQ(value.c, 'B'); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/flags/flag_test_defs.cc b/third_party/abseil_cpp/absl/flags/flag_test_defs.cc deleted file mode 100644 index 4e1693cdb9c4..000000000000 --- a/third_party/abseil_cpp/absl/flags/flag_test_defs.cc +++ /dev/null @@ -1,24 +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. - -// This file is used to test the mismatch of the flag type between definition -// and declaration. These are definitions. flag_test.cc contains declarations. -#include <string> -#include "absl/flags/flag.h" - -ABSL_FLAG(int, mistyped_int_flag, 0, ""); -ABSL_FLAG(std::string, mistyped_string_flag, "", ""); -ABSL_FLAG(bool, flag_on_separate_file, false, ""); -ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, ""); diff --git a/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc b/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc deleted file mode 100644 index 4482955c4cb6..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc +++ /dev/null @@ -1,26 +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/commandlineflag.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -FlagStateInterface::~FlagStateInterface() {} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/internal/commandlineflag.h b/third_party/abseil_cpp/absl/flags/internal/commandlineflag.h deleted file mode 100644 index cb46fe2e979d..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/commandlineflag.h +++ /dev/null @@ -1,68 +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_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ -#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ - -#include "absl/base/config.h" -#include "absl/base/internal/fast_type_id.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// An alias for flag fast type id. This value identifies the flag value type -// simialarly to typeid(T), without relying on RTTI being available. In most -// cases this id is enough to uniquely identify the flag's value type. In a few -// cases we'll have to resort to using actual RTTI implementation if it is -// available. -using FlagFastTypeId = absl::base_internal::FastTypeIdType; - -// Options that control SetCommandLineOptionWithMode. -enum FlagSettingMode { - // update the flag's value unconditionally (can call this multiple times). - SET_FLAGS_VALUE, - // update the flag's value, but *only if* it has not yet been updated - // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef". - SET_FLAG_IF_DEFAULT, - // set the flag's default value to this. If the flag has not been updated - // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef") - // change the flag's current value to the new default value as well. - SET_FLAGS_DEFAULT -}; - -// Options that control ParseFrom: Source of a value. -enum ValueSource { - // Flag is being set by value specified on a command line. - kCommandLine, - // Flag is being set by value specified in the code. - kProgrammaticChange, -}; - -// Handle to FlagState objects. Specific flag state objects will restore state -// of a flag produced this flag state from method CommandLineFlag::SaveState(). -class FlagStateInterface { - public: - virtual ~FlagStateInterface(); - - // Restores the flag originated this object to the saved state. - virtual void Restore() const = 0; -}; - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/flag.cc b/third_party/abseil_cpp/absl/flags/internal/flag.cc deleted file mode 100644 index 1502e7f11d36..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/flag.cc +++ /dev/null @@ -1,568 +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/internal/flag.h" - -#include <assert.h> -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include <array> -#include <atomic> -#include <memory> -#include <new> -#include <string> -#include <typeinfo> - -#include "absl/base/call_once.h" -#include "absl/base/casts.h" -#include "absl/base/config.h" -#include "absl/base/optimization.h" -#include "absl/flags/config.h" -#include "absl/flags/internal/commandlineflag.h" -#include "absl/flags/usage_config.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// The help message indicating that the commandline flag has been -// 'stripped'. It will not show up when doing "-help" and its -// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1 -// before including absl/flags/flag.h -const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; - -namespace { - -// Currently we only validate flag values for user-defined flag types. -bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) { -#define DONT_VALIDATE(T, _) \ - if (flag_type_id == base_internal::FastTypeId<T>()) return false; - ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE) -#undef DONT_VALIDATE - - return true; -} - -// RAII helper used to temporarily unlock and relock `absl::Mutex`. -// This is used when we need to ensure that locks are released while -// invoking user supplied callbacks and then reacquired, since callbacks may -// need to acquire these locks themselves. -class MutexRelock { - public: - explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); } - ~MutexRelock() { mu_.Lock(); } - - MutexRelock(const MutexRelock&) = delete; - MutexRelock& operator=(const MutexRelock&) = delete; - - private: - absl::Mutex& mu_; -}; - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// Persistent state of the flag data. - -class FlagImpl; - -class FlagState : public flags_internal::FlagStateInterface { - public: - template <typename V> - FlagState(FlagImpl& flag_impl, const V& v, bool modified, - bool on_command_line, int64_t counter) - : flag_impl_(flag_impl), - value_(v), - modified_(modified), - on_command_line_(on_command_line), - counter_(counter) {} - - ~FlagState() override { - if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer) - 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) {} - explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {} - - void* heap_allocated; - int64_t one_word; - flags_internal::AlignedTwoWords two_words; - } value_; - bool modified_; - bool on_command_line_; - int64_t counter_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// Flag implementation, which does not depend on flag value type. - -DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {} - -void DynValueDeleter::operator()(void* ptr) const { - if (op == nullptr) return; - - Delete(op, ptr); -} - -void FlagImpl::Init() { - new (&data_guard_) absl::Mutex; - - auto def_kind = static_cast<FlagDefaultKind>(def_kind_); - - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: - // For this storage kind the default_value_ always points to gen_func - // during initialization. - assert(def_kind == FlagDefaultKind::kGenFunc); - (*default_value_.gen_func)(AlignedBufferValue()); - break; - case FlagValueStorageKind::kOneWordAtomic: { - alignas(int64_t) std::array<char, sizeof(int64_t)> buf{}; - if (def_kind == FlagDefaultKind::kGenFunc) { - (*default_value_.gen_func)(buf.data()); - } else { - assert(def_kind != FlagDefaultKind::kDynamicValue); - std::memcpy(buf.data(), &default_value_, Sizeof(op_)); - } - OneWordValue().store(absl::bit_cast<int64_t>(buf), - std::memory_order_release); - break; - } - case FlagValueStorageKind::kTwoWordsAtomic: { - // For this storage kind the default_value_ always points to gen_func - // during initialization. - assert(def_kind == FlagDefaultKind::kGenFunc); - alignas(AlignedTwoWords) std::array<char, sizeof(AlignedTwoWords)> buf{}; - (*default_value_.gen_func)(buf.data()); - auto atomic_value = absl::bit_cast<AlignedTwoWords>(buf); - TwoWordsValue().store(atomic_value, std::memory_order_release); - break; - } - } -} - -absl::Mutex* FlagImpl::DataGuard() const { - absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init, - const_cast<FlagImpl*>(this)); - - // data_guard_ is initialized inside Init. - return reinterpret_cast<absl::Mutex*>(&data_guard_); -} - -void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id, - const std::type_info* (*gen_rtti)()) const { - FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_); - - // `rhs_type_id` is the fast type id corresponding to the declaration - // visibile at the call site. `lhs_type_id` is the fast type id - // corresponding to the type specified in flag definition. They must match - // for this operation to be well-defined. - if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return; - - const std::type_info* lhs_runtime_type_id = - flags_internal::RuntimeTypeId(op_); - const std::type_info* rhs_runtime_type_id = (*gen_rtti)(); - - if (lhs_runtime_type_id == rhs_runtime_type_id) return; - -#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) - if (*lhs_runtime_type_id == *rhs_runtime_type_id) return; -#endif - - ABSL_INTERNAL_LOG( - FATAL, absl::StrCat("Flag '", Name(), - "' is defined as one type and declared as another")); -} - -std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const { - void* res = nullptr; - switch (DefaultKind()) { - case FlagDefaultKind::kDynamicValue: - res = flags_internal::Clone(op_, default_value_.dynamic_value); - break; - case FlagDefaultKind::kGenFunc: - res = flags_internal::Alloc(op_); - (*default_value_.gen_func)(res); - break; - default: - res = flags_internal::Clone(op_, &default_value_); - break; - } - return {res, DynValueDeleter{op_}}; -} - -void FlagImpl::StoreValue(const void* src) { - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: - Copy(op_, src, AlignedBufferValue()); - break; - case FlagValueStorageKind::kOneWordAtomic: { - int64_t one_word_val = 0; - std::memcpy(&one_word_val, src, Sizeof(op_)); - OneWordValue().store(one_word_val, std::memory_order_release); - break; - } - case FlagValueStorageKind::kTwoWordsAtomic: { - AlignedTwoWords two_words_val{0, 0}; - std::memcpy(&two_words_val, src, Sizeof(op_)); - TwoWordsValue().store(two_words_val, std::memory_order_release); - break; - } - } - - modified_ = true; - ++counter_; - InvokeCallback(); -} - -absl::string_view FlagImpl::Name() const { return name_; } - -std::string FlagImpl::Filename() const { - return flags_internal::GetUsageConfig().normalize_filename(filename_); -} - -std::string FlagImpl::Help() const { - return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal - : help_.gen_func(); -} - -FlagFastTypeId FlagImpl::TypeId() const { - return flags_internal::FastTypeId(op_); -} - -bool FlagImpl::IsSpecifiedOnCommandLine() const { - absl::MutexLock l(DataGuard()); - return on_command_line_; -} - -std::string FlagImpl::DefaultValue() const { - absl::MutexLock l(DataGuard()); - - auto obj = MakeInitValue(); - return flags_internal::Unparse(op_, obj.get()); -} - -std::string FlagImpl::CurrentValue() const { - auto* guard = DataGuard(); // Make sure flag initialized - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: { - absl::MutexLock l(guard); - return flags_internal::Unparse(op_, AlignedBufferValue()); - } - case FlagValueStorageKind::kOneWordAtomic: { - const auto one_word_val = - absl::bit_cast<std::array<char, sizeof(int64_t)>>( - OneWordValue().load(std::memory_order_acquire)); - return flags_internal::Unparse(op_, one_word_val.data()); - } - case FlagValueStorageKind::kTwoWordsAtomic: { - const auto two_words_val = - absl::bit_cast<std::array<char, sizeof(AlignedTwoWords)>>( - TwoWordsValue().load(std::memory_order_acquire)); - return flags_internal::Unparse(op_, two_words_val.data()); - } - } - - return ""; -} - -void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) { - absl::MutexLock l(DataGuard()); - - if (callback_ == nullptr) { - callback_ = new FlagCallback; - } - callback_->func = mutation_callback; - - InvokeCallback(); -} - -void FlagImpl::InvokeCallback() const { - if (!callback_) return; - - // Make a copy of the C-style function pointer that we are about to invoke - // before we release the lock guarding it. - FlagCallbackFunc cb = callback_->func; - - // If the flag has a mutation callback this function invokes it. While the - // callback is being invoked the primary flag's mutex is unlocked and it is - // re-locked back after call to callback is completed. Callback invocation is - // guarded by flag's secondary mutex instead which prevents concurrent - // callback invocation. Note that it is possible for other thread to grab the - // primary lock and update flag's value at any time during the callback - // invocation. This is by design. Callback can get a value of the flag if - // necessary, but it might be different from the value initiated the callback - // and it also can be different by the time the callback invocation is - // completed. Requires that *primary_lock be held in exclusive mode; it may be - // released and reacquired by the implementation. - MutexRelock relock(*DataGuard()); - absl::MutexLock lock(&callback_->guard); - cb(); -} - -std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() { - absl::MutexLock l(DataGuard()); - - bool modified = modified_; - bool on_command_line = on_command_line_; - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: { - return absl::make_unique<FlagState>( - *this, flags_internal::Clone(op_, AlignedBufferValue()), modified, - on_command_line, counter_); - } - case FlagValueStorageKind::kOneWordAtomic: { - return absl::make_unique<FlagState>( - *this, OneWordValue().load(std::memory_order_acquire), modified, - on_command_line, counter_); - } - case FlagValueStorageKind::kTwoWordsAtomic: { - return absl::make_unique<FlagState>( - *this, TwoWordsValue().load(std::memory_order_acquire), modified, - on_command_line, counter_); - } - } - return nullptr; -} - -bool FlagImpl::RestoreState(const FlagState& flag_state) { - absl::MutexLock l(DataGuard()); - - if (flag_state.counter_ == counter_) { - return false; - } - - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: - StoreValue(flag_state.value_.heap_allocated); - break; - case FlagValueStorageKind::kOneWordAtomic: - StoreValue(&flag_state.value_.one_word); - break; - case FlagValueStorageKind::kTwoWordsAtomic: - StoreValue(&flag_state.value_.two_words); - break; - } - - modified_ = flag_state.modified_; - on_command_line_ = flag_state.on_command_line_; - - return true; -} - -template <typename StorageT> -StorageT* FlagImpl::OffsetValue() const { - char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this)); - // The offset is deduced via Flag value type specific op_. - size_t offset = flags_internal::ValueOffset(op_); - - return reinterpret_cast<StorageT*>(p + offset); -} - -void* FlagImpl::AlignedBufferValue() const { - assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer); - return OffsetValue<void>(); -} - -std::atomic<int64_t>& FlagImpl::OneWordValue() const { - assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic); - return OffsetValue<FlagOneWordValue>()->value; -} - -std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const { - assert(ValueStorageKind() == FlagValueStorageKind::kTwoWordsAtomic); - return OffsetValue<FlagTwoWordsValue>()->value; -} - -// Attempts to parse supplied `value` string using parsing routine in the `flag` -// argument. If parsing successful, this function replaces the dst with newly -// parsed value. In case if any error is encountered in either step, the error -// message is stored in 'err' -std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse( - absl::string_view value, std::string& err) const { - std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue(); - - std::string parse_err; - if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) { - absl::string_view err_sep = parse_err.empty() ? "" : "; "; - err = absl::StrCat("Illegal value '", value, "' specified for flag '", - Name(), "'", err_sep, parse_err); - return nullptr; - } - - return tentative_value; -} - -void FlagImpl::Read(void* dst) const { - auto* guard = DataGuard(); // Make sure flag initialized - switch (ValueStorageKind()) { - case FlagValueStorageKind::kAlignedBuffer: { - absl::MutexLock l(guard); - flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst); - break; - } - case FlagValueStorageKind::kOneWordAtomic: { - const int64_t one_word_val = - OneWordValue().load(std::memory_order_acquire); - std::memcpy(dst, &one_word_val, Sizeof(op_)); - break; - } - case FlagValueStorageKind::kTwoWordsAtomic: { - const AlignedTwoWords two_words_val = - TwoWordsValue().load(std::memory_order_acquire); - std::memcpy(dst, &two_words_val, Sizeof(op_)); - break; - } - } -} - -void FlagImpl::Write(const void* src) { - absl::MutexLock l(DataGuard()); - - if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) { - std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src), - DynValueDeleter{op_}}; - std::string ignored_error; - std::string src_as_str = flags_internal::Unparse(op_, src); - if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) { - ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), - "' to invalid value ", src_as_str)); - } - } - - StoreValue(src); -} - -// Sets the value of the flag based on specified string `value`. If the flag -// was successfully set to new value, it returns true. Otherwise, sets `err` -// to indicate the error, leaves the flag unchanged, and returns false. There -// are three ways to set the flag's value: -// * Update the current flag value -// * Update the flag's default value -// * Update the current flag value if it was never set before -// The mode is selected based on 'set_mode' parameter. -bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode, - ValueSource source, std::string& err) { - absl::MutexLock l(DataGuard()); - - switch (set_mode) { - case SET_FLAGS_VALUE: { - // set or modify the flag's value - auto tentative_value = TryParse(value, err); - if (!tentative_value) return false; - - StoreValue(tentative_value.get()); - - if (source == kCommandLine) { - on_command_line_ = true; - } - break; - } - case SET_FLAG_IF_DEFAULT: { - // set the flag's value, but only if it hasn't been set by someone else - if (modified_) { - // TODO(rogeeff): review and fix this semantic. Currently we do not fail - // in this case if flag is modified. This is misleading since the flag's - // value is not updated even though we return true. - // *err = absl::StrCat(Name(), " is already set to ", - // CurrentValue(), "\n"); - // return false; - return true; - } - auto tentative_value = TryParse(value, err); - if (!tentative_value) return false; - - StoreValue(tentative_value.get()); - break; - } - case SET_FLAGS_DEFAULT: { - auto tentative_value = TryParse(value, err); - if (!tentative_value) return false; - - if (DefaultKind() == FlagDefaultKind::kDynamicValue) { - void* old_value = default_value_.dynamic_value; - default_value_.dynamic_value = tentative_value.release(); - tentative_value.reset(old_value); - } else { - default_value_.dynamic_value = tentative_value.release(); - def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue); - } - - if (!modified_) { - // Need to set both default value *and* current, in this case. - StoreValue(default_value_.dynamic_value); - modified_ = false; - } - break; - } - } - - return true; -} - -void FlagImpl::CheckDefaultValueParsingRoundtrip() const { - std::string v = DefaultValue(); - - absl::MutexLock lock(DataGuard()); - - auto dst = MakeInitValue(); - std::string error; - if (!flags_internal::Parse(op_, v, dst.get(), &error)) { - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Flag ", Name(), " (from ", Filename(), - "): string form of default value '", v, - "' could not be parsed; error=", error)); - } - - // We do not compare dst to def since parsing/unparsing may make - // small changes, e.g., precision loss for floating point types. -} - -bool FlagImpl::ValidateInputValue(absl::string_view value) const { - absl::MutexLock l(DataGuard()); - - auto obj = MakeInitValue(); - std::string ignored_error; - return flags_internal::Parse(op_, value, obj.get(), &ignored_error); -} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/internal/flag.h b/third_party/abseil_cpp/absl/flags/internal/flag.h deleted file mode 100644 index 370d8a02ef04..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/flag.h +++ /dev/null @@ -1,775 +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_FLAGS_INTERNAL_FLAG_H_ -#define ABSL_FLAGS_INTERNAL_FLAG_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <atomic> -#include <cstring> -#include <memory> -#include <new> -#include <string> -#include <type_traits> -#include <typeinfo> - -#include "absl/base/attributes.h" -#include "absl/base/call_once.h" -#include "absl/base/config.h" -#include "absl/base/optimization.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/config.h" -#include "absl/flags/internal/commandlineflag.h" -#include "absl/flags/internal/registry.h" -#include "absl/flags/marshalling.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -/////////////////////////////////////////////////////////////////////////////// -// Forward declaration of absl::Flag<T> public API. -namespace flags_internal { -template <typename T> -class Flag; -} // namespace flags_internal - -#if defined(_MSC_VER) && !defined(__clang__) -template <typename T> -class Flag; -#else -template <typename T> -using Flag = flags_internal::Flag<T>; -#endif - -template <typename T> -ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag); - -template <typename T> -void SetFlag(absl::Flag<T>* flag, const T& v); - -template <typename T, typename V> -void SetFlag(absl::Flag<T>* flag, const V& v); - -template <typename U> -const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f); - -/////////////////////////////////////////////////////////////////////////////// -// Flag value type operations, eg., parsing, copying, etc. are provided -// by function specific to that type with a signature matching FlagOpFn. - -namespace flags_internal { - -enum class FlagOp { - kAlloc, - kDelete, - kCopy, - kCopyConstruct, - kSizeof, - kFastTypeId, - kRuntimeTypeId, - kParse, - kUnparse, - kValueOffset, -}; -using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*); - -// Forward declaration for Flag value specific operations. -template <typename T> -void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3); - -// Allocate aligned memory for a flag value. -inline void* Alloc(FlagOpFn op) { - return op(FlagOp::kAlloc, nullptr, nullptr, nullptr); -} -// Deletes memory interpreting obj as flag value type pointer. -inline void Delete(FlagOpFn op, void* obj) { - op(FlagOp::kDelete, nullptr, obj, nullptr); -} -// Copies src to dst interpreting as flag value type pointers. -inline void Copy(FlagOpFn op, const void* src, void* dst) { - op(FlagOp::kCopy, src, dst, nullptr); -} -// Construct a copy of flag value in a location pointed by dst -// based on src - pointer to the flag's value. -inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) { - op(FlagOp::kCopyConstruct, src, dst, nullptr); -} -// Makes a copy of flag value pointed by obj. -inline void* Clone(FlagOpFn op, const void* obj) { - void* res = flags_internal::Alloc(op); - flags_internal::CopyConstruct(op, obj, res); - return res; -} -// Returns true if parsing of input text is successfull. -inline bool Parse(FlagOpFn op, absl::string_view text, void* dst, - std::string* error) { - return op(FlagOp::kParse, &text, dst, error) != nullptr; -} -// Returns string representing supplied value. -inline std::string Unparse(FlagOpFn op, const void* val) { - std::string result; - op(FlagOp::kUnparse, val, &result, nullptr); - return result; -} -// Returns size of flag value type. -inline size_t Sizeof(FlagOpFn op) { - // This sequence of casts reverses the sequence from - // `flags_internal::FlagOps()` - return static_cast<size_t>(reinterpret_cast<intptr_t>( - op(FlagOp::kSizeof, nullptr, nullptr, nullptr))); -} -// Returns fast type id coresponding to the value type. -inline FlagFastTypeId FastTypeId(FlagOpFn op) { - return reinterpret_cast<FlagFastTypeId>( - op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr)); -} -// Returns fast type id coresponding to the value type. -inline const std::type_info* RuntimeTypeId(FlagOpFn op) { - return reinterpret_cast<const std::type_info*>( - op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr)); -} -// Returns offset of the field value_ from the field impl_ inside of -// absl::Flag<T> data. Given FlagImpl pointer p you can get the -// location of the corresponding value as: -// reinterpret_cast<char*>(p) + ValueOffset(). -inline ptrdiff_t ValueOffset(FlagOpFn op) { - // This sequence of casts reverses the sequence from - // `flags_internal::FlagOps()` - return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>( - op(FlagOp::kValueOffset, nullptr, nullptr, nullptr))); -} - -// Returns an address of RTTI's typeid(T). -template <typename T> -inline const std::type_info* GenRuntimeTypeId() { -#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) - return &typeid(T); -#else - return nullptr; -#endif -} - -/////////////////////////////////////////////////////////////////////////////// -// Flag help auxiliary structs. - -// This is help argument for absl::Flag encapsulating the string literal pointer -// or pointer to function generating it as well as enum descriminating two -// cases. -using HelpGenFunc = std::string (*)(); - -template <size_t N> -struct FixedCharArray { - char value[N]; - - template <size_t... I> - static constexpr FixedCharArray<N> FromLiteralString( - absl::string_view str, absl::index_sequence<I...>) { - return (void)str, FixedCharArray<N>({{str[I]..., '\0'}}); - } -}; - -template <typename Gen, size_t N = Gen::Value().size()> -constexpr FixedCharArray<N + 1> HelpStringAsArray(int) { - return FixedCharArray<N + 1>::FromLiteralString( - Gen::Value(), absl::make_index_sequence<N>{}); -} - -template <typename Gen> -constexpr std::false_type HelpStringAsArray(char) { - return std::false_type{}; -} - -union FlagHelpMsg { - constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {} - constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {} - - const char* literal; - HelpGenFunc gen_func; -}; - -enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 }; - -struct FlagHelpArg { - FlagHelpMsg source; - FlagHelpKind kind; -}; - -extern const char kStrippedFlagHelp[]; - -// These two HelpArg overloads allows us to select at compile time one of two -// way to pass Help argument to absl::Flag. We'll be passing -// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer -// first overload if possible. If help message is evaluatable on constexpr -// context We'll be able to make FixedCharArray out of it and we'll choose first -// overload. In this case the help message expression is immediately evaluated -// and is used to construct the absl::Flag. No additionl code is generated by -// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the -// consideration, in which case the second overload will be used. The second -// overload does not attempt to evaluate the help message expression -// immediately and instead delays the evaluation by returing the function -// pointer (&T::NonConst) genering the help message when necessary. This is -// evaluatable in constexpr context, but the cost is an extra function being -// generated in the ABSL_FLAG code. -template <typename Gen, size_t N> -constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) { - return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral}; -} - -template <typename Gen> -constexpr FlagHelpArg HelpArg(std::false_type) { - return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc}; -} - -/////////////////////////////////////////////////////////////////////////////// -// Flag default value auxiliary structs. - -// Signature for the function generating the initial flag value (usually -// based on default value supplied in flag's definition) -using FlagDfltGenFunc = void (*)(void*); - -union FlagDefaultSrc { - constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg) - : gen_func(gen_func_arg) {} - -#define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \ - T name##_value; \ - constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {} // NOLINT - ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE) -#undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE - - void* dynamic_value; - FlagDfltGenFunc gen_func; -}; - -enum class FlagDefaultKind : uint8_t { - kDynamicValue = 0, - kGenFunc = 1, - kOneWord = 2 // for default values UP to one word in size -}; - -struct FlagDefaultArg { - FlagDefaultSrc source; - FlagDefaultKind kind; -}; - -// This struct and corresponding overload to InitDefaultValue are used to -// facilitate usage of {} as default value in ABSL_FLAG macro. -// TODO(rogeeff): Fix handling types with explicit constructors. -struct EmptyBraces {}; - -template <typename T> -constexpr T InitDefaultValue(T t) { - return t; -} - -template <typename T> -constexpr T InitDefaultValue(EmptyBraces) { - return T{}; -} - -template <typename ValueT, typename GenT, - typename std::enable_if<std::is_integral<ValueT>::value, int>::type = - (GenT{}, 0)> -constexpr FlagDefaultArg DefaultArg(int) { - return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord}; -} - -template <typename ValueT, typename GenT> -constexpr FlagDefaultArg DefaultArg(char) { - return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc}; -} - -/////////////////////////////////////////////////////////////////////////////// -// Flag current value auxiliary structs. - -constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; } - -template <typename T> -using FlagUseOneWordStorage = std::integral_constant< - bool, absl::type_traits_internal::is_trivially_copyable<T>::value && - (sizeof(T) <= 8)>; - -#if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD) -// Clang does not always produce cmpxchg16b instruction when alignment of a 16 -// bytes type is not 16. -struct alignas(16) AlignedTwoWords { - int64_t first; - int64_t second; - - bool IsInitialized() const { - return first != flags_internal::UninitializedFlagValue(); - } -}; - -template <typename T> -using FlagUseTwoWordsStorage = std::integral_constant< - bool, absl::type_traits_internal::is_trivially_copyable<T>::value && - (sizeof(T) > 8) && (sizeof(T) <= 16)>; -#else -// This is actually unused and only here to avoid ifdefs in other palces. -struct AlignedTwoWords { - constexpr AlignedTwoWords() noexcept : dummy() {} - constexpr AlignedTwoWords(int64_t, int64_t) noexcept : dummy() {} - char dummy; - - bool IsInitialized() const { - std::abort(); - return true; - } -}; - -// This trait should be type dependent, otherwise SFINAE below will fail -template <typename T> -using FlagUseTwoWordsStorage = - std::integral_constant<bool, sizeof(T) != sizeof(T)>; -#endif - -template <typename T> -using FlagUseBufferStorage = - std::integral_constant<bool, !FlagUseOneWordStorage<T>::value && - !FlagUseTwoWordsStorage<T>::value>; - -enum class FlagValueStorageKind : uint8_t { - kAlignedBuffer = 0, - kOneWordAtomic = 1, - kTwoWordsAtomic = 2 -}; - -template <typename T> -static constexpr FlagValueStorageKind StorageKind() { - return FlagUseBufferStorage<T>::value - ? FlagValueStorageKind::kAlignedBuffer - : FlagUseOneWordStorage<T>::value - ? FlagValueStorageKind::kOneWordAtomic - : FlagValueStorageKind::kTwoWordsAtomic; -} - -struct FlagOneWordValue { - constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {} - - std::atomic<int64_t> value; -}; - -struct FlagTwoWordsValue { - constexpr FlagTwoWordsValue() - : value(AlignedTwoWords{UninitializedFlagValue(), 0}) {} - - std::atomic<AlignedTwoWords> value; -}; - -template <typename T, - FlagValueStorageKind Kind = flags_internal::StorageKind<T>()> -struct FlagValue; - -template <typename T> -struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> { - bool Get(T&) const { return false; } - - alignas(T) char value[sizeof(T)]; -}; - -template <typename T> -struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue { - bool Get(T& dst) const { - int64_t one_word_val = value.load(std::memory_order_acquire); - if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) { - return false; - } - std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T)); - return true; - } -}; - -template <typename T> -struct FlagValue<T, FlagValueStorageKind::kTwoWordsAtomic> : FlagTwoWordsValue { - bool Get(T& dst) const { - AlignedTwoWords two_words_val = value.load(std::memory_order_acquire); - if (ABSL_PREDICT_FALSE(!two_words_val.IsInitialized())) { - return false; - } - std::memcpy(&dst, static_cast<const void*>(&two_words_val), sizeof(T)); - return true; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// Flag callback auxiliary structs. - -// Signature for the mutation callback used by watched Flags -// The callback is noexcept. -// TODO(rogeeff): add noexcept after C++17 support is added. -using FlagCallbackFunc = void (*)(); - -struct FlagCallback { - FlagCallbackFunc func; - absl::Mutex guard; // Guard for concurrent callback invocations. -}; - -/////////////////////////////////////////////////////////////////////////////// -// Flag implementation, which does not depend on flag value type. -// The class encapsulates the Flag's data and access to it. - -struct DynValueDeleter { - explicit DynValueDeleter(FlagOpFn op_arg = nullptr); - void operator()(void* ptr) const; - - FlagOpFn op; -}; - -class FlagState; - -class FlagImpl final : public CommandLineFlag { - public: - constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op, - FlagHelpArg help, FlagValueStorageKind value_kind, - FlagDefaultArg default_arg) - : name_(name), - filename_(filename), - op_(op), - help_(help.source), - help_source_kind_(static_cast<uint8_t>(help.kind)), - value_storage_kind_(static_cast<uint8_t>(value_kind)), - def_kind_(static_cast<uint8_t>(default_arg.kind)), - modified_(false), - on_command_line_(false), - counter_(0), - callback_(nullptr), - default_value_(default_arg.source), - data_guard_{} {} - - // Constant access methods - void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard()); - - // Mutating access methods - void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard()); - - // Interfaces to operate on callbacks. - void SetCallback(const FlagCallbackFunc mutation_callback) - ABSL_LOCKS_EXCLUDED(*DataGuard()); - void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); - - // Used in read/write operations to validate source/target has correct type. - // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to - // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed - // int. To do that we pass the "assumed" type id (which is deduced from type - // int) as an argument `type_id`, which is in turn is validated against the - // type id stored in flag object by flag definition statement. - void AssertValidType(FlagFastTypeId type_id, - const std::type_info* (*gen_rtti)()) const; - - private: - template <typename T> - friend class Flag; - friend class FlagState; - - // Ensures that `data_guard_` is initialized and returns it. - absl::Mutex* DataGuard() const - ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_)); - // Returns heap allocated value of type T initialized with default value. - std::unique_ptr<void, DynValueDeleter> MakeInitValue() const - ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); - // Flag initialization called via absl::call_once. - void Init(); - - // Offset value access methods. One per storage kind. These methods to not - // respect const correctness, so be very carefull using them. - - // This is a shared helper routine which encapsulates most of the magic. Since - // it is only used inside the three routines below, which are defined in - // flag.cc, we can define it in that file as well. - template <typename StorageT> - StorageT* OffsetValue() const; - // This is an accessor for a value stored in an aligned buffer storage. - // Returns a mutable pointer to the start of a buffer. - void* AlignedBufferValue() 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; - // This is an accessor for a value stored as two words atomic. Returns a - // mutable reference to an atomic value. - std::atomic<AlignedTwoWords>& TwoWordsValue() const; - - // Attempts to parse supplied `value` string. If parsing is successful, - // returns new value. Otherwise returns nullptr. - std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value, - std::string& err) const - ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); - // Stores the flag value based on the pointer to the source. - void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); - - 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()); - - // Interfaces to save and restore flags to/from persistent state. - // Returns current flag state or nullptr if flag does not support - // saving and restoring a state. - std::unique_ptr<FlagStateInterface> SaveState() override - ABSL_LOCKS_EXCLUDED(*DataGuard()); - - // Restores the flag state to the supplied state object. If there is - // nothing to restore returns false. Otherwise returns true. - bool RestoreState(const FlagState& flag_state) - ABSL_LOCKS_EXCLUDED(*DataGuard()); - - bool ParseFrom(absl::string_view value, FlagSettingMode set_mode, - ValueSource source, std::string& error) override - ABSL_LOCKS_EXCLUDED(*DataGuard()); - - // Immutable flag's state. - - // Flags name passed to ABSL_FLAG as second arg. - const char* const name_; - // The file name where ABSL_FLAG resides. - const char* const filename_; - // Type-specific operations "vtable". - const FlagOpFn op_; - // Help message literal or function to generate it. - const FlagHelpMsg help_; - // Indicates if help message was supplied as literal or generator func. - const uint8_t help_source_kind_ : 1; - // Kind of storage this flag is using for the flag's value. - const uint8_t value_storage_kind_ : 2; - - uint8_t : 0; // The bytes containing the const bitfields must not be - // shared with bytes containing the mutable bitfields. - - // Mutable flag's state (guarded by `data_guard_`). - - // def_kind_ is not guard by DataGuard() since it is accessed in Init without - // locks. - uint8_t def_kind_ : 2; - // Has this flag's value been modified? - bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard()); - // Has this flag been specified on command line. - bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); - - // Unique tag for absl::call_once call to initialize this flag. - absl::once_flag init_control_; - - // 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_; - - // This is reserved space for an absl::Mutex to guard flag data. It will be - // initialized in FlagImpl::Init via placement new. - // We can't use "absl::Mutex data_guard_", since this class is not literal. - // We do not want to use "absl::Mutex* data_guard_", since this would require - // heap allocation during initialization, which is both slows program startup - // and can fail. Using reserved space + placement new allows us to avoid both - // problems. - alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)]; -}; - -/////////////////////////////////////////////////////////////////////////////// -// The Flag object parameterized by the flag's value type. This class implements -// flag reflection handle interface. - -template <typename T> -class Flag { - public: - constexpr Flag(const char* name, const char* filename, FlagHelpArg help, - const FlagDefaultArg default_arg) - : impl_(name, filename, &FlagOps<T>, help, - flags_internal::StorageKind<T>(), default_arg), - value_() {} - - // CommandLineFlag interface - absl::string_view Name() const { return impl_.Name(); } - std::string Filename() const { return impl_.Filename(); } - std::string Help() const { return impl_.Help(); } - // Do not use. To be removed. - bool IsSpecifiedOnCommandLine() const { - return impl_.IsSpecifiedOnCommandLine(); - } - std::string DefaultValue() const { return impl_.DefaultValue(); } - std::string CurrentValue() const { return impl_.CurrentValue(); } - - private: - template <typename, bool> - friend class FlagRegistrar; - friend class FlagImplPeer; - - T Get() const { - // See implementation notes in CommandLineFlag::Get(). - union U { - T value; - U() {} - ~U() { value.~T(); } - }; - U u; - -#if !defined(NDEBUG) - impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>); -#endif - - if (!value_.Get(u.value)) impl_.Read(&u.value); - return std::move(u.value); - } - void Set(const T& v) { - impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>); - impl_.Write(&v); - } - - // Access to the reflection. - const CommandLineFlag& Reflect() const { return impl_; } - - // Flag's data - // The implementation depends on value_ field to be placed exactly after the - // impl_ field, so that impl_ can figure out the offset to the value and - // access it. - FlagImpl impl_; - FlagValue<T> value_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// Trampoline for friend access - -class FlagImplPeer { - public: - template <typename T, typename FlagType> - static T InvokeGet(const FlagType& flag) { - return flag.Get(); - } - template <typename FlagType, typename T> - static void InvokeSet(FlagType& flag, const T& v) { - flag.Set(v); - } - template <typename FlagType> - static const CommandLineFlag& InvokeReflect(const FlagType& f) { - return f.Reflect(); - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// Implementation of Flag value specific operations routine. -template <typename T> -void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { - switch (op) { - case FlagOp::kAlloc: { - std::allocator<T> alloc; - return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1); - } - case FlagOp::kDelete: { - T* p = static_cast<T*>(v2); - p->~T(); - std::allocator<T> alloc; - std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1); - return nullptr; - } - case FlagOp::kCopy: - *static_cast<T*>(v2) = *static_cast<const T*>(v1); - return nullptr; - case FlagOp::kCopyConstruct: - new (v2) T(*static_cast<const T*>(v1)); - return nullptr; - case FlagOp::kSizeof: - return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T))); - case FlagOp::kFastTypeId: - return const_cast<void*>(base_internal::FastTypeId<T>()); - case FlagOp::kRuntimeTypeId: - return const_cast<std::type_info*>(GenRuntimeTypeId<T>()); - case FlagOp::kParse: { - // Initialize the temporary instance of type T based on current value in - // destination (which is going to be flag's default value). - T temp(*static_cast<T*>(v2)); - if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp, - static_cast<std::string*>(v3))) { - return nullptr; - } - *static_cast<T*>(v2) = std::move(temp); - return v2; - } - case FlagOp::kUnparse: - *static_cast<std::string*>(v2) = - absl::UnparseFlag<T>(*static_cast<const T*>(v1)); - return nullptr; - case FlagOp::kValueOffset: { - // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the - // offset of the data. - ptrdiff_t round_to = alignof(FlagValue<T>); - ptrdiff_t offset = - (sizeof(FlagImpl) + round_to - 1) / round_to * round_to; - return reinterpret_cast<void*>(offset); - } - } - return nullptr; -} - -/////////////////////////////////////////////////////////////////////////////// -// This class facilitates Flag object registration and tail expression-based -// flag definition, for example: -// ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher); -struct FlagRegistrarEmpty {}; -template <typename T, bool do_register> -class FlagRegistrar { - public: - explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) { - if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_); - } - - FlagRegistrar OnUpdate(FlagCallbackFunc cb) && { - flag_.impl_.SetCallback(cb); - return *this; - } - - // Make the registrar "die" gracefully as an empty struct on a line where - // registration happens. Registrar objects are intended to live only as - // temporary. - operator FlagRegistrarEmpty() const { return {}; } // NOLINT - - private: - Flag<T>& flag_; // Flag being registered (not owned). -}; - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_FLAG_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/parse.h b/third_party/abseil_cpp/absl/flags/internal/parse.h deleted file mode 100644 index de706c898470..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/parse.h +++ /dev/null @@ -1,59 +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_FLAGS_INTERNAL_PARSE_H_ -#define ABSL_FLAGS_INTERNAL_PARSE_H_ - -#include <string> -#include <vector> - -#include "absl/base/config.h" -#include "absl/flags/declare.h" -#include "absl/strings/string_view.h" - -ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile); -ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv); -ABSL_DECLARE_FLAG(std::vector<std::string>, tryfromenv); -ABSL_DECLARE_FLAG(std::vector<std::string>, undefok); - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs }; -enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage }; -enum class OnUndefinedFlag { - kIgnoreUndefined, - kReportUndefined, - kAbortIfUndefined -}; - -std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], - ArgvListAction arg_list_act, - UsageFlagsAction usage_flag_act, - OnUndefinedFlag on_undef_flag); - -// -------------------------------------------------------------------- -// Inspect original command line - -// Returns true if flag with specified name was either present on the original -// command line or specified in flag file present on the original command line. -bool WasPresentOnCommandLine(absl::string_view flag_name); - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_PARSE_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/path_util.h b/third_party/abseil_cpp/absl/flags/internal/path_util.h deleted file mode 100644 index a6594d3347e1..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/path_util.h +++ /dev/null @@ -1,62 +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_FLAGS_INTERNAL_PATH_UTIL_H_ -#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_ - -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// A portable interface that returns the basename of the filename passed as an -// argument. It is similar to basename(3) -// <https://linux.die.net/man/3/basename>. -// For example: -// flags_internal::Basename("a/b/prog/file.cc") -// returns "file.cc" -// flags_internal::Basename("file.cc") -// returns "file.cc" -inline absl::string_view Basename(absl::string_view filename) { - auto last_slash_pos = filename.find_last_of("/\\"); - - return last_slash_pos == absl::string_view::npos - ? filename - : filename.substr(last_slash_pos + 1); -} - -// A portable interface that returns the directory name of the filename -// passed as an argument, including the trailing slash. -// Returns the empty string if a slash is not found in the input file name. -// For example: -// flags_internal::Package("a/b/prog/file.cc") -// returns "a/b/prog/" -// flags_internal::Package("file.cc") -// returns "" -inline absl::string_view Package(absl::string_view filename) { - auto last_slash_pos = filename.find_last_of("/\\"); - - return last_slash_pos == absl::string_view::npos - ? absl::string_view() - : filename.substr(0, last_slash_pos + 1); -} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/path_util_test.cc b/third_party/abseil_cpp/absl/flags/internal/path_util_test.cc deleted file mode 100644 index 2091373c88ea..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/path_util_test.cc +++ /dev/null @@ -1,46 +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/internal/path_util.h" - -#include "gtest/gtest.h" - -namespace { - -namespace flags = absl::flags_internal; - -TEST(FlagsPathUtilTest, TestBasename) { - EXPECT_EQ(flags::Basename(""), ""); - EXPECT_EQ(flags::Basename("a.cc"), "a.cc"); - EXPECT_EQ(flags::Basename("dir/a.cc"), "a.cc"); - EXPECT_EQ(flags::Basename("dir1/dir2/a.cc"), "a.cc"); - EXPECT_EQ(flags::Basename("../dir1/dir2/a.cc"), "a.cc"); - EXPECT_EQ(flags::Basename("/dir1/dir2/a.cc"), "a.cc"); - EXPECT_EQ(flags::Basename("/dir1/dir2/../dir3/a.cc"), "a.cc"); -} - -// -------------------------------------------------------------------- - -TEST(FlagsPathUtilTest, TestPackage) { - EXPECT_EQ(flags::Package(""), ""); - EXPECT_EQ(flags::Package("a.cc"), ""); - EXPECT_EQ(flags::Package("dir/a.cc"), "dir/"); - EXPECT_EQ(flags::Package("dir1/dir2/a.cc"), "dir1/dir2/"); - EXPECT_EQ(flags::Package("../dir1/dir2/a.cc"), "../dir1/dir2/"); - EXPECT_EQ(flags::Package("/dir1/dir2/a.cc"), "/dir1/dir2/"); - EXPECT_EQ(flags::Package("/dir1/dir2/../dir3/a.cc"), "/dir1/dir2/../dir3/"); -} - -} // namespace diff --git a/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 a7eb58b6d45f..000000000000 --- 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 c64435cd6199..000000000000 --- 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.cc b/third_party/abseil_cpp/absl/flags/internal/program_name.cc deleted file mode 100644 index 51d698da8b31..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/program_name.cc +++ /dev/null @@ -1,60 +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/internal/program_name.h" - -#include <string> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/const_init.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/internal/path_util.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit); -ABSL_CONST_INIT static std::string* program_name - ABSL_GUARDED_BY(program_name_guard) = nullptr; - -std::string ProgramInvocationName() { - absl::MutexLock l(&program_name_guard); - - return program_name ? *program_name : "UNKNOWN"; -} - -std::string ShortProgramInvocationName() { - absl::MutexLock l(&program_name_guard); - - return program_name ? std::string(flags_internal::Basename(*program_name)) - : "UNKNOWN"; -} - -void SetProgramInvocationName(absl::string_view prog_name_str) { - absl::MutexLock l(&program_name_guard); - - if (!program_name) - program_name = new std::string(prog_name_str); - else - program_name->assign(prog_name_str.data(), prog_name_str.size()); -} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/internal/program_name.h b/third_party/abseil_cpp/absl/flags/internal/program_name.h deleted file mode 100644 index b99b94fe18ab..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/program_name.h +++ /dev/null @@ -1,50 +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_FLAGS_INTERNAL_PROGRAM_NAME_H_ -#define ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_ - -#include <string> - -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -// -------------------------------------------------------------------- -// Program name - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()` -// is never called. At the moment this is always set to argv[0] as part of -// library initialization. -std::string ProgramInvocationName(); - -// Returns base name for program invocation name. For example, if -// ProgramInvocationName() == "a/b/mybinary" -// then -// ShortProgramInvocationName() == "mybinary" -std::string ShortProgramInvocationName(); - -// Sets program invocation name to a new value. Should only be called once -// during program initialization, before any threads are spawned. -void SetProgramInvocationName(absl::string_view prog_name_str); - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/program_name_test.cc b/third_party/abseil_cpp/absl/flags/internal/program_name_test.cc deleted file mode 100644 index aff9f6315e4e..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/program_name_test.cc +++ /dev/null @@ -1,61 +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/internal/program_name.h" - -#include <string> - -#include "gtest/gtest.h" -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" - -namespace { - -namespace flags = absl::flags_internal; - -TEST(FlagsPathUtilTest, TestProgamNameInterfaces) { - flags::SetProgramInvocationName("absl/flags/program_name_test"); - std::string program_name = flags::ProgramInvocationName(); - for (char& c : program_name) - if (c == '\\') c = '/'; - -#if !defined(__wasm__) && !defined(__asmjs__) - const std::string expect_name = "absl/flags/program_name_test"; - const std::string expect_basename = "program_name_test"; -#else - // For targets that generate javascript or webassembly the invocation name - // has the special value below. - const std::string expect_name = "this.program"; - const std::string expect_basename = "this.program"; -#endif - - EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name; - EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename); - - flags::SetProgramInvocationName("a/my_test"); - - EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test"); - EXPECT_EQ(flags::ShortProgramInvocationName(), "my_test"); - - absl::string_view not_null_terminated("absl/aaa/bbb"); - not_null_terminated = not_null_terminated.substr(1, 10); - - flags::SetProgramInvocationName(not_null_terminated); - - EXPECT_EQ(flags::ProgramInvocationName(), "bsl/aaa/bb"); - EXPECT_EQ(flags::ShortProgramInvocationName(), "bb"); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/flags/internal/registry.h b/third_party/abseil_cpp/absl/flags/internal/registry.h deleted file mode 100644 index a8d9eb9cb0bb..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/registry.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. - -#ifndef ABSL_FLAGS_INTERNAL_REGISTRY_H_ -#define ABSL_FLAGS_INTERNAL_REGISTRY_H_ - -#include <functional> - -#include "absl/base/config.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/internal/commandlineflag.h" -#include "absl/strings/string_view.h" - -// -------------------------------------------------------------------- -// Global flags registry API. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// Executes specified visitor for each non-retired flag in the registry. While -// callback are executed, the registry is locked and can't be changed. -void ForEachFlag(std::function<void(CommandLineFlag&)> visitor); - -//----------------------------------------------------------------------------- - -bool RegisterCommandLineFlag(CommandLineFlag&); - -void FinalizeRegistry(); - -//----------------------------------------------------------------------------- -// Retired registrations: -// -// Retired flag registrations are treated specially. A 'retired' flag is -// provided only for compatibility with automated invocations that still -// name it. A 'retired' flag: -// - is not bound to a C++ FLAGS_ reference. -// - has a type and a value, but that value is intentionally inaccessible. -// - does not appear in --help messages. -// - is fully supported by _all_ flag parsing routines. -// - consumes args normally, and complains about type mismatches in its -// argument. -// - emits a complaint but does not die (e.g. LOG(ERROR)) if it is -// accessed by name through the flags API for parsing or otherwise. -// -// The registrations for a flag happen in an unspecified order as the -// initializers for the namespace-scope objects of a program are run. -// Any number of weak registrations for a flag can weakly define the flag. -// One non-weak registration will upgrade the flag from weak to non-weak. -// Further weak registrations of a non-weak flag are ignored. -// -// This mechanism is designed to support moving dead flags into a -// 'graveyard' library. An example migration: -// -// 0: Remove references to this FLAGS_flagname in the C++ codebase. -// 1: Register as 'retired' in old_lib. -// 2: Make old_lib depend on graveyard. -// 3: Add a redundant 'retired' registration to graveyard. -// 4: Remove the old_lib 'retired' registration. -// 5: Eventually delete the graveyard registration entirely. -// - -// Retire flag with name "name" and type indicated by ops. -void Retire(const char* name, FlagFastTypeId type_id, char* buf); - -constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*); -constexpr size_t kRetiredFlagObjAlignment = alignof(void*); - -// Registered a retired flag with name 'flag_name' and type 'T'. -template <typename T> -class RetiredFlag { - public: - void Retire(const char* flag_name) { - flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_); - } - - private: - alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize]; -}; - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_REGISTRY_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/usage.cc b/third_party/abseil_cpp/absl/flags/internal/usage.cc deleted file mode 100644 index f29d7c9b48f0..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/usage.cc +++ /dev/null @@ -1,524 +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/internal/usage.h" - -#include <stdint.h> - -#include <functional> -#include <map> -#include <ostream> -#include <string> -#include <utility> -#include <vector> - -#include "absl/base/config.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/flag.h" -#include "absl/flags/internal/flag.h" -#include "absl/flags/internal/path_util.h" -#include "absl/flags/internal/private_handle_accessor.h" -#include "absl/flags/internal/program_name.h" -#include "absl/flags/internal/registry.h" -#include "absl/flags/usage_config.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" - -// Dummy global variables to prevent anyone else defining these. -bool FLAGS_help = false; -bool FLAGS_helpfull = false; -bool FLAGS_helpshort = false; -bool FLAGS_helppackage = false; -bool FLAGS_version = false; -bool FLAGS_only_check_args = false; -bool FLAGS_helpon = false; -bool FLAGS_helpmatch = false; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { -namespace { - -using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>; - -// Maximum length size in a human readable format. -constexpr size_t kHrfMaxLineLength = 80; - -// This class is used to emit an XML element with `tag` and `text`. -// It adds opening and closing tags and escapes special characters in the text. -// For example: -// std::cout << XMLElement("title", "Milk & Cookies"); -// prints "<title>Milk & Cookies</title>" -class XMLElement { - public: - XMLElement(absl::string_view tag, absl::string_view txt) - : tag_(tag), txt_(txt) {} - - friend std::ostream& operator<<(std::ostream& out, - const XMLElement& xml_elem) { - out << "<" << xml_elem.tag_ << ">"; - - for (auto c : xml_elem.txt_) { - switch (c) { - case '"': - out << """; - break; - case '\'': - out << "'"; - break; - case '&': - out << "&"; - break; - case '<': - out << "<"; - break; - case '>': - out << ">"; - break; - default: - out << c; - break; - } - } - - return out << "</" << xml_elem.tag_ << ">"; - } - - private: - absl::string_view tag_; - absl::string_view txt_; -}; - -// -------------------------------------------------------------------- -// Helper class to pretty-print info about a flag. - -class FlagHelpPrettyPrinter { - public: - // Pretty printer holds on to the std::ostream& reference to direct an output - // to that stream. - FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len, - size_t wrapped_line_indent, std::ostream& out) - : out_(out), - max_line_len_(max_line_len), - min_line_len_(min_line_len), - wrapped_line_indent_(wrapped_line_indent), - line_len_(0), - first_line_(true) {} - - void Write(absl::string_view str, bool wrap_line = false) { - // Empty string - do nothing. - if (str.empty()) return; - - std::vector<absl::string_view> tokens; - if (wrap_line) { - for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) { - if (!tokens.empty()) { - // Keep line separators in the input string. - tokens.push_back("\n"); - } - for (auto token : - absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty())) { - tokens.push_back(token); - } - } - } else { - tokens.push_back(str); - } - - for (auto token : tokens) { - bool new_line = (line_len_ == 0); - - // Respect line separators in the input string. - if (token == "\n") { - EndLine(); - continue; - } - - // Write the token, ending the string first if necessary/possible. - if (!new_line && - (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) { - EndLine(); - new_line = true; - } - - if (new_line) { - StartLine(); - } else { - out_ << ' '; - ++line_len_; - } - - out_ << token; - line_len_ += token.size(); - } - } - - void StartLine() { - if (first_line_) { - line_len_ = min_line_len_; - first_line_ = false; - } else { - line_len_ = min_line_len_ + wrapped_line_indent_; - } - out_ << std::string(line_len_, ' '); - } - void EndLine() { - out_ << '\n'; - line_len_ = 0; - } - - private: - std::ostream& out_; - const size_t max_line_len_; - const size_t min_line_len_; - const size_t wrapped_line_indent_; - size_t line_len_; - bool first_line_; -}; - -void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) { - FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out); - - // Flag name. - printer.Write(absl::StrCat("--", flag.Name())); - - // Flag help. - printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true); - - // The listed default value will be the actual default from the flag - // definition in the originating source file, unless the value has - // subsequently been modified using SetCommandLineOption() with mode - // SET_FLAGS_DEFAULT. - std::string dflt_val = flag.DefaultValue(); - std::string curr_val = flag.CurrentValue(); - bool is_modified = curr_val != dflt_val; - - if (flag.IsOfType<std::string>()) { - dflt_val = absl::StrCat("\"", dflt_val, "\""); - } - printer.Write(absl::StrCat("default: ", dflt_val, ";")); - - if (is_modified) { - if (flag.IsOfType<std::string>()) { - curr_val = absl::StrCat("\"", curr_val, "\""); - } - printer.Write(absl::StrCat("currently: ", curr_val, ";")); - } - - printer.EndLine(); -} - -// Shows help for every filename which matches any of the filters -// If filters are empty, shows help for every file. -// If a flag's help message has been stripped (e.g. by adding '#define -// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help' -// and its variants. -void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb, - HelpFormat format, absl::string_view program_usage_message) { - if (format == HelpFormat::kHumanReadable) { - out << flags_internal::ShortProgramInvocationName() << ": " - << program_usage_message << "\n\n"; - } else { - // XML schema is not a part of our public API for now. - out << "<?xml version=\"1.0\"?>\n" - << "<!-- This output should be used with care. We do not report type " - "names for flags with user defined types -->\n" - << "<!-- Prefer flag only_check_args for validating flag inputs -->\n" - // The document. - << "<AllFlags>\n" - // The program name and usage. - << XMLElement("program", flags_internal::ShortProgramInvocationName()) - << '\n' - << XMLElement("usage", program_usage_message) << '\n'; - } - - // Map of package name to - // map of file name to - // vector of flags in the file. - // This map is used to output matching flags grouped by package and file - // name. - std::map<std::string, - std::map<std::string, std::vector<const absl::CommandLineFlag*>>> - matching_flags; - - flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) { - // Ignore retired flags. - if (flag.IsRetired()) return; - - // If the flag has been stripped, pretend that it doesn't exist. - if (flag.Help() == flags_internal::kStrippedFlagHelp) return; - - // Make sure flag satisfies the filter - if (!filter_cb(flag)) return; - - std::string flag_filename = flag.Filename(); - - matching_flags[std::string(flags_internal::Package(flag_filename))] - [flag_filename] - .push_back(&flag); - }); - - absl::string_view package_separator; // controls blank lines between packages - absl::string_view file_separator; // controls blank lines between files - for (const auto& package : matching_flags) { - if (format == HelpFormat::kHumanReadable) { - out << package_separator; - package_separator = "\n\n"; - } - - file_separator = ""; - for (const auto& flags_in_file : package.second) { - if (format == HelpFormat::kHumanReadable) { - out << file_separator << " Flags from " << flags_in_file.first - << ":\n"; - file_separator = "\n"; - } - - for (const auto* flag : flags_in_file.second) { - flags_internal::FlagHelp(out, *flag, format); - } - } - } - - if (format == HelpFormat::kHumanReadable) { - FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out); - - if (filter_cb && matching_flags.empty()) { - printer.Write("No flags matched.\n", true); - } - printer.EndLine(); - printer.Write( - "Try --helpfull to get a list of all flags or --help=substring " - "shows help for flags which include specified substring in either " - "in the name, or description or path.\n", - true); - } else { - // The end of the document. - out << "</AllFlags>\n"; - } -} - -void FlagsHelpImpl(std::ostream& out, - flags_internal::FlagKindFilter filename_filter_cb, - HelpFormat format, absl::string_view program_usage_message) { - FlagsHelpImpl( - out, - [&](const absl::CommandLineFlag& flag) { - return filename_filter_cb && filename_filter_cb(flag.Filename()); - }, - format, program_usage_message); -} - -} // namespace - -// -------------------------------------------------------------------- -// Produces the help message describing specific flag. -void FlagHelp(std::ostream& out, const CommandLineFlag& flag, - HelpFormat format) { - if (format == HelpFormat::kHumanReadable) - flags_internal::FlagHelpHumanReadable(flag, out); -} - -// -------------------------------------------------------------------- -// Produces the help messages for all flags matching the filename filter. -// If filter is empty produces help messages for all flags. -void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format, - absl::string_view program_usage_message) { - flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) { - return filter.empty() || filename.find(filter) != absl::string_view::npos; - }; - flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message); -} - -// -------------------------------------------------------------------- -// Checks all the 'usage' command line flags to see if any have been set. -// If so, handles them appropriately. -int HandleUsageFlags(std::ostream& out, - absl::string_view program_usage_message) { - switch (GetFlagsHelpMode()) { - case HelpMode::kNone: - break; - case HelpMode::kImportant: - flags_internal::FlagsHelpImpl( - out, flags_internal::GetUsageConfig().contains_help_flags, - GetFlagsHelpFormat(), program_usage_message); - return 1; - - case HelpMode::kShort: - flags_internal::FlagsHelpImpl( - out, flags_internal::GetUsageConfig().contains_helpshort_flags, - GetFlagsHelpFormat(), program_usage_message); - return 1; - - case HelpMode::kFull: - flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(), - program_usage_message); - return 1; - - case HelpMode::kPackage: - flags_internal::FlagsHelpImpl( - out, flags_internal::GetUsageConfig().contains_helppackage_flags, - GetFlagsHelpFormat(), program_usage_message); - - return 1; - - case HelpMode::kMatch: { - std::string substr = GetFlagsHelpMatchSubstr(); - if (substr.empty()) { - // show all options - flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(), - program_usage_message); - } else { - auto filter_cb = [&substr](const absl::CommandLineFlag& flag) { - if (absl::StrContains(flag.Name(), substr)) return true; - if (absl::StrContains(flag.Filename(), substr)) return true; - if (absl::StrContains(flag.Help(), substr)) return true; - - return false; - }; - flags_internal::FlagsHelpImpl( - out, filter_cb, HelpFormat::kHumanReadable, program_usage_message); - } - - return 1; - } - case HelpMode::kVersion: - if (flags_internal::GetUsageConfig().version_string) - out << flags_internal::GetUsageConfig().version_string(); - // Unlike help, we may be asking for version in a script, so return 0 - return 0; - - case HelpMode::kOnlyCheckArgs: - return 0; - } - - return -1; -} - -// -------------------------------------------------------------------- -// Globals representing usage reporting flags - -namespace { - -ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit); -ABSL_CONST_INIT std::string* match_substr - ABSL_GUARDED_BY(help_attributes_guard) = nullptr; -ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) = - HelpMode::kNone; -ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) = - HelpFormat::kHumanReadable; - -} // namespace - -std::string GetFlagsHelpMatchSubstr() { - absl::MutexLock l(&help_attributes_guard); - if (match_substr == nullptr) return ""; - return *match_substr; -} - -void SetFlagsHelpMatchSubstr(absl::string_view substr) { - absl::MutexLock l(&help_attributes_guard); - if (match_substr == nullptr) match_substr = new std::string; - match_substr->assign(substr.data(), substr.size()); -} - -HelpMode GetFlagsHelpMode() { - absl::MutexLock l(&help_attributes_guard); - // Refer to dummy variales to prevent linker dropping them - if (FLAGS_help || FLAGS_helpfull || FLAGS_helpshort || FLAGS_helppackage || - FLAGS_version || FLAGS_only_check_args || FLAGS_helpon || - FLAGS_helpmatch) { - help_mode = HelpMode::kNone; - } - return help_mode; -} - -void SetFlagsHelpMode(HelpMode mode) { - absl::MutexLock l(&help_attributes_guard); - help_mode = mode; -} - -HelpFormat GetFlagsHelpFormat() { - absl::MutexLock l(&help_attributes_guard); - return help_format; -} - -void SetFlagsHelpFormat(HelpFormat format) { - absl::MutexLock l(&help_attributes_guard); - help_format = format; -} - -// Deduces usage flags from the input argument in a form --name=value or -// --name. argument is already split into name and value before we call this -// function. -bool DeduceUsageFlags(absl::string_view name, absl::string_view value) { - if (absl::ConsumePrefix(&name, "help")) { - if (name == "") { - if (value.empty()) { - SetFlagsHelpMode(HelpMode::kImportant); - } else { - SetFlagsHelpMode(HelpMode::kMatch); - SetFlagsHelpMatchSubstr(value); - } - return true; - } - - if (name == "match") { - SetFlagsHelpMode(HelpMode::kMatch); - SetFlagsHelpMatchSubstr(value); - return true; - } - - if (name == "on") { - SetFlagsHelpMode(HelpMode::kMatch); - SetFlagsHelpMatchSubstr(absl::StrCat("/", value, ".")); - return true; - } - - if (name == "full") { - SetFlagsHelpMode(HelpMode::kFull); - return true; - } - - if (name == "short") { - SetFlagsHelpMode(HelpMode::kShort); - return true; - } - - if (name == "package") { - SetFlagsHelpMode(HelpMode::kPackage); - return true; - } - - return false; - } - - if (name == "version") { - SetFlagsHelpMode(HelpMode::kVersion); - return true; - } - - if (name == "only_check_args") { - SetFlagsHelpMode(HelpMode::kOnlyCheckArgs); - return true; - } - - return false; -} - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/internal/usage.h b/third_party/abseil_cpp/absl/flags/internal/usage.h deleted file mode 100644 index c0bcac57628a..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/usage.h +++ /dev/null @@ -1,104 +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_FLAGS_INTERNAL_USAGE_H_ -#define ABSL_FLAGS_INTERNAL_USAGE_H_ - -#include <iosfwd> -#include <string> - -#include "absl/base/config.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/declare.h" -#include "absl/strings/string_view.h" - -// -------------------------------------------------------------------- -// Usage reporting interfaces - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// The format to report the help messages in. -enum class HelpFormat { - kHumanReadable, -}; - -// Streams the help message describing `flag` to `out`. -// The default value for `flag` is included in the output. -void FlagHelp(std::ostream& out, const CommandLineFlag& flag, - HelpFormat format = HelpFormat::kHumanReadable); - -// Produces the help messages for all flags matching the filter. A flag matches -// the filter if it is defined in a file with a filename which includes -// filter string as a substring. You can use '/' and '.' to restrict the -// matching to a specific file names. For example: -// FlagsHelp(out, "/path/to/file."); -// restricts help to only flags which resides in files named like: -// .../path/to/file.<ext> -// for any extension 'ext'. If the filter is empty this function produces help -// messages for all flags. -void FlagsHelp(std::ostream& out, absl::string_view filter, - HelpFormat format, absl::string_view program_usage_message); - -// -------------------------------------------------------------------- - -// If any of the 'usage' related command line flags (listed on the bottom of -// this file) has been set this routine produces corresponding help message in -// the specified output stream and returns: -// 0 - if "version" or "only_check_flags" flags were set and handled. -// 1 - if some other 'usage' related flag was set and handled. -// -1 - if no usage flags were set on a commmand line. -// Non negative return values are expected to be used as an exit code for a -// binary. -int HandleUsageFlags(std::ostream& out, - absl::string_view program_usage_message); - -// -------------------------------------------------------------------- -// Globals representing usage reporting flags - -enum class HelpMode { - kNone, - kImportant, - kShort, - kFull, - kPackage, - kMatch, - kVersion, - kOnlyCheckArgs -}; - -// Returns substring to filter help output (--help=substr argument) -std::string GetFlagsHelpMatchSubstr(); -// Returns the requested help mode. -HelpMode GetFlagsHelpMode(); -// Returns the requested help format. -HelpFormat GetFlagsHelpFormat(); - -// These are corresponding setters to the attributes above. -void SetFlagsHelpMatchSubstr(absl::string_view); -void SetFlagsHelpMode(HelpMode); -void SetFlagsHelpFormat(HelpFormat); - -// Deduces usage flags from the input argument in a form --name=value or -// --name. argument is already split into name and value before we call this -// function. -bool DeduceUsageFlags(absl::string_view name, absl::string_view value); - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_INTERNAL_USAGE_H_ diff --git a/third_party/abseil_cpp/absl/flags/internal/usage_test.cc b/third_party/abseil_cpp/absl/flags/internal/usage_test.cc deleted file mode 100644 index b5c2487da577..000000000000 --- a/third_party/abseil_cpp/absl/flags/internal/usage_test.cc +++ /dev/null @@ -1,493 +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/internal/usage.h" - -#include <stdint.h> - -#include <sstream> -#include <string> - -#include "gtest/gtest.h" -#include "absl/flags/flag.h" -#include "absl/flags/internal/parse.h" -#include "absl/flags/internal/path_util.h" -#include "absl/flags/internal/program_name.h" -#include "absl/flags/reflection.h" -#include "absl/flags/usage.h" -#include "absl/flags/usage_config.h" -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" - -ABSL_FLAG(int, usage_reporting_test_flag_01, 101, - "usage_reporting_test_flag_01 help message"); -ABSL_FLAG(bool, usage_reporting_test_flag_02, false, - "usage_reporting_test_flag_02 help message"); -ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03, - "usage_reporting_test_flag_03 help message"); -ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L, - "usage_reporting_test_flag_04 help message"); - -static const char kTestUsageMessage[] = "Custom usage message"; - -struct UDT { - UDT() = default; - UDT(const UDT&) = default; -}; -bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; } -std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; } - -ABSL_FLAG(UDT, usage_reporting_test_flag_05, {}, - "usage_reporting_test_flag_05 help message"); - -ABSL_FLAG( - std::string, usage_reporting_test_flag_06, {}, - "usage_reporting_test_flag_06 help message.\n" - "\n" - "Some more help.\n" - "Even more long long long long long long long long long long long long " - "help message."); - -namespace { - -namespace flags = absl::flags_internal; - -static std::string NormalizeFileName(absl::string_view fname) { -#ifdef _WIN32 - std::string normalized(fname); - std::replace(normalized.begin(), normalized.end(), '\\', '/'); - fname = normalized; -#endif - - auto absl_pos = fname.rfind("absl/"); - if (absl_pos != absl::string_view::npos) { - fname = fname.substr(absl_pos); - } - return std::string(fname); -} - -class UsageReportingTest : public testing::Test { - protected: - UsageReportingTest() { - // Install default config for the use on this unit test. - // Binary may install a custom config before tests are run. - absl::FlagsUsageConfig default_config; - default_config.normalize_filename = &NormalizeFileName; - absl::SetFlagsUsageConfig(default_config); - } - ~UsageReportingTest() override { - flags::SetFlagsHelpMode(flags::HelpMode::kNone); - flags::SetFlagsHelpMatchSubstr(""); - flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable); - } - - private: - absl::FlagSaver flag_saver_; -}; - -// -------------------------------------------------------------------- - -using UsageReportingDeathTest = UsageReportingTest; - -TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) { - EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage); - -#ifndef _WIN32 - // TODO(rogeeff): figure out why this does not work on Windows. - EXPECT_DEATH_IF_SUPPORTED( - absl::SetProgramUsageMessage("custom usage message"), - ".*SetProgramUsageMessage\\(\\) called twice.*"); -#endif -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) { - const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01"); - std::stringstream test_buf; - - flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); - EXPECT_EQ( - test_buf.str(), - R"( --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; -)"); -} - -TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) { - const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02"); - std::stringstream test_buf; - - flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); - EXPECT_EQ( - test_buf.str(), - R"( --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; -)"); -} - -TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) { - const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03"); - std::stringstream test_buf; - - flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); - EXPECT_EQ( - test_buf.str(), - R"( --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; -)"); -} - -TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) { - const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04"); - std::stringstream test_buf; - - flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); - EXPECT_EQ( - test_buf.str(), - R"( --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; -)"); -} - -TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) { - const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05"); - std::stringstream test_buf; - - flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); - EXPECT_EQ( - test_buf.str(), - R"( --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestFlagsHelpHRF) { - std::string usage_test_flags_out = - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"; - - std::stringstream test_buf_01; - flags::FlagsHelp(test_buf_01, "usage_test.cc", - flags::HelpFormat::kHumanReadable, kTestUsageMessage); - EXPECT_EQ(test_buf_01.str(), usage_test_flags_out); - - std::stringstream test_buf_02; - flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc", - flags::HelpFormat::kHumanReadable, kTestUsageMessage); - EXPECT_EQ(test_buf_02.str(), usage_test_flags_out); - - std::stringstream test_buf_03; - flags::FlagsHelp(test_buf_03, "usage_test", flags::HelpFormat::kHumanReadable, - kTestUsageMessage); - EXPECT_EQ(test_buf_03.str(), usage_test_flags_out); - - std::stringstream test_buf_04; - flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc", - flags::HelpFormat::kHumanReadable, kTestUsageMessage); - EXPECT_EQ(test_buf_04.str(), - R"(usage_test: Custom usage message - -No flags matched. - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); - - std::stringstream test_buf_05; - flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable, - kTestUsageMessage); - std::string test_out = test_buf_05.str(); - absl::string_view test_out_str(test_out); - EXPECT_TRUE( - absl::StartsWith(test_out_str, "usage_test: Custom usage message")); - EXPECT_TRUE(absl::StrContains( - test_out_str, "Flags from absl/flags/internal/usage_test.cc:")); - EXPECT_TRUE( - absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 ")); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestNoUsageFlags) { - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { - flags::SetFlagsHelpMode(flags::HelpMode::kShort); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_help_simple) { - flags::SetFlagsHelpMode(flags::HelpMode::kImportant); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) { - flags::SetFlagsHelpMode(flags::HelpMode::kMatch); - flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06"); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) { - flags::SetFlagsHelpMode(flags::HelpMode::kMatch); - flags::SetFlagsHelpMatchSubstr("test_flag"); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { - flags::SetFlagsHelpMode(flags::HelpMode::kPackage); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_version) { - flags::SetFlagsHelpMode(flags::HelpMode::kVersion); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); -#ifndef NDEBUG - EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n"); -#else - EXPECT_EQ(test_buf.str(), "usage_test\n"); -#endif -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) { - flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs); - - std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); - EXPECT_EQ(test_buf.str(), ""); -} - -// -------------------------------------------------------------------- - -TEST_F(UsageReportingTest, TestUsageFlag_helpon) { - flags::SetFlagsHelpMode(flags::HelpMode::kMatch); - flags::SetFlagsHelpMatchSubstr("/bla-bla."); - - std::stringstream test_buf_01; - EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1); - EXPECT_EQ(test_buf_01.str(), - R"(usage_test: Custom usage message - -No flags matched. - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); - - flags::SetFlagsHelpMatchSubstr("/usage_test."); - - std::stringstream test_buf_02; - EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1); - EXPECT_EQ(test_buf_02.str(), - R"(usage_test: Custom usage message - - Flags from absl/flags/internal/usage_test.cc: - --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); - default: 101; - --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); - default: false; - --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); - default: 1.03; - --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); - default: 1000000000000004; - --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); - default: UDT{}; - --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. - - Some more help. - Even more long long long long long long long long long long long long help - message.); default: ""; - -Try --helpfull to get a list of all flags or --help=substring shows help for -flags which include specified substring in either in the name, or description or -path. -)"); -} - -// -------------------------------------------------------------------- - -} // namespace - -int main(int argc, char* argv[]) { - (void)absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc - flags::SetProgramInvocationName("usage_test"); - absl::SetProgramUsageMessage(kTestUsageMessage); - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/third_party/abseil_cpp/absl/flags/marshalling.cc b/third_party/abseil_cpp/absl/flags/marshalling.cc deleted file mode 100644 index 81f9cebd6f41..000000000000 --- a/third_party/abseil_cpp/absl/flags/marshalling.cc +++ /dev/null @@ -1,241 +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/marshalling.h" - -#include <stddef.h> - -#include <cmath> -#include <limits> -#include <string> -#include <type_traits> -#include <vector> - -#include "absl/base/config.h" -#include "absl/base/log_severity.h" -#include "absl/base/macros.h" -#include "absl/strings/ascii.h" -#include "absl/strings/match.h" -#include "absl/strings/numbers.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_join.h" -#include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// -------------------------------------------------------------------- -// AbslParseFlag specializations for boolean type. - -bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) { - const char* kTrue[] = {"1", "t", "true", "y", "yes"}; - const char* kFalse[] = {"0", "f", "false", "n", "no"}; - static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal"); - - text = absl::StripAsciiWhitespace(text); - - for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) { - if (absl::EqualsIgnoreCase(text, kTrue[i])) { - *dst = true; - return true; - } else if (absl::EqualsIgnoreCase(text, kFalse[i])) { - *dst = false; - return true; - } - } - return false; // didn't match a legal input -} - -// -------------------------------------------------------------------- -// AbslParseFlag for integral types. - -// Return the base to use for parsing text as an integer. Leading 0x -// puts us in base 16. But leading 0 does not put us in base 8. It -// caused too many bugs when we had that behavior. -static int NumericBase(absl::string_view text) { - const bool hex = (text.size() >= 2 && text[0] == '0' && - (text[1] == 'x' || text[1] == 'X')); - return hex ? 16 : 10; -} - -template <typename IntType> -inline bool ParseFlagImpl(absl::string_view text, IntType& dst) { - text = absl::StripAsciiWhitespace(text); - - return absl::numbers_internal::safe_strtoi_base(text, &dst, - NumericBase(text)); -} - -bool AbslParseFlag(absl::string_view text, short* dst, std::string*) { - int val; - if (!ParseFlagImpl(text, val)) return false; - if (static_cast<short>(val) != val) // worked, but number out of range - return false; - *dst = static_cast<short>(val); - return true; -} - -bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) { - unsigned int val; - if (!ParseFlagImpl(text, val)) return false; - if (static_cast<unsigned short>(val) != - val) // worked, but number out of range - return false; - *dst = static_cast<unsigned short>(val); - return true; -} - -bool AbslParseFlag(absl::string_view text, int* dst, std::string*) { - return ParseFlagImpl(text, *dst); -} - -bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) { - return ParseFlagImpl(text, *dst); -} - -bool AbslParseFlag(absl::string_view text, long* dst, std::string*) { - return ParseFlagImpl(text, *dst); -} - -bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) { - return ParseFlagImpl(text, *dst); -} - -bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) { - return ParseFlagImpl(text, *dst); -} - -bool AbslParseFlag(absl::string_view text, unsigned long long* dst, - std::string*) { - return ParseFlagImpl(text, *dst); -} - -// -------------------------------------------------------------------- -// AbslParseFlag for floating point types. - -bool AbslParseFlag(absl::string_view text, float* dst, std::string*) { - return absl::SimpleAtof(text, dst); -} - -bool AbslParseFlag(absl::string_view text, double* dst, std::string*) { - return absl::SimpleAtod(text, dst); -} - -// -------------------------------------------------------------------- -// AbslParseFlag for strings. - -bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) { - dst->assign(text.data(), text.size()); - return true; -} - -// -------------------------------------------------------------------- -// AbslParseFlag for vector of strings. - -bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst, - std::string*) { - // An empty flag value corresponds to an empty vector, not a vector - // with a single, empty std::string. - if (text.empty()) { - dst->clear(); - return true; - } - *dst = absl::StrSplit(text, ',', absl::AllowEmpty()); - return true; -} - -// -------------------------------------------------------------------- -// AbslUnparseFlag specializations for various builtin flag types. - -std::string Unparse(bool v) { return v ? "true" : "false"; } -std::string Unparse(short v) { return absl::StrCat(v); } -std::string Unparse(unsigned short v) { return absl::StrCat(v); } -std::string Unparse(int v) { return absl::StrCat(v); } -std::string Unparse(unsigned int v) { return absl::StrCat(v); } -std::string Unparse(long v) { return absl::StrCat(v); } -std::string Unparse(unsigned long v) { return absl::StrCat(v); } -std::string Unparse(long long v) { return absl::StrCat(v); } -std::string Unparse(unsigned long long v) { return absl::StrCat(v); } -template <typename T> -std::string UnparseFloatingPointVal(T v) { - // digits10 is guaranteed to roundtrip correctly in string -> value -> string - // conversions, but may not be enough to represent all the values correctly. - std::string digit10_str = - absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v); - if (std::isnan(v) || std::isinf(v)) return digit10_str; - - T roundtrip_val = 0; - std::string err; - if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) && - roundtrip_val == v) { - return digit10_str; - } - - // max_digits10 is the number of base-10 digits that are necessary to uniquely - // represent all distinct values. - return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v); -} -std::string Unparse(float v) { return UnparseFloatingPointVal(v); } -std::string Unparse(double v) { return UnparseFloatingPointVal(v); } -std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); } -std::string AbslUnparseFlag(const std::vector<std::string>& v) { - return absl::StrJoin(v, ","); -} - -} // namespace flags_internal - -bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst, - std::string* err) { - text = absl::StripAsciiWhitespace(text); - if (text.empty()) { - *err = "no value provided"; - return false; - } - if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1); - if (absl::EqualsIgnoreCase(text, "info")) { - *dst = absl::LogSeverity::kInfo; - return true; - } - if (absl::EqualsIgnoreCase(text, "warning")) { - *dst = absl::LogSeverity::kWarning; - return true; - } - if (absl::EqualsIgnoreCase(text, "error")) { - *dst = absl::LogSeverity::kError; - return true; - } - if (absl::EqualsIgnoreCase(text, "fatal")) { - *dst = absl::LogSeverity::kFatal; - return true; - } - std::underlying_type<absl::LogSeverity>::type numeric_value; - if (absl::ParseFlag(text, &numeric_value, err)) { - *dst = static_cast<absl::LogSeverity>(numeric_value); - return true; - } - *err = "only integers and absl::LogSeverity enumerators are accepted"; - return false; -} - -std::string AbslUnparseFlag(absl::LogSeverity v) { - if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v); - return absl::UnparseFlag(static_cast<int>(v)); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/marshalling.h b/third_party/abseil_cpp/absl/flags/marshalling.h deleted file mode 100644 index 0b5033547e97..000000000000 --- a/third_party/abseil_cpp/absl/flags/marshalling.h +++ /dev/null @@ -1,264 +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. -// -// ----------------------------------------------------------------------------- -// File: marshalling.h -// ----------------------------------------------------------------------------- -// -// This header file defines the API for extending Abseil flag support to -// custom types, and defines the set of overloads for fundamental types. -// -// Out of the box, the Abseil flags library supports the following types: -// -// * `bool` -// * `int16_t` -// * `uint16_t` -// * `int32_t` -// * `uint32_t` -// * `int64_t` -// * `uint64_t` -// * `float` -// * `double` -// * `std::string` -// * `std::vector<std::string>` -// * `absl::LogSeverity` (provided natively for layering reasons) -// -// Note that support for integral types is implemented using overloads for -// variable-width fundamental types (`short`, `int`, `long`, etc.). However, -// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`, -// etc.) we've noted above within flag definitions. -// -// In addition, several Abseil libraries provide their own custom support for -// Abseil flags. Documentation for these formats is provided in the type's -// `AbslParseFlag()` definition. -// -// The Abseil time library provides the following support for civil time values: -// -// * `absl::CivilSecond` -// * `absl::CivilMinute` -// * `absl::CivilHour` -// * `absl::CivilDay` -// * `absl::CivilMonth` -// * `absl::CivilYear` -// -// and also provides support for the following absolute time values: -// -// * `absl::Duration` -// * `absl::Time` -// -// Additional support for Abseil types will be noted here as it is added. -// -// You can also provide your own custom flags by adding overloads for -// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See -// below.) -// -// ----------------------------------------------------------------------------- -// Adding Type Support for Abseil Flags -// ----------------------------------------------------------------------------- -// -// To add support for your user-defined type, add overloads of `AbslParseFlag()` -// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T` -// is a class type, these functions can be friend function definitions. These -// overloads must be added to the same namespace where the type is defined, so -// that they can be discovered by Argument-Dependent Lookup (ADL). -// -// Example: -// -// namespace foo { -// -// enum OutputMode { kPlainText, kHtml }; -// -// // AbslParseFlag converts from a string to OutputMode. -// // Must be in same namespace as OutputMode. -// -// // Parses an OutputMode from the command line flag value `text. Returns -// // `true` and sets `*mode` on success; returns `false` and sets `*error` -// // on failure. -// bool AbslParseFlag(absl::string_view text, -// OutputMode* mode, -// std::string* error) { -// if (text == "plaintext") { -// *mode = kPlainText; -// return true; -// } -// if (text == "html") { -// *mode = kHtml; -// return true; -// } -// *error = "unknown value for enumeration"; -// return false; -// } -// -// // AbslUnparseFlag converts from an OutputMode to a string. -// // Must be in same namespace as OutputMode. -// -// // Returns a textual flag value corresponding to the OutputMode `mode`. -// std::string AbslUnparseFlag(OutputMode mode) { -// switch (mode) { -// case kPlainText: return "plaintext"; -// case kHtml: return "html"; -// } -// return absl::StrCat(mode); -// } -// -// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class -// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads -// for a type should only be declared in the same file and namespace as said -// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a -// given type will be discovered via Argument-Dependent Lookup (ADL). -// -// `AbslParseFlag()` may need, in turn, to parse simpler constituent types -// using `absl::ParseFlag()`. For example, a custom struct `MyFlagType` -// consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()` -// overload for its `MyFlagType` like so: -// -// Example: -// -// namespace my_flag_type { -// -// struct MyFlagType { -// std::pair<int, std::string> my_flag_data; -// }; -// -// bool AbslParseFlag(absl::string_view text, MyFlagType* flag, -// std::string* err); -// -// std::string AbslUnparseFlag(const MyFlagType&); -// -// // Within the implementation, `AbslParseFlag()` will, in turn invoke -// // `absl::ParseFlag()` on its constituent `int` and `std::string` types -// // (which have built-in Abseil flag support. -// -// bool AbslParseFlag(absl::string_view text, MyFlagType* flag, -// std::string* err) { -// std::pair<absl::string_view, absl::string_view> tokens = -// absl::StrSplit(text, ','); -// if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err)) -// return false; -// if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err)) -// return false; -// return true; -// } -// -// // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on -// // the constituent types. -// std::string AbslUnparseFlag(const MyFlagType& flag) { -// return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first), -// ",", -// absl::UnparseFlag(flag.my_flag_data.second)); -// } -#ifndef ABSL_FLAGS_MARSHALLING_H_ -#define ABSL_FLAGS_MARSHALLING_H_ - -#include <string> -#include <vector> - -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types. -bool AbslParseFlag(absl::string_view, bool*, std::string*); -bool AbslParseFlag(absl::string_view, short*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, unsigned short*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, int*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, unsigned long long*, // NOLINT - std::string*); -bool AbslParseFlag(absl::string_view, float*, std::string*); -bool AbslParseFlag(absl::string_view, double*, std::string*); -bool AbslParseFlag(absl::string_view, std::string*, std::string*); -bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); - -template <typename T> -bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { - // Comment on next line provides a good compiler error message if T - // does not have AbslParseFlag(absl::string_view, T*, std::string*). - return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag? -} - -// Strings and std:: containers do not have the same overload resolution -// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we -// can avoid the need for additional specializations of Unparse (below). -std::string AbslUnparseFlag(absl::string_view v); -std::string AbslUnparseFlag(const std::vector<std::string>&); - -template <typename T> -std::string Unparse(const T& v) { - // Comment on next line provides a good compiler error message if T does not - // have UnparseFlag. - return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag? -} - -// Overloads for builtin types. -std::string Unparse(bool v); -std::string Unparse(short v); // NOLINT -std::string Unparse(unsigned short v); // NOLINT -std::string Unparse(int v); // NOLINT -std::string Unparse(unsigned int v); // NOLINT -std::string Unparse(long v); // NOLINT -std::string Unparse(unsigned long v); // NOLINT -std::string Unparse(long long v); // NOLINT -std::string Unparse(unsigned long long v); // NOLINT -std::string Unparse(float v); -std::string Unparse(double v); - -} // namespace flags_internal - -// ParseFlag() -// -// Parses a string value into a flag value of type `T`. Do not add overloads of -// this function for your type directly; instead, add an `AbslParseFlag()` -// free function as documented above. -// -// Some implementations of `AbslParseFlag()` for types which consist of other, -// constituent types which already have Abseil flag support, may need to call -// `absl::ParseFlag()` on those consituent string values. (See above.) -template <typename T> -inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) { - return flags_internal::InvokeParseFlag(input, dst, error); -} - -// UnparseFlag() -// -// Unparses a flag value of type `T` into a string value. Do not add overloads -// of this function for your type directly; instead, add an `AbslUnparseFlag()` -// free function as documented above. -// -// Some implementations of `AbslUnparseFlag()` for types which consist of other, -// constituent types which already have Abseil flag support, may want to call -// `absl::UnparseFlag()` on those constituent types. (See above.) -template <typename T> -inline std::string UnparseFlag(const T& v) { - return flags_internal::Unparse(v); -} - -// Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's -// definition because it is layered below flags. See proper documentation in -// base/log_severity.h. -enum class LogSeverity : int; -bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); -std::string AbslUnparseFlag(absl::LogSeverity); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_MARSHALLING_H_ diff --git a/third_party/abseil_cpp/absl/flags/marshalling_test.cc b/third_party/abseil_cpp/absl/flags/marshalling_test.cc deleted file mode 100644 index 4a64ce11a165..000000000000 --- a/third_party/abseil_cpp/absl/flags/marshalling_test.cc +++ /dev/null @@ -1,904 +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/marshalling.h" - -#include <stdint.h> - -#include <cmath> -#include <limits> -#include <string> -#include <vector> - -#include "gtest/gtest.h" - -namespace { - -TEST(MarshallingTest, TestBoolParsing) { - std::string err; - bool value; - - // True values. - EXPECT_TRUE(absl::ParseFlag("True", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("true", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("TRUE", &value, &err)); - EXPECT_TRUE(value); - - EXPECT_TRUE(absl::ParseFlag("Yes", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("yes", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("YES", &value, &err)); - EXPECT_TRUE(value); - - EXPECT_TRUE(absl::ParseFlag("t", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("T", &value, &err)); - EXPECT_TRUE(value); - - EXPECT_TRUE(absl::ParseFlag("y", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("Y", &value, &err)); - EXPECT_TRUE(value); - - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_TRUE(value); - - // False values. - EXPECT_TRUE(absl::ParseFlag("False", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("false", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("FALSE", &value, &err)); - EXPECT_FALSE(value); - - EXPECT_TRUE(absl::ParseFlag("No", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("no", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("NO", &value, &err)); - EXPECT_FALSE(value); - - EXPECT_TRUE(absl::ParseFlag("f", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("F", &value, &err)); - EXPECT_FALSE(value); - - EXPECT_TRUE(absl::ParseFlag("n", &value, &err)); - EXPECT_FALSE(value); - EXPECT_TRUE(absl::ParseFlag("N", &value, &err)); - EXPECT_FALSE(value); - - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_FALSE(value); - - // Whitespace handling. - EXPECT_TRUE(absl::ParseFlag(" true", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag("true ", &value, &err)); - EXPECT_TRUE(value); - EXPECT_TRUE(absl::ParseFlag(" true ", &value, &err)); - EXPECT_TRUE(value); - - // Invalid input. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("11", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("tt", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt16Parsing) { - std::string err; - int16_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); - EXPECT_EQ(value, -1); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("-18765", &value, &err)); - EXPECT_EQ(value, -18765); - EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); - EXPECT_EQ(value, 3); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("-001", &value, &err)); - EXPECT_EQ(value, -1); - EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); - EXPECT_EQ(value, 100); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); - EXPECT_EQ(value, 564); - // TODO(rogeeff): fix below validations - EXPECT_FALSE(absl::ParseFlag("-0x7FFD", &value, &err)); - EXPECT_NE(value, -3); - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err)); - EXPECT_EQ(value, 34); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("40000", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUint16Parsing) { - std::string err; - uint16_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); - EXPECT_EQ(value, 3); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); - EXPECT_EQ(value, 100); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); - EXPECT_EQ(value, 564); - // TODO(rogeeff): fix below validations - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err)); - EXPECT_EQ(value, 34); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("70000", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt32Parsing) { - std::string err; - int32_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); - EXPECT_EQ(value, -1); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err)); - EXPECT_EQ(value, -98765); - EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); - EXPECT_EQ(value, 3); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("-001", &value, &err)); - EXPECT_EQ(value, -1); - EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); - EXPECT_EQ(value, 100); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); - EXPECT_EQ(value, 564); - // TODO(rogeeff): fix below validations - EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFD", &value, &err)); - EXPECT_NE(value, -3); - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err)); - EXPECT_EQ(value, 34); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("70000000000", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUint32Parsing) { - std::string err; - uint32_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); - EXPECT_EQ(value, 3); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); - EXPECT_EQ(value, 100); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err)); - EXPECT_EQ(value, 564); - EXPECT_TRUE(absl::ParseFlag("0xFFFFFFFD", &value, &err)); - EXPECT_EQ(value, 4294967293); - // TODO(rogeeff): fix below validations - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err)); - EXPECT_EQ(value, 34); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("140000000000", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt64Parsing) { - std::string err; - int64_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("-1", &value, &err)); - EXPECT_EQ(value, -1); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err)); - EXPECT_EQ(value, -98765); - EXPECT_TRUE(absl::ParseFlag("+3", &value, &err)); - EXPECT_EQ(value, 3); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err)); - EXPECT_EQ(value, 100); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0XFFFAAABBBCCCDDD", &value, &err)); - EXPECT_EQ(value, 1152827684197027293); - // TODO(rogeeff): fix below validation - EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFFFFFFFFFE", &value, &err)); - EXPECT_NE(value, -2); - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - EXPECT_TRUE(absl::ParseFlag(" 0x7F ", &value, &err)); - EXPECT_EQ(value, 127); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUInt64Parsing) { - std::string err; - uint64_t value; - - // Decimal values. - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0", &value, &err)); - EXPECT_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("123", &value, &err)); - EXPECT_EQ(value, 123); - EXPECT_TRUE(absl::ParseFlag("+13", &value, &err)); - EXPECT_EQ(value, 13); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("001", &value, &err)); - EXPECT_EQ(value, 1); - EXPECT_TRUE(absl::ParseFlag("0000300", &value, &err)); - EXPECT_EQ(value, 300); - - // Hex values. - EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err)); - EXPECT_EQ(value, 16); - EXPECT_TRUE(absl::ParseFlag("0XFFFF", &value, &err)); - EXPECT_EQ(value, 65535); - // TODO(rogeeff): fix below validation - EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err)); - EXPECT_NE(value, 49); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err)); - EXPECT_EQ(value, 11); - EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err)); - EXPECT_EQ(value, 12); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("-1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2U", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestFloatParsing) { - std::string err; - float value; - - // Ordinary values. - EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err)); - EXPECT_FLOAT_EQ(value, 1.3f); - EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err)); - EXPECT_DOUBLE_EQ(value, -0.1f); - EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.01f); - - // Scientific values. - EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err)); - EXPECT_DOUBLE_EQ(value, 1.2e3f); - EXPECT_TRUE(absl::ParseFlag("9.8765402e-37", &value, &err)); - EXPECT_DOUBLE_EQ(value, 9.8765402e-37f); - EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.11e+3f); - EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.f); - EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err)); - EXPECT_TRUE(std::isinf(value)); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err)); - EXPECT_DOUBLE_EQ(value, 1.6f); - EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.0001f); - - // Trailing zero values. - EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err)); - EXPECT_DOUBLE_EQ(value, -5.1f); - - // Exceptional values. - EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err)); - EXPECT_TRUE(std::isnan(value)); - EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err)); - EXPECT_TRUE(std::isinf(value)); - - // Hex values - EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err)); - EXPECT_DOUBLE_EQ(value, 66096.f); - EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err)); - EXPECT_NEAR(value, -60.4092f, 5e-5f); - EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err)); - EXPECT_NEAR(value, 1.01328e-05f, 5e-11f); - EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err)); - EXPECT_NEAR(value, 0.0078125f, 5e-8f); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10.1 ", &value, &err)); - EXPECT_DOUBLE_EQ(value, 10.1f); - EXPECT_TRUE(absl::ParseFlag(" 2.34", &value, &err)); - EXPECT_DOUBLE_EQ(value, 2.34f); - EXPECT_TRUE(absl::ParseFlag(" 5.7 ", &value, &err)); - EXPECT_DOUBLE_EQ(value, 5.7f); - EXPECT_TRUE(absl::ParseFlag(" -0xE0.F3p01 ", &value, &err)); - EXPECT_NEAR(value, -449.8984375f, 5e-8f); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err)); - // TODO(rogeeff): below assertion should fail - EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestDoubleParsing) { - std::string err; - double value; - - // Ordinary values. - EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err)); - EXPECT_DOUBLE_EQ(value, 1.3); - EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err)); - EXPECT_DOUBLE_EQ(value, -0.1); - EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.01); - - // Scientific values. - EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err)); - EXPECT_DOUBLE_EQ(value, 1.2e3); - EXPECT_TRUE(absl::ParseFlag("9.00000002e-123", &value, &err)); - EXPECT_DOUBLE_EQ(value, 9.00000002e-123); - EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.11e+3); - EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0); - EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err)); - EXPECT_TRUE(std::isinf(value)); - - // Leading zero values. - EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err)); - EXPECT_DOUBLE_EQ(value, 1.6); - EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err)); - EXPECT_DOUBLE_EQ(value, 0.0001); - - // Trailing zero values. - EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err)); - EXPECT_DOUBLE_EQ(value, -5.1); - - // Exceptional values. - EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err)); - EXPECT_TRUE(std::isnan(value)); - EXPECT_TRUE(absl::ParseFlag("nan", &value, &err)); - EXPECT_TRUE(std::isnan(value)); - EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err)); - EXPECT_TRUE(std::isinf(value)); - EXPECT_TRUE(absl::ParseFlag("inf", &value, &err)); - EXPECT_TRUE(std::isinf(value)); - - // Hex values - EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err)); - EXPECT_DOUBLE_EQ(value, 66096); - EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err)); - EXPECT_NEAR(value, -60.4092, 5e-5); - EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err)); - EXPECT_NEAR(value, 1.01328e-05, 5e-11); - EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err)); - EXPECT_NEAR(value, 0.0078125, 5e-8); - - // Whitespace handling - EXPECT_TRUE(absl::ParseFlag("10.1 ", &value, &err)); - EXPECT_DOUBLE_EQ(value, 10.1); - EXPECT_TRUE(absl::ParseFlag(" 2.34", &value, &err)); - EXPECT_DOUBLE_EQ(value, 2.34); - EXPECT_TRUE(absl::ParseFlag(" 5.7 ", &value, &err)); - EXPECT_DOUBLE_EQ(value, 5.7); - EXPECT_TRUE(absl::ParseFlag(" -0xE0.F3p01 ", &value, &err)); - EXPECT_NEAR(value, -449.8984375, 5e-8); - - // Invalid values. - EXPECT_FALSE(absl::ParseFlag("", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag(" ", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("--1", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\n", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("\t", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err)); - EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err)); - // TODO(rogeeff): below assertion should fail - EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err)); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestStringParsing) { - std::string err; - std::string value; - - EXPECT_TRUE(absl::ParseFlag("", &value, &err)); - EXPECT_EQ(value, ""); - EXPECT_TRUE(absl::ParseFlag(" ", &value, &err)); - EXPECT_EQ(value, " "); - EXPECT_TRUE(absl::ParseFlag(" ", &value, &err)); - EXPECT_EQ(value, " "); - EXPECT_TRUE(absl::ParseFlag("\n", &value, &err)); - EXPECT_EQ(value, "\n"); - EXPECT_TRUE(absl::ParseFlag("\t", &value, &err)); - EXPECT_EQ(value, "\t"); - EXPECT_TRUE(absl::ParseFlag("asdfg", &value, &err)); - EXPECT_EQ(value, "asdfg"); - EXPECT_TRUE(absl::ParseFlag("asdf ghjk", &value, &err)); - EXPECT_EQ(value, "asdf ghjk"); - EXPECT_TRUE(absl::ParseFlag("a\nb\nc", &value, &err)); - EXPECT_EQ(value, "a\nb\nc"); - EXPECT_TRUE(absl::ParseFlag("asd\0fgh", &value, &err)); - EXPECT_EQ(value, "asd"); - EXPECT_TRUE(absl::ParseFlag("\\\\", &value, &err)); - EXPECT_EQ(value, "\\\\"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestVectorOfStringParsing) { - std::string err; - std::vector<std::string> value; - - EXPECT_TRUE(absl::ParseFlag("", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>{}); - EXPECT_TRUE(absl::ParseFlag("1", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"1"})); - EXPECT_TRUE(absl::ParseFlag("a,b", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"a", "b"})); - EXPECT_TRUE(absl::ParseFlag("a,b,c,", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"a", "b", "c", ""})); - EXPECT_TRUE(absl::ParseFlag("a,,", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"a", "", ""})); - EXPECT_TRUE(absl::ParseFlag(",", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"", ""})); - EXPECT_TRUE(absl::ParseFlag("a, b,c ", &value, &err)); - EXPECT_EQ(value, std::vector<std::string>({"a", " b", "c "})); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestBoolUnparsing) { - EXPECT_EQ(absl::UnparseFlag(true), "true"); - EXPECT_EQ(absl::UnparseFlag(false), "false"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt16Unparsing) { - int16_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = -1; - EXPECT_EQ(absl::UnparseFlag(value), "-1"); - value = 9876; - EXPECT_EQ(absl::UnparseFlag(value), "9876"); - value = -987; - EXPECT_EQ(absl::UnparseFlag(value), "-987"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUint16Unparsing) { - uint16_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = 19876; - EXPECT_EQ(absl::UnparseFlag(value), "19876"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt32Unparsing) { - int32_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = -1; - EXPECT_EQ(absl::UnparseFlag(value), "-1"); - value = 12345; - EXPECT_EQ(absl::UnparseFlag(value), "12345"); - value = -987; - EXPECT_EQ(absl::UnparseFlag(value), "-987"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUint32Unparsing) { - uint32_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = 1234500; - EXPECT_EQ(absl::UnparseFlag(value), "1234500"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestInt64Unparsing) { - int64_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = -1; - EXPECT_EQ(absl::UnparseFlag(value), "-1"); - value = 123456789L; - EXPECT_EQ(absl::UnparseFlag(value), "123456789"); - value = -987654321L; - EXPECT_EQ(absl::UnparseFlag(value), "-987654321"); - value = 0x7FFFFFFFFFFFFFFF; - EXPECT_EQ(absl::UnparseFlag(value), "9223372036854775807"); - value = 0xFFFFFFFFFFFFFFFF; - EXPECT_EQ(absl::UnparseFlag(value), "-1"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestUint64Unparsing) { - uint64_t value; - - value = 1; - EXPECT_EQ(absl::UnparseFlag(value), "1"); - value = 0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = 123456789L; - EXPECT_EQ(absl::UnparseFlag(value), "123456789"); - value = 0xFFFFFFFFFFFFFFFF; - EXPECT_EQ(absl::UnparseFlag(value), "18446744073709551615"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestFloatUnparsing) { - float value; - - value = 1.1f; - EXPECT_EQ(absl::UnparseFlag(value), "1.1"); - value = 0.01f; - EXPECT_EQ(absl::UnparseFlag(value), "0.01"); - value = 1.23e-2f; - EXPECT_EQ(absl::UnparseFlag(value), "0.0123"); - value = -0.71f; - EXPECT_EQ(absl::UnparseFlag(value), "-0.71"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestDoubleUnparsing) { - double value; - - value = 1.1; - EXPECT_EQ(absl::UnparseFlag(value), "1.1"); - value = 0.01; - EXPECT_EQ(absl::UnparseFlag(value), "0.01"); - value = 1.23e-2; - EXPECT_EQ(absl::UnparseFlag(value), "0.0123"); - value = -0.71; - EXPECT_EQ(absl::UnparseFlag(value), "-0.71"); - value = -0; - EXPECT_EQ(absl::UnparseFlag(value), "0"); - value = std::nan(""); - EXPECT_EQ(absl::UnparseFlag(value), "nan"); - value = std::numeric_limits<double>::infinity(); - EXPECT_EQ(absl::UnparseFlag(value), "inf"); -} - -// -------------------------------------------------------------------- - -TEST(MarshallingTest, TestStringUnparsing) { - EXPECT_EQ(absl::UnparseFlag(""), ""); - EXPECT_EQ(absl::UnparseFlag(" "), " "); - EXPECT_EQ(absl::UnparseFlag("qwerty"), "qwerty"); - EXPECT_EQ(absl::UnparseFlag("ASDFGH"), "ASDFGH"); - EXPECT_EQ(absl::UnparseFlag("\n\t "), "\n\t "); -} - -// -------------------------------------------------------------------- - -template <typename T> -void TestRoundtrip(T v) { - T new_v; - std::string err; - EXPECT_TRUE(absl::ParseFlag(absl::UnparseFlag(v), &new_v, &err)); - EXPECT_EQ(new_v, v); -} - -TEST(MarshallingTest, TestFloatRoundTrip) { - TestRoundtrip(0.1f); - TestRoundtrip(0.12f); - TestRoundtrip(0.123f); - TestRoundtrip(0.1234f); - TestRoundtrip(0.12345f); - TestRoundtrip(0.123456f); - TestRoundtrip(0.1234567f); - TestRoundtrip(0.12345678f); - - TestRoundtrip(0.1e20f); - TestRoundtrip(0.12e20f); - TestRoundtrip(0.123e20f); - TestRoundtrip(0.1234e20f); - TestRoundtrip(0.12345e20f); - TestRoundtrip(0.123456e20f); - TestRoundtrip(0.1234567e20f); - TestRoundtrip(0.12345678e20f); - - TestRoundtrip(0.1e-20f); - TestRoundtrip(0.12e-20f); - TestRoundtrip(0.123e-20f); - TestRoundtrip(0.1234e-20f); - TestRoundtrip(0.12345e-20f); - TestRoundtrip(0.123456e-20f); - TestRoundtrip(0.1234567e-20f); - TestRoundtrip(0.12345678e-20f); -} - -TEST(MarshallingTest, TestDoubleRoundTrip) { - TestRoundtrip(0.1); - TestRoundtrip(0.12); - TestRoundtrip(0.123); - TestRoundtrip(0.1234); - TestRoundtrip(0.12345); - TestRoundtrip(0.123456); - TestRoundtrip(0.1234567); - TestRoundtrip(0.12345678); - TestRoundtrip(0.123456789); - TestRoundtrip(0.1234567891); - TestRoundtrip(0.12345678912); - TestRoundtrip(0.123456789123); - TestRoundtrip(0.1234567891234); - TestRoundtrip(0.12345678912345); - TestRoundtrip(0.123456789123456); - TestRoundtrip(0.1234567891234567); - TestRoundtrip(0.12345678912345678); - - TestRoundtrip(0.1e50); - TestRoundtrip(0.12e50); - TestRoundtrip(0.123e50); - TestRoundtrip(0.1234e50); - TestRoundtrip(0.12345e50); - TestRoundtrip(0.123456e50); - TestRoundtrip(0.1234567e50); - TestRoundtrip(0.12345678e50); - TestRoundtrip(0.123456789e50); - TestRoundtrip(0.1234567891e50); - TestRoundtrip(0.12345678912e50); - TestRoundtrip(0.123456789123e50); - TestRoundtrip(0.1234567891234e50); - TestRoundtrip(0.12345678912345e50); - TestRoundtrip(0.123456789123456e50); - TestRoundtrip(0.1234567891234567e50); - TestRoundtrip(0.12345678912345678e50); - - TestRoundtrip(0.1e-50); - TestRoundtrip(0.12e-50); - TestRoundtrip(0.123e-50); - TestRoundtrip(0.1234e-50); - TestRoundtrip(0.12345e-50); - TestRoundtrip(0.123456e-50); - TestRoundtrip(0.1234567e-50); - TestRoundtrip(0.12345678e-50); - TestRoundtrip(0.123456789e-50); - TestRoundtrip(0.1234567891e-50); - TestRoundtrip(0.12345678912e-50); - TestRoundtrip(0.123456789123e-50); - TestRoundtrip(0.1234567891234e-50); - TestRoundtrip(0.12345678912345e-50); - TestRoundtrip(0.123456789123456e-50); - TestRoundtrip(0.1234567891234567e-50); - TestRoundtrip(0.12345678912345678e-50); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/flags/parse.cc b/third_party/abseil_cpp/absl/flags/parse.cc deleted file mode 100644 index dd1a6796cabd..000000000000 --- a/third_party/abseil_cpp/absl/flags/parse.cc +++ /dev/null @@ -1,823 +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/parse.h" - -#include <stdlib.h> - -#include <algorithm> -#include <fstream> -#include <iostream> -#include <iterator> -#include <string> -#include <tuple> -#include <utility> -#include <vector> - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/const_init.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/config.h" -#include "absl/flags/flag.h" -#include "absl/flags/internal/commandlineflag.h" -#include "absl/flags/internal/flag.h" -#include "absl/flags/internal/parse.h" -#include "absl/flags/internal/private_handle_accessor.h" -#include "absl/flags/internal/program_name.h" -#include "absl/flags/internal/usage.h" -#include "absl/flags/reflection.h" -#include "absl/flags/usage.h" -#include "absl/flags/usage_config.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" -#include "absl/synchronization/mutex.h" - -// -------------------------------------------------------------------- - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { -namespace { - -ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit); - -ABSL_CONST_INIT bool flagfile_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; -ABSL_CONST_INIT bool fromenv_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; -ABSL_CONST_INIT bool tryfromenv_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; - -ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit); -ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags - ABSL_GUARDED_BY(specified_flags_guard) = nullptr; - -struct SpecifiedFlagsCompare { - bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const { - return a->Name() < b->Name(); - } - bool operator()(const CommandLineFlag* a, absl::string_view b) const { - return a->Name() < b; - } - bool operator()(absl::string_view a, const CommandLineFlag* b) const { - return a < b->Name(); - } -}; - -} // namespace -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -ABSL_FLAG(std::vector<std::string>, flagfile, {}, - "comma-separated list of files to load flags from") - .OnUpdate([]() { - if (absl::GetFlag(FLAGS_flagfile).empty()) return; - - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); - - // Setting this flag twice before it is handled most likely an internal - // error and should be reviewed by developers. - if (absl::flags_internal::flagfile_needs_processing) { - ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled"); - } - - absl::flags_internal::flagfile_needs_processing = true; - }); -ABSL_FLAG(std::vector<std::string>, fromenv, {}, - "comma-separated list of flags to set from the environment" - " [use 'export FLAGS_flag1=value']") - .OnUpdate([]() { - if (absl::GetFlag(FLAGS_fromenv).empty()) return; - - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); - - // Setting this flag twice before it is handled most likely an internal - // error and should be reviewed by developers. - if (absl::flags_internal::fromenv_needs_processing) { - ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled."); - } - - absl::flags_internal::fromenv_needs_processing = true; - }); -ABSL_FLAG(std::vector<std::string>, tryfromenv, {}, - "comma-separated list of flags to try to set from the environment if " - "present") - .OnUpdate([]() { - if (absl::GetFlag(FLAGS_tryfromenv).empty()) return; - - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); - - // Setting this flag twice before it is handled most likely an internal - // error and should be reviewed by developers. - if (absl::flags_internal::tryfromenv_needs_processing) { - ABSL_INTERNAL_LOG(WARNING, - "tryfromenv set twice before it is handled."); - } - - absl::flags_internal::tryfromenv_needs_processing = true; - }); - -ABSL_FLAG(std::vector<std::string>, undefok, {}, - "comma-separated list of flag names that it is okay to specify " - "on the command line even if the program does not define a flag " - "with that name"); - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -namespace { - -class ArgsList { - public: - ArgsList() : next_arg_(0) {} - ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {} - explicit ArgsList(const std::vector<std::string>& args) - : args_(args), next_arg_(0) {} - - // Returns success status: true if parsing successful, false otherwise. - bool ReadFromFlagfile(const std::string& flag_file_name); - - int Size() const { return args_.size() - next_arg_; } - int FrontIndex() const { return next_arg_; } - absl::string_view Front() const { return args_[next_arg_]; } - void PopFront() { next_arg_++; } - - private: - std::vector<std::string> args_; - int next_arg_; -}; - -bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) { - std::ifstream flag_file(flag_file_name); - - if (!flag_file) { - flags_internal::ReportUsageError( - absl::StrCat("Can't open flagfile ", flag_file_name), true); - - return false; - } - - // This argument represents fake argv[0], which should be present in all arg - // lists. - args_.push_back(""); - - std::string line; - bool success = true; - - while (std::getline(flag_file, line)) { - absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line); - - if (stripped.empty() || stripped[0] == '#') { - // Comment or empty line; just ignore. - continue; - } - - if (stripped[0] == '-') { - if (stripped == "--") { - flags_internal::ReportUsageError( - "Flagfile can't contain position arguments or --", true); - - success = false; - break; - } - - args_.push_back(std::string(stripped)); - continue; - } - - flags_internal::ReportUsageError( - absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ", - line), - true); - - success = false; - } - - return success; -} - -// -------------------------------------------------------------------- - -// Reads the environment variable with name `name` and stores results in -// `value`. If variable is not present in environment returns false, otherwise -// returns true. -bool GetEnvVar(const char* var_name, std::string& var_value) { -#ifdef _WIN32 - char buf[1024]; - auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf)); - if (get_res >= sizeof(buf)) { - return false; - } - - if (get_res == 0) { - return false; - } - - var_value = std::string(buf, get_res); -#else - const char* val = ::getenv(var_name); - if (val == nullptr) { - return false; - } - - var_value = val; -#endif - - return true; -} - -// -------------------------------------------------------------------- - -// Returns: -// Flag name or empty if arg= -- -// Flag value after = in --flag=value (empty if --foo) -// "Is empty value" status. True if arg= --foo=, false otherwise. This is -// required to separate --foo from --foo=. -// For example: -// arg return values -// "--foo=bar" -> {"foo", "bar", false}. -// "--foo" -> {"foo", "", false}. -// "--foo=" -> {"foo", "", true}. -std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue( - absl::string_view arg) { - // Allow -foo and --foo - absl::ConsumePrefix(&arg, "-"); - - if (arg.empty()) { - return std::make_tuple("", "", false); - } - - auto equal_sign_pos = arg.find("="); - - absl::string_view flag_name = arg.substr(0, equal_sign_pos); - - absl::string_view value; - bool is_empty_value = false; - - if (equal_sign_pos != absl::string_view::npos) { - value = arg.substr(equal_sign_pos + 1); - is_empty_value = value.empty(); - } - - return std::make_tuple(flag_name, value, is_empty_value); -} - -// -------------------------------------------------------------------- - -// Returns: -// found flag or nullptr -// is negative in case of --nofoo -std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) { - CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name); - bool is_negative = false; - - if (!flag && absl::ConsumePrefix(&flag_name, "no")) { - flag = absl::FindCommandLineFlag(flag_name); - is_negative = true; - } - - return std::make_tuple(flag, is_negative); -} - -// -------------------------------------------------------------------- - -// Verify that default values of typed flags must be convertible to string and -// back. -void CheckDefaultValuesParsingRoundtrip() { -#ifndef NDEBUG - flags_internal::ForEachFlag([&](CommandLineFlag& flag) { - if (flag.IsRetired()) return; - -#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \ - if (flag.IsOfType<T>()) return; - - ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE) -#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE - - flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip( - flag); - }); -#endif -} - -// -------------------------------------------------------------------- - -// Returns success status, which is true if we successfully read all flag files, -// in which case new ArgLists are appended to the input_args in a reverse order -// of file names in the input flagfiles list. This order ensures that flags from -// the first flagfile in the input list are processed before the second flagfile -// etc. -bool ReadFlagfiles(const std::vector<std::string>& flagfiles, - std::vector<ArgsList>& input_args) { - bool success = true; - for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) { - ArgsList al; - - if (al.ReadFromFlagfile(*it)) { - input_args.push_back(al); - } else { - success = false; - } - } - - return success; -} - -// Returns success status, which is true if were able to locate all environment -// variables correctly or if fail_on_absent_in_env is false. The environment -// variable names are expected to be of the form `FLAGS_<flag_name>`, where -// `flag_name` is a string from the input flag_names list. If successful we -// append a single ArgList at the end of the input_args. -bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names, - std::vector<ArgsList>& input_args, - bool fail_on_absent_in_env) { - bool success = true; - std::vector<std::string> args; - - // This argument represents fake argv[0], which should be present in all arg - // lists. - args.push_back(""); - - for (const auto& flag_name : flag_names) { - // Avoid infinite recursion. - if (flag_name == "fromenv" || flag_name == "tryfromenv") { - flags_internal::ReportUsageError( - absl::StrCat("Infinite recursion on flag ", flag_name), true); - - success = false; - continue; - } - - const std::string envname = absl::StrCat("FLAGS_", flag_name); - std::string envval; - if (!GetEnvVar(envname.c_str(), envval)) { - if (fail_on_absent_in_env) { - flags_internal::ReportUsageError( - absl::StrCat(envname, " not found in environment"), true); - - success = false; - } - - continue; - } - - args.push_back(absl::StrCat("--", flag_name, "=", envval)); - } - - if (success) { - input_args.emplace_back(args); - } - - return success; -} - -// -------------------------------------------------------------------- - -// Returns success status, which is true if were able to handle all generator -// flags (flagfile, fromenv, tryfromemv) successfully. -bool HandleGeneratorFlags(std::vector<ArgsList>& input_args, - std::vector<std::string>& flagfile_value) { - bool success = true; - - absl::MutexLock l(&flags_internal::processing_checks_guard); - - // flagfile could have been set either on a command line or - // programmatically before invoking ParseCommandLine. Note that we do not - // actually process arguments specified in the flagfile, but instead - // create a secondary arguments list to be processed along with the rest - // of the comamnd line arguments. Since we always the process most recently - // created list of arguments first, this will result in flagfile argument - // being processed before any other argument in the command line. If - // FLAGS_flagfile contains more than one file name we create multiple new - // levels of arguments in a reverse order of file names. Thus we always - // process arguments from first file before arguments containing in a - // second file, etc. If flagfile contains another - // --flagfile inside of it, it will produce new level of arguments and - // processed before the rest of the flagfile. We are also collecting all - // flagfiles set on original command line. Unlike the rest of the flags, - // this flag can be set multiple times and is expected to be handled - // multiple times. We are collecting them all into a single list and set - // the value of FLAGS_flagfile to that value at the end of the parsing. - if (flags_internal::flagfile_needs_processing) { - auto flagfiles = absl::GetFlag(FLAGS_flagfile); - - if (input_args.size() == 1) { - flagfile_value.insert(flagfile_value.end(), flagfiles.begin(), - flagfiles.end()); - } - - success &= ReadFlagfiles(flagfiles, input_args); - - flags_internal::flagfile_needs_processing = false; - } - - // Similar to flagfile fromenv/tryfromemv can be set both - // programmatically and at runtime on a command line. Unlike flagfile these - // can't be recursive. - if (flags_internal::fromenv_needs_processing) { - auto flags_list = absl::GetFlag(FLAGS_fromenv); - - success &= ReadFlagsFromEnv(flags_list, input_args, true); - - flags_internal::fromenv_needs_processing = false; - } - - if (flags_internal::tryfromenv_needs_processing) { - auto flags_list = absl::GetFlag(FLAGS_tryfromenv); - - success &= ReadFlagsFromEnv(flags_list, input_args, false); - - flags_internal::tryfromenv_needs_processing = false; - } - - return success; -} - -// -------------------------------------------------------------------- - -void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) { - // Setting flagfile to the value which collates all the values set on a - // command line and programmatically. So if command line looked like - // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is - // going to be {"f1", "f2"} - if (!flagfile_value.empty()) { - absl::SetFlag(&FLAGS_flagfile, flagfile_value); - absl::MutexLock l(&flags_internal::processing_checks_guard); - flags_internal::flagfile_needs_processing = false; - } - - // fromenv/tryfromenv are set to <undefined> value. - if (!absl::GetFlag(FLAGS_fromenv).empty()) { - absl::SetFlag(&FLAGS_fromenv, {}); - } - if (!absl::GetFlag(FLAGS_tryfromenv).empty()) { - absl::SetFlag(&FLAGS_tryfromenv, {}); - } - - absl::MutexLock l(&flags_internal::processing_checks_guard); - flags_internal::fromenv_needs_processing = false; - flags_internal::tryfromenv_needs_processing = false; -} - -// -------------------------------------------------------------------- - -// Returns: -// success status -// deduced value -// We are also mutating curr_list in case if we need to get a hold of next -// argument in the input. -std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag, - absl::string_view value, - bool is_negative, - bool is_empty_value, - ArgsList* curr_list) { - // Value is either an argument suffix after `=` in "--foo=<value>" - // or separate argument in case of "--foo" "<value>". - - // boolean flags have these forms: - // --foo - // --nofoo - // --foo=true - // --foo=false - // --nofoo=<value> is not supported - // --foo <value> is not supported - - // non boolean flags have these forms: - // --foo=<value> - // --foo <value> - // --nofoo is not supported - - if (flag.IsOfType<bool>()) { - if (value.empty()) { - if (is_empty_value) { - // "--bool_flag=" case - flags_internal::ReportUsageError( - absl::StrCat( - "Missing the value after assignment for the boolean flag '", - flag.Name(), "'"), - true); - return std::make_tuple(false, ""); - } - - // "--bool_flag" case - value = is_negative ? "0" : "1"; - } else if (is_negative) { - // "--nobool_flag=Y" case - flags_internal::ReportUsageError( - absl::StrCat("Negative form with assignment is not valid for the " - "boolean flag '", - flag.Name(), "'"), - true); - return std::make_tuple(false, ""); - } - } else if (is_negative) { - // "--noint_flag=1" case - flags_internal::ReportUsageError( - absl::StrCat("Negative form is not valid for the flag '", flag.Name(), - "'"), - true); - return std::make_tuple(false, ""); - } else if (value.empty() && (!is_empty_value)) { - if (curr_list->Size() == 1) { - // "--int_flag" case - flags_internal::ReportUsageError( - absl::StrCat("Missing the value for the flag '", flag.Name(), "'"), - true); - return std::make_tuple(false, ""); - } - - // "--int_flag" "10" case - curr_list->PopFront(); - value = curr_list->Front(); - - // Heuristic to detect the case where someone treats a string arg - // like a bool or just forgets to pass a value: - // --my_string_var --foo=bar - // We look for a flag of string type, whose value begins with a - // dash and corresponds to known flag or standalone --. - if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) { - auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1))); - - if (maybe_flag_name.empty() || - std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) { - // "--string_flag" "--known_flag" case - ABSL_INTERNAL_LOG( - WARNING, - absl::StrCat("Did you really mean to set flag '", flag.Name(), - "' to the value '", value, "'?")); - } - } - } - - return std::make_tuple(true, value); -} - -// -------------------------------------------------------------------- - -bool CanIgnoreUndefinedFlag(absl::string_view flag_name) { - auto undefok = absl::GetFlag(FLAGS_undefok); - if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) { - return true; - } - - if (absl::ConsumePrefix(&flag_name, "no") && - std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) { - return true; - } - - return false; -} - -} // namespace - -// -------------------------------------------------------------------- - -bool WasPresentOnCommandLine(absl::string_view flag_name) { - absl::MutexLock l(&specified_flags_guard); - ABSL_INTERNAL_CHECK(specified_flags != nullptr, - "ParseCommandLine is not invoked yet"); - - return std::binary_search(specified_flags->begin(), specified_flags->end(), - flag_name, SpecifiedFlagsCompare{}); -} - -// -------------------------------------------------------------------- - -std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], - ArgvListAction arg_list_act, - UsageFlagsAction usage_flag_act, - OnUndefinedFlag on_undef_flag) { - ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]"); - - // Once parsing has started we will not have more flag registrations. - // If we did, they would be missing during parsing, which is a problem on - // itself. - flags_internal::FinalizeRegistry(); - - // This routine does not return anything since we abort on failure. - CheckDefaultValuesParsingRoundtrip(); - - std::vector<std::string> flagfile_value; - - std::vector<ArgsList> input_args; - input_args.push_back(ArgsList(argc, argv)); - - std::vector<char*> output_args; - std::vector<char*> positional_args; - output_args.reserve(argc); - - // This is the list of undefined flags. The element of the list is the pair - // consisting of boolean indicating if flag came from command line (vs from - // some flag file we've read) and flag name. - // TODO(rogeeff): Eliminate the first element in the pair after cleanup. - std::vector<std::pair<bool, std::string>> undefined_flag_names; - - // Set program invocation name if it is not set before. - if (ProgramInvocationName() == "UNKNOWN") { - flags_internal::SetProgramInvocationName(argv[0]); - } - output_args.push_back(argv[0]); - - absl::MutexLock l(&specified_flags_guard); - if (specified_flags == nullptr) { - specified_flags = new std::vector<const CommandLineFlag*>; - } else { - specified_flags->clear(); - } - - // Iterate through the list of the input arguments. First level are arguments - // originated from argc/argv. Following levels are arguments originated from - // recursive parsing of flagfile(s). - bool success = true; - while (!input_args.empty()) { - // 10. First we process the built-in generator flags. - success &= HandleGeneratorFlags(input_args, flagfile_value); - - // 30. Select top-most (most recent) arguments list. If it is empty drop it - // and re-try. - ArgsList& curr_list = input_args.back(); - - curr_list.PopFront(); - - if (curr_list.Size() == 0) { - input_args.pop_back(); - continue; - } - - // 40. Pick up the front remaining argument in the current list. If current - // stack of argument lists contains only one element - we are processing an - // argument from the original argv. - absl::string_view arg(curr_list.Front()); - bool arg_from_argv = input_args.size() == 1; - - // 50. If argument does not start with - or is just "-" - this is - // positional argument. - if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) { - ABSL_INTERNAL_CHECK(arg_from_argv, - "Flagfile cannot contain positional argument"); - - positional_args.push_back(argv[curr_list.FrontIndex()]); - continue; - } - - if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) { - output_args.push_back(argv[curr_list.FrontIndex()]); - } - - // 60. Split the current argument on '=' to figure out the argument - // name and value. If flag name is empty it means we've got "--". value - // can be empty either if there were no '=' in argument string at all or - // an argument looked like "--foo=". In a latter case is_empty_value is - // true. - absl::string_view flag_name; - absl::string_view value; - bool is_empty_value = false; - - std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg); - - // 70. "--" alone means what it does for GNU: stop flags parsing. We do - // not support positional arguments in flagfiles, so we just drop them. - if (flag_name.empty()) { - ABSL_INTERNAL_CHECK(arg_from_argv, - "Flagfile cannot contain positional argument"); - - curr_list.PopFront(); - break; - } - - // 80. Locate the flag based on flag name. Handle both --foo and --nofoo - CommandLineFlag* flag = nullptr; - bool is_negative = false; - std::tie(flag, is_negative) = LocateFlag(flag_name); - - if (flag == nullptr) { - // Usage flags are not modeled as Abseil flags. Locate them separately. - if (flags_internal::DeduceUsageFlags(flag_name, value)) { - continue; - } - - if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) { - undefined_flag_names.emplace_back(arg_from_argv, - std::string(flag_name)); - } - continue; - } - - // 90. Deduce flag's value (from this or next argument) - auto curr_index = curr_list.FrontIndex(); - bool value_success = true; - std::tie(value_success, value) = - DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list); - success &= value_success; - - // If above call consumed an argument, it was a standalone value - if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) && - (curr_index != curr_list.FrontIndex())) { - output_args.push_back(argv[curr_list.FrontIndex()]); - } - - // 100. Set the located flag to a new new value, unless it is retired. - // Setting retired flag fails, but we ignoring it here while also reporting - // access to retired flag. - std::string error; - if (!flags_internal::PrivateHandleAccessor::ParseFrom( - *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) { - if (flag->IsRetired()) continue; - - flags_internal::ReportUsageError(error, true); - success = false; - } else { - specified_flags->push_back(flag); - } - } - - for (const auto& flag_name : undefined_flag_names) { - if (CanIgnoreUndefinedFlag(flag_name.second)) continue; - - flags_internal::ReportUsageError( - absl::StrCat("Unknown command line flag '", flag_name.second, "'"), - true); - - success = false; - } - -#if ABSL_FLAGS_STRIP_NAMES - if (!success) { - flags_internal::ReportUsageError( - "NOTE: command line flags are disabled in this build", true); - } -#endif - - if (!success) { - flags_internal::HandleUsageFlags(std::cout, - ProgramUsageMessage()); - std::exit(1); - } - - if (usage_flag_act == UsageFlagsAction::kHandleUsage) { - int exit_code = flags_internal::HandleUsageFlags( - std::cout, ProgramUsageMessage()); - - if (exit_code != -1) { - std::exit(exit_code); - } - } - - ResetGeneratorFlags(flagfile_value); - - // Reinstate positional args which were intermixed with flags in the arguments - // list. - for (auto arg : positional_args) { - output_args.push_back(arg); - } - - // All the remaining arguments are positional. - if (!input_args.empty()) { - for (int arg_index = input_args.back().FrontIndex(); arg_index < argc; - ++arg_index) { - output_args.push_back(argv[arg_index]); - } - } - - // Trim and sort the vector. - specified_flags->shrink_to_fit(); - std::sort(specified_flags->begin(), specified_flags->end(), - SpecifiedFlagsCompare{}); - return output_args; -} - -} // namespace flags_internal - -// -------------------------------------------------------------------- - -std::vector<char*> ParseCommandLine(int argc, char* argv[]) { - return flags_internal::ParseCommandLineImpl( - argc, argv, flags_internal::ArgvListAction::kRemoveParsedArgs, - flags_internal::UsageFlagsAction::kHandleUsage, - flags_internal::OnUndefinedFlag::kAbortIfUndefined); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/parse.h b/third_party/abseil_cpp/absl/flags/parse.h deleted file mode 100644 index 929de2cb40de..000000000000 --- a/third_party/abseil_cpp/absl/flags/parse.h +++ /dev/null @@ -1,60 +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. -// -// ----------------------------------------------------------------------------- -// File: parse.h -// ----------------------------------------------------------------------------- -// -// This file defines the main parsing function for Abseil flags: -// `absl::ParseCommandLine()`. - -#ifndef ABSL_FLAGS_PARSE_H_ -#define ABSL_FLAGS_PARSE_H_ - -#include <vector> - -#include "absl/base/config.h" -#include "absl/flags/internal/parse.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ParseCommandLine() -// -// Parses the set of command-line arguments passed in the `argc` (argument -// count) and `argv[]` (argument vector) parameters from `main()`, assigning -// values to any defined Abseil flags. (Any arguments passed after the -// flag-terminating delimiter (`--`) are treated as positional arguments and -// ignored.) -// -// Any command-line flags (and arguments to those flags) are parsed into Abseil -// Flag values, if those flags are defined. Any undefined flags will either -// return an error, or be ignored if that flag is designated using `undefok` to -// indicate "undefined is OK." -// -// Any command-line positional arguments not part of any command-line flag (or -// arguments to a flag) are returned in a vector, with the program invocation -// name at position 0 of that vector. (Note that this includes positional -// arguments after the flag-terminating delimiter `--`.) -// -// After all flags and flag arguments are parsed, this function looks for any -// built-in usage flags (e.g. `--help`), and if any were specified, it reports -// help messages and then exits the program. -std::vector<char*> ParseCommandLine(int argc, char* argv[]); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_PARSE_H_ diff --git a/third_party/abseil_cpp/absl/flags/parse_test.cc b/third_party/abseil_cpp/absl/flags/parse_test.cc deleted file mode 100644 index 41bc0bc6b3a4..000000000000 --- a/third_party/abseil_cpp/absl/flags/parse_test.cc +++ /dev/null @@ -1,929 +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/parse.h" - -#include <stdlib.h> - -#include <fstream> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/scoped_set_env.h" -#include "absl/flags/declare.h" -#include "absl/flags/flag.h" -#include "absl/flags/internal/parse.h" -#include "absl/flags/internal/usage.h" -#include "absl/flags/reflection.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/strings/substitute.h" -#include "absl/types/span.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -namespace { - -using absl::base_internal::ScopedSetEnv; - -struct UDT { - UDT() = default; - UDT(const UDT&) = default; - UDT(int v) : value(v) {} // NOLINT - - int value; -}; - -bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) { - if (in == "A") { - udt->value = 1; - return true; - } - if (in == "AAA") { - udt->value = 10; - return true; - } - - *err = "Use values A, AAA instead"; - return false; -} -std::string AbslUnparseFlag(const UDT& udt) { - return udt.value == 1 ? "A" : "AAA"; -} - -std::string GetTestTmpDirEnvVar(const char* const env_var_name) { -#ifdef _WIN32 - char buf[MAX_PATH]; - auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf)); - if (get_res >= sizeof(buf) || get_res == 0) { - return ""; - } - - return std::string(buf, get_res); -#else - const char* val = ::getenv(env_var_name); - if (val == nullptr) { - return ""; - } - - return val; -#endif -} - -const std::string& GetTestTempDir() { - static std::string* temp_dir_name = []() -> std::string* { - std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR")); - - if (res->empty()) { - *res = GetTestTmpDirEnvVar("TMPDIR"); - } - - if (res->empty()) { -#ifdef _WIN32 - char temp_path_buffer[MAX_PATH]; - - auto len = GetTempPathA(MAX_PATH, temp_path_buffer); - if (len < MAX_PATH && len != 0) { - std::string temp_dir_name = temp_path_buffer; - if (!absl::EndsWith(temp_dir_name, "\\")) { - temp_dir_name.push_back('\\'); - } - absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId()); - if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) { - *res = temp_dir_name; - } - } -#else - char temp_dir_template[] = "/tmp/parse_test.XXXXXX"; - if (auto* unique_name = ::mkdtemp(temp_dir_template)) { - *res = unique_name; - } -#endif - } - - if (res->empty()) { - ABSL_INTERNAL_LOG(FATAL, - "Failed to make temporary directory for data files"); - } - -#ifdef _WIN32 - *res += "\\"; -#else - *res += "/"; -#endif - - return res; - }(); - - return *temp_dir_name; -} - -struct FlagfileData { - const absl::string_view file_name; - const absl::Span<const char* const> file_lines; -}; - -// clang-format off -constexpr const char* const ff1_data[] = { - "# comment ", - " # comment ", - "", - " ", - "--int_flag=-1", - " --string_flag=q2w2 ", - " ## ", - " --double_flag=0.1", - "--bool_flag=Y " -}; - -constexpr const char* const ff2_data[] = { - "# Setting legacy flag", - "--legacy_int=1111", - "--legacy_bool", - "--nobool_flag", - "--legacy_str=aqsw", - "--int_flag=100", - " ## =============" -}; -// clang-format on - -// Builds flagfile flag in the flagfile_flag buffer and returns it. This -// function also creates a temporary flagfile based on FlagfileData input. -// We create a flagfile in a temporary directory with the name specified in -// FlagfileData and populate it with lines specifed in FlagfileData. If $0 is -// referenced in any of the lines in FlagfileData they are replaced with -// temporary directory location. This way we can test inclusion of one flagfile -// from another flagfile. -const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd, - std::string& flagfile_flag) { - flagfile_flag = "--flagfile="; - absl::string_view separator; - for (const auto& flagfile_data : ffd) { - std::string flagfile_name = - absl::StrCat(GetTestTempDir(), flagfile_data.file_name); - - std::ofstream flagfile_out(flagfile_name); - for (auto line : flagfile_data.file_lines) { - flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n"; - } - - absl::StrAppend(&flagfile_flag, separator, flagfile_name); - separator = ","; - } - - return flagfile_flag.c_str(); -} - -} // namespace - -ABSL_FLAG(int, int_flag, 1, ""); -ABSL_FLAG(double, double_flag, 1.1, ""); -ABSL_FLAG(std::string, string_flag, "a", ""); -ABSL_FLAG(bool, bool_flag, false, ""); -ABSL_FLAG(UDT, udt_flag, -1, ""); -ABSL_RETIRED_FLAG(int, legacy_int, 1, ""); -ABSL_RETIRED_FLAG(bool, legacy_bool, false, ""); -ABSL_RETIRED_FLAG(std::string, legacy_str, "l", ""); - -namespace { - -namespace flags = absl::flags_internal; -using testing::ElementsAreArray; - -class ParseTest : public testing::Test { - public: - ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); } - - private: - absl::FlagSaver flag_saver_; -}; - -// -------------------------------------------------------------------- - -template <int N> -std::vector<char*> InvokeParse(const char* (&in_argv)[N]) { - return absl::ParseCommandLine(N, const_cast<char**>(in_argv)); -} - -// -------------------------------------------------------------------- - -template <int N> -void TestParse(const char* (&in_argv)[N], int int_flag_value, - double double_flag_val, absl::string_view string_flag_val, - bool bool_flag_val, int exp_position_args = 0) { - auto out_args = InvokeParse(in_argv); - - EXPECT_EQ(out_args.size(), 1 + exp_position_args); - EXPECT_STREQ(out_args[0], "testbin"); - - EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value); - EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001); - EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val); - EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestEmptyArgv) { - const char* in_argv[] = {"testbin"}; - - auto out_args = InvokeParse(in_argv); - - EXPECT_EQ(out_args.size(), 1); - EXPECT_STREQ(out_args[0], "testbin"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidIntArg) { - const char* in_args1[] = { - "testbin", - "--int_flag=10", - }; - TestParse(in_args1, 10, 1.1, "a", false); - - const char* in_args2[] = { - "testbin", - "-int_flag=020", - }; - TestParse(in_args2, 20, 1.1, "a", false); - - const char* in_args3[] = { - "testbin", - "--int_flag", - "-30", - }; - TestParse(in_args3, -30, 1.1, "a", false); - - const char* in_args4[] = { - "testbin", - "-int_flag", - "0x21", - }; - TestParse(in_args4, 33, 1.1, "a", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidDoubleArg) { - const char* in_args1[] = { - "testbin", - "--double_flag=2.3", - }; - TestParse(in_args1, 1, 2.3, "a", false); - - const char* in_args2[] = { - "testbin", - "--double_flag=0x1.2", - }; - TestParse(in_args2, 1, 1.125, "a", false); - - const char* in_args3[] = { - "testbin", - "--double_flag", - "99.7", - }; - TestParse(in_args3, 1, 99.7, "a", false); - - const char* in_args4[] = { - "testbin", - "--double_flag", - "0x20.1", - }; - TestParse(in_args4, 1, 32.0625, "a", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidStringArg) { - const char* in_args1[] = { - "testbin", - "--string_flag=aqswde", - }; - TestParse(in_args1, 1, 1.1, "aqswde", false); - - const char* in_args2[] = { - "testbin", - "-string_flag=a=b=c", - }; - TestParse(in_args2, 1, 1.1, "a=b=c", false); - - const char* in_args3[] = { - "testbin", - "--string_flag", - "zaxscd", - }; - TestParse(in_args3, 1, 1.1, "zaxscd", false); - - const char* in_args4[] = { - "testbin", - "-string_flag", - "--int_flag", - }; - TestParse(in_args4, 1, 1.1, "--int_flag", false); - - const char* in_args5[] = { - "testbin", - "--string_flag", - "--no_a_flag=11", - }; - TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidBoolArg) { - const char* in_args1[] = { - "testbin", - "--bool_flag", - }; - TestParse(in_args1, 1, 1.1, "a", true); - - const char* in_args2[] = { - "testbin", - "--nobool_flag", - }; - TestParse(in_args2, 1, 1.1, "a", false); - - const char* in_args3[] = { - "testbin", - "--bool_flag=true", - }; - TestParse(in_args3, 1, 1.1, "a", true); - - const char* in_args4[] = { - "testbin", - "-bool_flag=false", - }; - TestParse(in_args4, 1, 1.1, "a", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidUDTArg) { - const char* in_args1[] = { - "testbin", - "--udt_flag=A", - }; - InvokeParse(in_args1); - - EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1); - - const char* in_args2[] = {"testbin", "--udt_flag", "AAA"}; - InvokeParse(in_args2); - - EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidMultipleArg) { - const char* in_args1[] = { - "testbin", "--bool_flag", "--int_flag=2", - "--double_flag=0.1", "--string_flag=asd", - }; - TestParse(in_args1, 2, 0.1, "asd", true); - - const char* in_args2[] = { - "testbin", "--string_flag=", "--nobool_flag", "--int_flag", - "-011", "--double_flag", "-1e-2", - }; - TestParse(in_args2, -11, -0.01, "", false); - - const char* in_args3[] = { - "testbin", "--int_flag", "-0", "--string_flag", "\"\"", - "--bool_flag=true", "--double_flag=1e18", - }; - TestParse(in_args3, 0, 1e18, "\"\"", true); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestPositionalArgs) { - const char* in_args1[] = { - "testbin", - "p1", - "p2", - }; - TestParse(in_args1, 1, 1.1, "a", false, 2); - - auto out_args1 = InvokeParse(in_args1); - - EXPECT_STREQ(out_args1[1], "p1"); - EXPECT_STREQ(out_args1[2], "p2"); - - const char* in_args2[] = { - "testbin", - "--int_flag=2", - "p1", - }; - TestParse(in_args2, 2, 1.1, "a", false, 1); - - auto out_args2 = InvokeParse(in_args2); - - EXPECT_STREQ(out_args2[1], "p1"); - - const char* in_args3[] = {"testbin", "p1", "--int_flag=3", - "p2", "--bool_flag", "true"}; - TestParse(in_args3, 3, 1.1, "a", true, 3); - - auto out_args3 = InvokeParse(in_args3); - - EXPECT_STREQ(out_args3[1], "p1"); - EXPECT_STREQ(out_args3[2], "p2"); - EXPECT_STREQ(out_args3[3], "true"); - - const char* in_args4[] = { - "testbin", - "--", - "p1", - "p2", - }; - TestParse(in_args4, 3, 1.1, "a", true, 2); - - auto out_args4 = InvokeParse(in_args4); - - EXPECT_STREQ(out_args4[1], "p1"); - EXPECT_STREQ(out_args4[2], "p2"); - - const char* in_args5[] = { - "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2", - }; - TestParse(in_args5, 4, 1.1, "a", true, 4); - - auto out_args5 = InvokeParse(in_args5); - - EXPECT_STREQ(out_args5[1], "p1"); - EXPECT_STREQ(out_args5[2], "--bool_flag"); - EXPECT_STREQ(out_args5[3], "false"); - EXPECT_STREQ(out_args5[4], "p2"); -} - -// -------------------------------------------------------------------- - -using ParseDeathTest = ParseTest; - -TEST_F(ParseDeathTest, TestUndefinedArg) { - const char* in_args1[] = { - "testbin", - "--undefined_flag", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "Unknown command line flag 'undefined_flag'"); - - const char* in_args2[] = { - "testbin", - "--noprefixed_flag", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), - "Unknown command line flag 'noprefixed_flag'"); - - const char* in_args3[] = { - "testbin", - "--Int_flag=1", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3), - "Unknown command line flag 'Int_flag'"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) { - const char* in_args1[] = { - "testbin", - "--bool_flag=", - }; - EXPECT_DEATH_IF_SUPPORTED( - InvokeParse(in_args1), - "Missing the value after assignment for the boolean flag 'bool_flag'"); - - const char* in_args2[] = { - "testbin", - "--nobool_flag=true", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), - "Negative form with assignment is not valid for the boolean " - "flag 'bool_flag'"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) { - const char* in_args1[] = { - "testbin", - "--nostring_flag", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "Negative form is not valid for the flag 'string_flag'"); - - const char* in_args2[] = { - "testbin", - "--int_flag", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), - "Missing the value for the flag 'int_flag'"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) { - const char* in_args1[] = { - "testbin", - "--udt_flag=1", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "Illegal value '1' specified for flag 'udt_flag'; Use values A, " - "AAA instead"); - - const char* in_args2[] = { - "testbin", - "--udt_flag", - "AA", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), - "Illegal value 'AA' specified for flag 'udt_flag'; Use values " - "A, AAA instead"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestLegacyFlags) { - const char* in_args1[] = { - "testbin", - "--legacy_int=11", - }; - TestParse(in_args1, 1, 1.1, "a", false); - - const char* in_args2[] = { - "testbin", - "--legacy_bool", - }; - TestParse(in_args2, 1, 1.1, "a", false); - - const char* in_args3[] = { - "testbin", "--legacy_int", "22", "--int_flag=2", - "--legacy_bool", "true", "--legacy_str", "--string_flag=qwe", - }; - TestParse(in_args3, 2, 1.1, "a", false, 1); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestSimpleValidFlagfile) { - std::string flagfile_flag; - - const char* in_args1[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, - flagfile_flag), - }; - TestParse(in_args1, -1, 0.1, "q2w2 ", true); - - const char* in_args2[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}}, - flagfile_flag), - }; - TestParse(in_args2, 100, 0.1, "q2w2 ", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestValidMultiFlagfile) { - std::string flagfile_flag; - - const char* in_args1[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}, - {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, - flagfile_flag), - }; - TestParse(in_args1, -1, 0.1, "q2w2 ", true); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) { - std::string flagfile_flag; - - const char* in_args1[] = { - "testbin", "--int_flag=3", - GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, - flagfile_flag), - "-double_flag=0.2"}; - TestParse(in_args1, -1, 0.2, "q2w2 ", true); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestFlagfileInFlagfile) { - std::string flagfile_flag; - - constexpr const char* const ff3_data[] = { - "--flagfile=$0/parse_test.ff1", - "--flagfile=$0/parse_test.ff2", - }; - - GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}, - {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, - flagfile_flag); - - const char* in_args1[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}}, - flagfile_flag), - }; - TestParse(in_args1, 100, 0.1, "q2w2 ", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestInvalidFlagfiles) { - std::string flagfile_flag; - - constexpr const char* const ff4_data[] = { - "--unknown_flag=10" - }; - - const char* in_args1[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff4", - absl::MakeConstSpan(ff4_data)}}, flagfile_flag), - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "Unknown command line flag 'unknown_flag'"); - - constexpr const char* const ff5_data[] = { - "--int_flag 10", - }; - - const char* in_args2[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff5", - absl::MakeConstSpan(ff5_data)}}, flagfile_flag), - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2), - "Unknown command line flag 'int_flag 10'"); - - constexpr const char* const ff6_data[] = { - "--int_flag=10", "--", "arg1", "arg2", "arg3", - }; - - const char* in_args3[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}}, - flagfile_flag), - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3), - "Flagfile can't contain position arguments or --"); - - const char* in_args4[] = { - "testbin", - "--flagfile=invalid_flag_file", - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4), - "Can't open flagfile invalid_flag_file"); - - constexpr const char* const ff7_data[] = { - "--int_flag=10", - "*bin*", - "--str_flag=aqsw", - }; - - const char* in_args5[] = { - "testbin", - GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}}, - flagfile_flag), - }; - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5), - "Unexpected line in the flagfile .*: \\*bin\\*"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) { - const char* in_args1[] = {"testbin", - "--fromenv=int_flag,bool_flag,string_flag"}; - - ScopedSetEnv set_int_flag("FLAGS_int_flag", "33"); - ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True"); - ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12"); - - TestParse(in_args1, 33, 1.1, "AQ12", true); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) { - const char* in_args1[] = {"testbin", "--fromenv=int_flag"}; - - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "FLAGS_int_flag not found in environment"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) { - const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"}; - - ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag"); - - EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1), - "Infinite recursion on flag tryfromenv"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) { - const char* in_args1[] = { - "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"}; - - ScopedSetEnv set_int_flag("FLAGS_int_flag", "17"); - ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y"); - - TestParse(in_args1, 17, 1.1, "a", true); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) { - const char* in_args1[] = { - "testbin", - "--bool_flag=T", - "--tryfromenv=int_flag,bool_flag", - "--int_flag=-21", - }; - - ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15"); - ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F"); - - TestParse(in_args1, -21, 1.1, "a", false); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestKeepParsedArgs) { - const char* in_args1[] = { - "testbin", "arg1", "--bool_flag", - "--int_flag=211", "arg2", "--double_flag=1.1", - "--string_flag", "asd", "--", - "arg3", "arg4", - }; - - auto out_args1 = InvokeParse(in_args1); - - EXPECT_THAT( - out_args1, - ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"), - absl::string_view("arg2"), absl::string_view("arg3"), - absl::string_view("arg4")})); - - auto out_args2 = flags::ParseCommandLineImpl( - 11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs, - flags::UsageFlagsAction::kHandleUsage, - flags::OnUndefinedFlag::kAbortIfUndefined); - - EXPECT_THAT( - out_args2, - ElementsAreArray({absl::string_view("testbin"), - absl::string_view("--bool_flag"), - absl::string_view("--int_flag=211"), - absl::string_view("--double_flag=1.1"), - absl::string_view("--string_flag"), - absl::string_view("asd"), absl::string_view("--"), - absl::string_view("arg1"), absl::string_view("arg2"), - absl::string_view("arg3"), absl::string_view("arg4")})); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, TestIgnoreUndefinedFlags) { - const char* in_args1[] = { - "testbin", - "arg1", - "--undef_flag=aa", - "--int_flag=21", - }; - - auto out_args1 = flags::ParseCommandLineImpl( - 4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs, - flags::UsageFlagsAction::kHandleUsage, - flags::OnUndefinedFlag::kIgnoreUndefined); - - EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"), - absl::string_view("arg1")})); - - EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21); - - const char* in_args2[] = { - "testbin", - "arg1", - "--undef_flag=aa", - "--string_flag=AA", - }; - - auto out_args2 = flags::ParseCommandLineImpl( - 4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs, - flags::UsageFlagsAction::kHandleUsage, - flags::OnUndefinedFlag::kIgnoreUndefined); - - EXPECT_THAT( - out_args2, - ElementsAreArray( - {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"), - absl::string_view("--string_flag=AA"), absl::string_view("arg1")})); - - EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA"); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) { - const char* in_args1[] = { - "testbin", - "--help", - }; - - EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), ""); - - const char* in_args2[] = { - "testbin", - "--help", - "--int_flag=3", - }; - - auto out_args2 = flags::ParseCommandLineImpl( - 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs, - flags::UsageFlagsAction::kIgnoreUsage, - flags::OnUndefinedFlag::kAbortIfUndefined); - - EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant); - EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) { - const char* in_args1[] = { - "testbin", - "--help=abcd", - }; - - auto out_args1 = flags::ParseCommandLineImpl( - 2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs, - flags::UsageFlagsAction::kIgnoreUsage, - flags::OnUndefinedFlag::kAbortIfUndefined); - - EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch); - EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd"); - - const char* in_args2[] = {"testbin", "--help", "some_positional_arg"}; - - auto out_args2 = flags::ParseCommandLineImpl( - 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs, - flags::UsageFlagsAction::kIgnoreUsage, - flags::OnUndefinedFlag::kAbortIfUndefined); - - EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant); -} - -// -------------------------------------------------------------------- - -TEST_F(ParseTest, WasPresentOnCommandLine) { - const char* in_args1[] = { - "testbin", "arg1", "--bool_flag", - "--int_flag=211", "arg2", "--double_flag=1.1", - "--string_flag", "asd", "--", - "--some_flag", "arg4", - }; - - InvokeParse(in_args1); - - EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag")); - EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag")); - EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag")); - EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag")); - EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag")); - EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag")); -} - -// -------------------------------------------------------------------- - -} // namespace diff --git a/third_party/abseil_cpp/absl/flags/reflection.cc b/third_party/abseil_cpp/absl/flags/reflection.cc deleted file mode 100644 index c976d4679601..000000000000 --- a/third_party/abseil_cpp/absl/flags/reflection.cc +++ /dev/null @@ -1,337 +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 <map> -#include <string> - -#include "absl/base/config.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/commandlineflag.h" -#include "absl/flags/internal/private_handle_accessor.h" -#include "absl/flags/internal/registry.h" -#include "absl/flags/usage_config.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -// -------------------------------------------------------------------- -// FlagRegistry -// A FlagRegistry singleton object holds all flag objects indexed by their -// names so that if you know a flag's name, you can access or set it. If the -// function is named FooLocked(), you must own the registry lock before -// calling the function; otherwise, you should *not* hold the lock, and the -// function will acquire it itself if needed. -// -------------------------------------------------------------------- - -class FlagRegistry { - public: - FlagRegistry() = default; - ~FlagRegistry() = default; - - // Store a flag in this registry. Takes ownership of *flag. - void RegisterFlag(CommandLineFlag& flag); - - void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); } - void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); } - - // Returns the flag object for the specified name, or nullptr if not found. - // Will emit a warning if a 'retired' flag is specified. - CommandLineFlag* FindFlag(absl::string_view name); - - static FlagRegistry& GlobalRegistry(); // returns a singleton registry - - private: - friend class flags_internal::FlagSaverImpl; // reads all the flags in order - // to copy them - friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor); - friend void FinalizeRegistry(); - - // The map from name to flag, for FindFlag(). - using FlagMap = std::map<absl::string_view, CommandLineFlag*>; - using FlagIterator = FlagMap::iterator; - using FlagConstIterator = FlagMap::const_iterator; - FlagMap flags_; - std::vector<CommandLineFlag*> flat_flags_; - std::atomic<bool> finalized_flags_{false}; - - absl::Mutex lock_; - - // Disallow - FlagRegistry(const FlagRegistry&); - FlagRegistry& operator=(const FlagRegistry&); -}; - -namespace { - -class FlagRegistryLock { - public: - explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); } - ~FlagRegistryLock() { fr_.Unlock(); } - - private: - FlagRegistry& fr_; -}; - -} // namespace - -CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) { - if (finalized_flags_.load(std::memory_order_acquire)) { - // We could save some gcus here if we make `Name()` be non-virtual. - // We could move the `const char*` name to the base class. - auto it = std::partition_point( - flat_flags_.begin(), flat_flags_.end(), - [=](CommandLineFlag* f) { return f->Name() < name; }); - if (it != flat_flags_.end() && (*it)->Name() == name) return *it; - } - - FlagRegistryLock frl(*this); - auto it = flags_.find(name); - return it != flags_.end() ? it->second : nullptr; -} - -void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { - 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) { - FlagRegistry::GlobalRegistry().RegisterFlag(flag); - return true; -} - -void FinalizeRegistry() { - auto& registry = FlagRegistry::GlobalRegistry(); - FlagRegistryLock frl(registry); - if (registry.finalized_flags_.load(std::memory_order_relaxed)) { - // Was already finalized. Ignore the second time. - return; - } - registry.flat_flags_.reserve(registry.flags_.size()); - for (const auto& f : registry.flags_) { - registry.flat_flags_.push_back(f.second); - } - registry.flags_.clear(); - registry.finalized_flags_.store(true, std::memory_order_release); -} - -// -------------------------------------------------------------------- - -namespace { - -class RetiredFlagObj final : public CommandLineFlag { - public: - constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id) - : name_(name), type_id_(type_id) {} - - private: - absl::string_view Name() const override { return name_; } - std::string Filename() const override { - OnAccess(); - return "RETIRED"; - } - FlagFastTypeId TypeId() const override { return type_id_; } - std::string Help() const override { - OnAccess(); - return ""; - } - bool IsRetired() const override { return true; } - bool IsSpecifiedOnCommandLine() const override { - OnAccess(); - return false; - } - std::string DefaultValue() const override { - OnAccess(); - return ""; - } - std::string CurrentValue() const override { - OnAccess(); - return ""; - } - - // Any input is valid - bool ValidateInputValue(absl::string_view) const override { - OnAccess(); - return true; - } - - std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override { - return nullptr; - } - - bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode, - flags_internal::ValueSource, std::string&) override { - OnAccess(); - return false; - } - - void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); } - - void Read(void*) const override { OnAccess(); } - - void OnAccess() const { - flags_internal::ReportUsageError( - absl::StrCat("Accessing retired flag '", name_, "'"), false); - } - - // Data members - const char* const name_; - const FlagFastTypeId type_id_; -}; - -} // namespace - -void Retire(const char* name, FlagFastTypeId type_id, char* buf) { - static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, ""); - static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, ""); - auto* flag = ::new (static_cast<void*>(buf)) - flags_internal::RetiredFlagObj(name, type_id); - FlagRegistry::GlobalRegistry().RegisterFlag(*flag); -} - -// -------------------------------------------------------------------- - -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 e6baf5de4b0c..000000000000 --- 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 4c80900956a9..000000000000 --- a/third_party/abseil_cpp/absl/flags/reflection_test.cc +++ /dev/null @@ -1,267 +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 { - -namespace flags = absl::flags_internal; - -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.cc b/third_party/abseil_cpp/absl/flags/usage.cc deleted file mode 100644 index 452f667512e8..000000000000 --- a/third_party/abseil_cpp/absl/flags/usage.cc +++ /dev/null @@ -1,65 +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/usage.h" - -#include <stdlib.h> - -#include <string> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/const_init.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/internal/usage.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { -namespace { -ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit); -ABSL_CONST_INIT std::string* program_usage_message - ABSL_GUARDED_BY(usage_message_guard) = nullptr; -} // namespace -} // namespace flags_internal - -// -------------------------------------------------------------------- -// Sets the "usage" message to be used by help reporting routines. -void SetProgramUsageMessage(absl::string_view new_usage_message) { - absl::MutexLock l(&flags_internal::usage_message_guard); - - if (flags_internal::program_usage_message != nullptr) { - ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice."); - std::exit(1); - } - - flags_internal::program_usage_message = new std::string(new_usage_message); -} - -// -------------------------------------------------------------------- -// Returns the usage message set by SetProgramUsageMessage(). -// Note: We able to return string_view here only because calling -// SetProgramUsageMessage twice is prohibited. -absl::string_view ProgramUsageMessage() { - absl::MutexLock l(&flags_internal::usage_message_guard); - - return flags_internal::program_usage_message != nullptr - ? absl::string_view(*flags_internal::program_usage_message) - : "Warning: SetProgramUsageMessage() never called"; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/usage.h b/third_party/abseil_cpp/absl/flags/usage.h deleted file mode 100644 index ad12ab7ad902..000000000000 --- a/third_party/abseil_cpp/absl/flags/usage.h +++ /dev/null @@ -1,43 +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_FLAGS_USAGE_H_ -#define ABSL_FLAGS_USAGE_H_ - -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -// -------------------------------------------------------------------- -// Usage reporting interfaces - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Sets the "usage" message to be used by help reporting routines. -// For example: -// absl::SetProgramUsageMessage( -// absl::StrCat("This program does nothing. Sample usage:\n", argv[0], -// " <uselessarg1> <uselessarg2>")); -// Do not include commandline flags in the usage: we do that for you! -// Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit. -void SetProgramUsageMessage(absl::string_view new_usage_message); - -// Returns the usage message set by SetProgramUsageMessage(). -absl::string_view ProgramUsageMessage(); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FLAGS_USAGE_H_ diff --git a/third_party/abseil_cpp/absl/flags/usage_config.cc b/third_party/abseil_cpp/absl/flags/usage_config.cc deleted file mode 100644 index ae2f548a570b..000000000000 --- a/third_party/abseil_cpp/absl/flags/usage_config.cc +++ /dev/null @@ -1,164 +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/usage_config.h" - -#include <functional> -#include <iostream> -#include <string> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/const_init.h" -#include "absl/base/thread_annotations.h" -#include "absl/flags/internal/path_util.h" -#include "absl/flags/internal/program_name.h" -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" -#include "absl/synchronization/mutex.h" - -extern "C" { - -// Additional report of fatal usage error message before we std::exit. Error is -// fatal if is_fatal argument to ReportUsageError is true. -ABSL_ATTRIBUTE_WEAK void AbslInternalReportFatalUsageError(absl::string_view) {} - -} // extern "C" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace flags_internal { - -namespace { - -// -------------------------------------------------------------------- -// Returns true if flags defined in the filename should be reported with -// -helpshort flag. - -bool ContainsHelpshortFlags(absl::string_view filename) { - // By default we only want flags in binary's main. We expect the main - // routine to reside in <program>.cc or <program>-main.cc or - // <program>_main.cc, where the <program> is the name of the binary - // (without .exe on Windows). - auto suffix = flags_internal::Basename(filename); - auto program_name = flags_internal::ShortProgramInvocationName(); - absl::string_view program_name_ref = program_name; -#if defined(_WIN32) - absl::ConsumeSuffix(&program_name_ref, ".exe"); -#endif - if (!absl::ConsumePrefix(&suffix, program_name_ref)) - return false; - return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") || - absl::StartsWith(suffix, "_main."); -} - -// -------------------------------------------------------------------- -// Returns true if flags defined in the filename should be reported with -// -helppackage flag. - -bool ContainsHelppackageFlags(absl::string_view filename) { - // TODO(rogeeff): implement properly when registry is available. - return ContainsHelpshortFlags(filename); -} - -// -------------------------------------------------------------------- -// Generates program version information into supplied output. - -std::string VersionString() { - std::string version_str(flags_internal::ShortProgramInvocationName()); - - version_str += "\n"; - -#if !defined(NDEBUG) - version_str += "Debug build (NDEBUG not #defined)\n"; -#endif - - return version_str; -} - -// -------------------------------------------------------------------- -// Normalizes the filename specific to the build system/filesystem used. - -std::string NormalizeFilename(absl::string_view filename) { - // Skip any leading slashes - auto pos = filename.find_first_not_of("\\/"); - if (pos == absl::string_view::npos) return ""; - - filename.remove_prefix(pos); - return std::string(filename); -} - -// -------------------------------------------------------------------- - -ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit); -ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config - ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr; - -} // namespace - -FlagsUsageConfig GetUsageConfig() { - absl::MutexLock l(&custom_usage_config_guard); - - if (custom_usage_config) return *custom_usage_config; - - FlagsUsageConfig default_config; - default_config.contains_helpshort_flags = &ContainsHelpshortFlags; - default_config.contains_help_flags = &ContainsHelppackageFlags; - default_config.contains_helppackage_flags = &ContainsHelppackageFlags; - default_config.version_string = &VersionString; - default_config.normalize_filename = &NormalizeFilename; - - return default_config; -} - -void ReportUsageError(absl::string_view msg, bool is_fatal) { - std::cerr << "ERROR: " << msg << std::endl; - - if (is_fatal) { - AbslInternalReportFatalUsageError(msg); - } -} - -} // namespace flags_internal - -void SetFlagsUsageConfig(FlagsUsageConfig usage_config) { - absl::MutexLock l(&flags_internal::custom_usage_config_guard); - - if (!usage_config.contains_helpshort_flags) - usage_config.contains_helpshort_flags = - flags_internal::ContainsHelpshortFlags; - - if (!usage_config.contains_help_flags) - usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags; - - if (!usage_config.contains_helppackage_flags) - usage_config.contains_helppackage_flags = - flags_internal::ContainsHelppackageFlags; - - if (!usage_config.version_string) - usage_config.version_string = flags_internal::VersionString; - - if (!usage_config.normalize_filename) - usage_config.normalize_filename = flags_internal::NormalizeFilename; - - if (flags_internal::custom_usage_config) - *flags_internal::custom_usage_config = usage_config; - else - flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/flags/usage_config.h b/third_party/abseil_cpp/absl/flags/usage_config.h deleted file mode 100644 index 96eecea23159..000000000000 --- a/third_party/abseil_cpp/absl/flags/usage_config.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. -// -// ----------------------------------------------------------------------------- -// File: usage_config.h -// ----------------------------------------------------------------------------- -// -// This file defines the main usage reporting configuration interfaces and -// documents Abseil's supported built-in usage flags. If these flags are found -// when parsing a command-line, Abseil will exit the program and display -// appropriate help messages. -#ifndef ABSL_FLAGS_USAGE_CONFIG_H_ -#define ABSL_FLAGS_USAGE_CONFIG_H_ - -#include <functional> -#include <string> - -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -// ----------------------------------------------------------------------------- -// Built-in Usage Flags -// ----------------------------------------------------------------------------- -// -// Abseil supports the following built-in usage flags. When passed, these flags -// exit the program and : -// -// * --help -// Shows help on important flags for this binary -// * --helpfull -// Shows help on all flags -// * --helpshort -// Shows help on only the main module for this program -// * --helppackage -// Shows help on all modules in the main package -// * --version -// Shows the version and build info for this binary and exits -// * --only_check_args -// Exits after checking all flags -// * --helpon -// Shows help on the modules named by this flag value -// * --helpmatch -// Shows help on modules whose name contains the specified substring - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace flags_internal { -using FlagKindFilter = std::function<bool (absl::string_view)>; -} // namespace flags_internal - -// FlagsUsageConfig -// -// This structure contains the collection of callbacks for changing the behavior -// of the usage reporting routines in Abseil Flags. -struct FlagsUsageConfig { - // Returns true if flags defined in the given source code file should be - // reported with --helpshort flag. For example, if the file - // "path/to/my/code.cc" defines the flag "--my_flag", and - // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the - // program with --helpshort will include information about --my_flag in the - // program output. - flags_internal::FlagKindFilter contains_helpshort_flags; - - // Returns true if flags defined in the filename should be reported with - // --help flag. For example, if the file - // "path/to/my/code.cc" defines the flag "--my_flag", and - // contains_help_flags("path/to/my/code.cc") returns true, invoking the - // program with --help will include information about --my_flag in the - // program output. - flags_internal::FlagKindFilter contains_help_flags; - - // Returns true if flags defined in the filename should be reported with - // --helppackage flag. For example, if the file - // "path/to/my/code.cc" defines the flag "--my_flag", and - // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the - // program with --helppackage will include information about --my_flag in the - // program output. - flags_internal::FlagKindFilter contains_helppackage_flags; - - // Generates string containing program version. This is the string reported - // when user specifies --version in a command line. - std::function<std::string()> version_string; - - // Normalizes the filename specific to the build system/filesystem used. This - // routine is used when we report the information about the flag definition - // location. For instance, if your build resides at some location you do not - // want to expose in the usage output, you can trim it to show only relevant - // part. - // For example: - // normalize_filename("/my_company/some_long_path/src/project/file.cc") - // might produce - // "project/file.cc". - std::function<std::string(absl::string_view)> normalize_filename; -}; - -// SetFlagsUsageConfig() -// -// Sets the usage reporting configuration callbacks. If any of the callbacks are -// not set in usage_config instance, then the default value of the callback is -// used. -void SetFlagsUsageConfig(FlagsUsageConfig usage_config); - -namespace flags_internal { - -FlagsUsageConfig GetUsageConfig(); - -void ReportUsageError(absl::string_view msg, bool is_fatal); - -} // namespace flags_internal -ABSL_NAMESPACE_END -} // namespace absl - -extern "C" { - -// Additional report of fatal usage error message before we std::exit. Error is -// fatal if is_fatal argument to ReportUsageError is true. -void AbslInternalReportFatalUsageError(absl::string_view); - -} // extern "C" - -#endif // ABSL_FLAGS_USAGE_CONFIG_H_ diff --git a/third_party/abseil_cpp/absl/flags/usage_config_test.cc b/third_party/abseil_cpp/absl/flags/usage_config_test.cc deleted file mode 100644 index e57a8832f645..000000000000 --- a/third_party/abseil_cpp/absl/flags/usage_config_test.cc +++ /dev/null @@ -1,205 +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/usage_config.h" - -#include <string> - -#include "gtest/gtest.h" -#include "absl/flags/internal/path_util.h" -#include "absl/flags/internal/program_name.h" -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" - -namespace { - -class FlagsUsageConfigTest : public testing::Test { - protected: - void SetUp() override { - // Install Default config for the use on this unit test. - // Binary may install a custom config before tests are run. - absl::FlagsUsageConfig default_config; - absl::SetFlagsUsageConfig(default_config); - } -}; - -namespace flags = absl::flags_internal; - -bool TstContainsHelpshortFlags(absl::string_view f) { - return absl::StartsWith(flags::Basename(f), "progname."); -} - -bool TstContainsHelppackageFlags(absl::string_view f) { - return absl::EndsWith(flags::Package(f), "aaa/"); -} - -bool TstContainsHelpFlags(absl::string_view f) { - return absl::EndsWith(flags::Package(f), "zzz/"); -} - -std::string TstVersionString() { return "program 1.0.0"; } - -std::string TstNormalizeFilename(absl::string_view filename) { - return std::string(filename.substr(2)); -} - -void TstReportUsageMessage(absl::string_view msg) {} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) { - EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags); - EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags); - EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags); - EXPECT_TRUE(flags::GetUsageConfig().version_string); - EXPECT_TRUE(flags::GetUsageConfig().normalize_filename); - - absl::FlagsUsageConfig empty_config; - empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags; - empty_config.contains_help_flags = &TstContainsHelpFlags; - empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags; - empty_config.version_string = &TstVersionString; - empty_config.normalize_filename = &TstNormalizeFilename; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags); - EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags); - EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags); - EXPECT_TRUE(flags::GetUsageConfig().version_string); - EXPECT_TRUE(flags::GetUsageConfig().normalize_filename); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) { -#if defined(_WIN32) - flags::SetProgramInvocationName("usage_config_test.exe"); -#else - flags::SetProgramInvocationName("usage_config_test"); -#endif - - auto config = flags::GetUsageConfig(); - EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc")); - EXPECT_TRUE( - config.contains_helpshort_flags("aaaa/usage_config_test-main.cc")); - EXPECT_TRUE(config.contains_helpshort_flags("abc/usage_config_test_main.cc")); - EXPECT_FALSE(config.contains_helpshort_flags("usage_config_main.cc")); - - absl::FlagsUsageConfig empty_config; - empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_TRUE( - flags::GetUsageConfig().contains_helpshort_flags("aaa/progname.cpp")); - EXPECT_FALSE( - flags::GetUsageConfig().contains_helpshort_flags("aaa/progmane.cpp")); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) { - flags::SetProgramInvocationName("usage_config_test"); - - auto config = flags::GetUsageConfig(); - EXPECT_TRUE(config.contains_help_flags("zzz/usage_config_test.cc")); - EXPECT_TRUE( - config.contains_help_flags("bdir/a/zzz/usage_config_test-main.cc")); - EXPECT_TRUE( - config.contains_help_flags("//aqse/zzz/usage_config_test_main.cc")); - EXPECT_FALSE(config.contains_help_flags("zzz/aa/usage_config_main.cc")); - - absl::FlagsUsageConfig empty_config; - empty_config.contains_help_flags = &TstContainsHelpFlags; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags("zzz/main-body.c")); - EXPECT_FALSE( - flags::GetUsageConfig().contains_help_flags("zzz/dir/main-body.c")); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) { - flags::SetProgramInvocationName("usage_config_test"); - - auto config = flags::GetUsageConfig(); - EXPECT_TRUE(config.contains_helppackage_flags("aaa/usage_config_test.cc")); - EXPECT_TRUE( - config.contains_helppackage_flags("bbdir/aaa/usage_config_test-main.cc")); - EXPECT_TRUE(config.contains_helppackage_flags( - "//aqswde/aaa/usage_config_test_main.cc")); - EXPECT_FALSE(config.contains_helppackage_flags("aadir/usage_config_main.cc")); - - absl::FlagsUsageConfig empty_config; - empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_TRUE( - flags::GetUsageConfig().contains_helppackage_flags("aaa/main-body.c")); - EXPECT_FALSE( - flags::GetUsageConfig().contains_helppackage_flags("aadir/main-body.c")); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestVersionString) { - flags::SetProgramInvocationName("usage_config_test"); - -#ifdef NDEBUG - std::string expected_output = "usage_config_test\n"; -#else - std::string expected_output = - "usage_config_test\nDebug build (NDEBUG not #defined)\n"; -#endif - - EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output); - - absl::FlagsUsageConfig empty_config; - empty_config.version_string = &TstVersionString; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_EQ(flags::GetUsageConfig().version_string(), "program 1.0.0"); -} - -// -------------------------------------------------------------------- - -TEST_F(FlagsUsageConfigTest, TestNormalizeFilename) { - // This tests the default implementation. - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/"), ""); - - // This tests that the custom implementation is called. - absl::FlagsUsageConfig empty_config; - empty_config.normalize_filename = &TstNormalizeFilename; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("aaa/a.cc"), "a/a.cc"); - - // This tests that the default implementation is called. - empty_config.normalize_filename = nullptr; - absl::SetFlagsUsageConfig(empty_config); - - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\a\\a.cc"), "a\\a.cc"); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("//"), ""); - EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\\\"), ""); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/functional/BUILD.bazel b/third_party/abseil_cpp/absl/functional/BUILD.bazel deleted file mode 100644 index ebd9b99b782f..000000000000 --- a/third_party/abseil_cpp/absl/functional/BUILD.bazel +++ /dev/null @@ -1,93 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "bind_front", - srcs = ["internal/front_binder.h"], - hdrs = ["bind_front.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:base_internal", - "//absl/container:compressed_tuple", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_test( - name = "bind_front_test", - srcs = ["bind_front_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bind_front", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "function_ref", - srcs = ["internal/function_ref.h"], - hdrs = ["function_ref.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:base_internal", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "function_ref_test", - size = "small", - srcs = ["function_ref_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":function_ref", - "//absl/container:test_instance_tracker", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "function_ref_benchmark", - srcs = [ - "function_ref_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":function_ref", - "//absl/base:core_headers", - "@com_github_google_benchmark//:benchmark_main", - ], -) diff --git a/third_party/abseil_cpp/absl/functional/CMakeLists.txt b/third_party/abseil_cpp/absl/functional/CMakeLists.txt deleted file mode 100644 index cda914f2cd53..000000000000 --- a/third_party/abseil_cpp/absl/functional/CMakeLists.txt +++ /dev/null @@ -1,72 +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. -# - -absl_cc_library( - NAME - bind_front - SRCS - "internal/front_binder.h" - HDRS - "bind_front.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base_internal - absl::compressed_tuple - PUBLIC -) - -absl_cc_test( - NAME - bind_front_test - SRCS - "bind_front_test.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bind_front - absl::memory - gmock_main -) - -absl_cc_library( - NAME - function_ref - SRCS - "internal/function_ref.h" - HDRS - "function_ref.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base_internal - absl::meta - PUBLIC -) - -absl_cc_test( - NAME - function_ref_test - SRCS - "function_ref_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::function_ref - absl::memory - absl::test_instance_tracker - gmock_main -) diff --git a/third_party/abseil_cpp/absl/functional/bind_front.h b/third_party/abseil_cpp/absl/functional/bind_front.h deleted file mode 100644 index 5b47970e3577..000000000000 --- a/third_party/abseil_cpp/absl/functional/bind_front.h +++ /dev/null @@ -1,184 +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: bind_front.h -// ----------------------------------------------------------------------------- -// -// `absl::bind_front()` returns a functor by binding a number of arguments to -// the front of a provided (usually more generic) functor. Unlike `std::bind`, -// it does not require the use of argument placeholders. The simpler syntax of -// `absl::bind_front()` allows you to avoid known misuses with `std::bind()`. -// -// `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming -// `std::bind_front()`, which similarly resolves these issues with -// `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow -// partial function application. (See -// https://en.wikipedia.org/wiki/Partial_application). - -#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_ -#define ABSL_FUNCTIONAL_BIND_FRONT_H_ - -#include "absl/functional/internal/front_binder.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// bind_front() -// -// Binds the first N arguments of an invocable object and stores them by value. -// -// Like `std::bind()`, `absl::bind_front()` is implicitly convertible to -// `std::function`. In particular, it may be used as a simpler replacement for -// `std::bind()` in most cases, as it does not require placeholders to be -// specified. More importantly, it provides more reliable correctness guarantees -// than `std::bind()`; while `std::bind()` will silently ignore passing more -// parameters than expected, for example, `absl::bind_front()` will report such -// mis-uses as errors. -// -// absl::bind_front(a...) can be seen as storing the results of -// std::make_tuple(a...). -// -// Example: Binding a free function. -// -// int Minus(int a, int b) { return a - b; } -// -// assert(absl::bind_front(Minus)(3, 2) == 3 - 2); -// assert(absl::bind_front(Minus, 3)(2) == 3 - 2); -// assert(absl::bind_front(Minus, 3, 2)() == 3 - 2); -// -// Example: Binding a member function. -// -// struct Math { -// int Double(int a) const { return 2 * a; } -// }; -// -// Math math; -// -// assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3); -// // Stores a pointer to math inside the functor. -// assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3); -// // Stores a copy of math inside the functor. -// assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3); -// // Stores std::unique_ptr<Math> inside the functor. -// assert(absl::bind_front(&Math::Double, -// std::unique_ptr<Math>(new Math))(3) == 2 * 3); -// -// Example: Using `absl::bind_front()`, instead of `std::bind()`, with -// `std::function`. -// -// class FileReader { -// public: -// void ReadFileAsync(const std::string& filename, std::string* content, -// const std::function<void()>& done) { -// // Calls Executor::Schedule(std::function<void()>). -// Executor::DefaultExecutor()->Schedule( -// absl::bind_front(&FileReader::BlockingRead, this, -// filename, content, done)); -// } -// -// private: -// void BlockingRead(const std::string& filename, std::string* content, -// const std::function<void()>& done) { -// CHECK_OK(file::GetContents(filename, content, {})); -// done(); -// } -// }; -// -// `absl::bind_front()` stores bound arguments explicitly using the type passed -// rather than implicitly based on the type accepted by its functor. -// -// Example: Binding arguments explicitly. -// -// void LogStringView(absl::string_view sv) { -// LOG(INFO) << sv; -// } -// -// Executor* e = Executor::DefaultExecutor(); -// std::string s = "hello"; -// absl::string_view sv = s; -// -// // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it. -// e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling -// // string_view. -// -// e->Schedule(absl::bind_front(LogStringView, s)); // OK: stores a copy of -// // s. -// -// To store some of the arguments passed to `absl::bind_front()` by reference, -// use std::ref()` and `std::cref()`. -// -// Example: Storing some of the bound arguments by reference. -// -// class Service { -// public: -// void Serve(const Request& req, std::function<void()>* done) { -// // The request protocol buffer won't be deleted until done is called. -// // It's safe to store a reference to it inside the functor. -// Executor::DefaultExecutor()->Schedule( -// absl::bind_front(&Service::BlockingServe, this, std::cref(req), -// done)); -// } -// -// private: -// void BlockingServe(const Request& req, std::function<void()>* done); -// }; -// -// Example: Storing bound arguments by reference. -// -// void Print(const std::string& a, const std::string& b) { -// std::cerr << a << b; -// } -// -// std::string hi = "Hello, "; -// std::vector<std::string> names = {"Chuk", "Gek"}; -// // Doesn't copy hi. -// for_each(names.begin(), names.end(), -// absl::bind_front(Print, std::ref(hi))); -// -// // DO NOT DO THIS: the functor may outlive "hi", resulting in -// // dangling references. -// foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest")); // BAD! -// auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD! -// -// Example: Storing reference-like types. -// -// void Print(absl::string_view a, const std::string& b) { -// std::cerr << a << b; -// } -// -// std::string hi = "Hello, "; -// // Copies "hi". -// absl::bind_front(Print, hi)("Chuk"); -// -// // Compile error: std::reference_wrapper<const string> is not implicitly -// // convertible to string_view. -// // absl::bind_front(Print, std::cref(hi))("Chuk"); -// -// // Doesn't copy "hi". -// absl::bind_front(Print, absl::string_view(hi))("Chuk"); -// -template <class F, class... BoundArgs> -constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front( - F&& func, BoundArgs&&... args) { - return functional_internal::bind_front_t<F, BoundArgs...>( - absl::in_place, absl::forward<F>(func), - absl::forward<BoundArgs>(args)...); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FUNCTIONAL_BIND_FRONT_H_ diff --git a/third_party/abseil_cpp/absl/functional/bind_front_test.cc b/third_party/abseil_cpp/absl/functional/bind_front_test.cc deleted file mode 100644 index 4801a81caf0d..000000000000 --- a/third_party/abseil_cpp/absl/functional/bind_front_test.cc +++ /dev/null @@ -1,231 +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/functional/bind_front.h" - -#include <stddef.h> - -#include <functional> -#include <memory> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/memory/memory.h" - -namespace { - -char CharAt(const char* s, size_t index) { return s[index]; } - -TEST(BindTest, Basics) { - EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2)); - EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2)); - EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)()); -} - -TEST(BindTest, Lambda) { - auto lambda = [](int x, int y, int z) { return x + y + z; }; - EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3)); - EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3)); - EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3)); - EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)()); -} - -struct Functor { - std::string operator()() & { return "&"; } - std::string operator()() const& { return "const&"; } - std::string operator()() && { return "&&"; } - std::string operator()() const&& { return "const&&"; } -}; - -TEST(BindTest, PerfectForwardingOfBoundArgs) { - auto f = absl::bind_front(Functor()); - const auto& cf = f; - EXPECT_EQ("&", f()); - EXPECT_EQ("const&", cf()); - EXPECT_EQ("&&", std::move(f)()); - EXPECT_EQ("const&&", std::move(cf)()); -} - -struct ArgDescribe { - std::string operator()(int&) const { return "&"; } // NOLINT - std::string operator()(const int&) const { return "const&"; } // NOLINT - std::string operator()(int&&) const { return "&&"; } - std::string operator()(const int&&) const { return "const&&"; } -}; - -TEST(BindTest, PerfectForwardingOfFreeArgs) { - ArgDescribe f; - int i; - EXPECT_EQ("&", absl::bind_front(f)(static_cast<int&>(i))); - EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i))); - EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i))); - EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(i))); -} - -struct NonCopyableFunctor { - NonCopyableFunctor() = default; - NonCopyableFunctor(const NonCopyableFunctor&) = delete; - NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete; - const NonCopyableFunctor* operator()() const { return this; } -}; - -TEST(BindTest, RefToFunctor) { - // It won't copy/move the functor and use the original object. - NonCopyableFunctor ncf; - auto bound_ncf = absl::bind_front(std::ref(ncf)); - auto bound_ncf_copy = bound_ncf; - EXPECT_EQ(&ncf, bound_ncf_copy()); -} - -struct Struct { - std::string value; -}; - -TEST(BindTest, StoreByCopy) { - Struct s = {"hello"}; - auto f = absl::bind_front(&Struct::value, s); - auto g = f; - EXPECT_EQ("hello", f()); - EXPECT_EQ("hello", g()); - EXPECT_NE(&s.value, &f()); - EXPECT_NE(&s.value, &g()); - EXPECT_NE(&g(), &f()); -} - -struct NonCopyable { - explicit NonCopyable(const std::string& s) : value(s) {} - NonCopyable(const NonCopyable&) = delete; - NonCopyable& operator=(const NonCopyable&) = delete; - - std::string value; -}; - -const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; } - -TEST(BindTest, StoreByRef) { - NonCopyable s("hello"); - auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s)); - EXPECT_EQ("hello", f()); - EXPECT_EQ(&s.value, &f()); - auto g = std::move(f); // NOLINT - EXPECT_EQ("hello", g()); - EXPECT_EQ(&s.value, &g()); - s.value = "goodbye"; - EXPECT_EQ("goodbye", g()); -} - -TEST(BindTest, StoreByCRef) { - NonCopyable s("hello"); - auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s)); - EXPECT_EQ("hello", f()); - EXPECT_EQ(&s.value, &f()); - auto g = std::move(f); // NOLINT - EXPECT_EQ("hello", g()); - EXPECT_EQ(&s.value, &g()); - s.value = "goodbye"; - EXPECT_EQ("goodbye", g()); -} - -const std::string& GetNonCopyableValueByWrapper( - std::reference_wrapper<NonCopyable> n) { - return n.get().value; -} - -TEST(BindTest, StoreByRefInvokeByWrapper) { - NonCopyable s("hello"); - auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s)); - EXPECT_EQ("hello", f()); - EXPECT_EQ(&s.value, &f()); - auto g = std::move(f); - EXPECT_EQ("hello", g()); - EXPECT_EQ(&s.value, &g()); - s.value = "goodbye"; - EXPECT_EQ("goodbye", g()); -} - -TEST(BindTest, StoreByPointer) { - NonCopyable s("hello"); - auto f = absl::bind_front(&NonCopyable::value, &s); - EXPECT_EQ("hello", f()); - EXPECT_EQ(&s.value, &f()); - auto g = std::move(f); - EXPECT_EQ("hello", g()); - EXPECT_EQ(&s.value, &g()); -} - -int Sink(std::unique_ptr<int> p) { - return *p; -} - -std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); } - -TEST(BindTest, NonCopyableArg) { - EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42))); - EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))()); -} - -TEST(BindTest, NonCopyableResult) { - EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42)); - EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42)); -} - -// is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to -// instantiate the copy constructor leads to a compile error. This is similar -// to how standard containers behave. -template <class T> -struct FalseCopyable { - FalseCopyable() {} - FalseCopyable(const FalseCopyable& other) : m(other.m) {} - FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {} - T m; -}; - -int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; } - -TEST(BindTest, WrappedMoveOnly) { - FalseCopyable<std::unique_ptr<int>> x; - x.m = absl::make_unique<int>(42); - auto f = absl::bind_front(&GetMember, std::move(x)); - EXPECT_EQ(42, std::move(f)()); -} - -int Plus(int a, int b) { return a + b; } - -TEST(BindTest, ConstExpr) { - constexpr auto f = absl::bind_front(CharAt); - EXPECT_EQ(f("ABC", 1), 'B'); - static constexpr int five = 5; - constexpr auto plus5 = absl::bind_front(Plus, five); - EXPECT_EQ(plus5(1), 6); - - // There seems to be a bug in MSVC dealing constexpr construction of - // char[]. Notice 'plus5' above; 'int' works just fine. -#if !(defined(_MSC_VER) && _MSC_VER < 1910) - static constexpr char data[] = "DEF"; - constexpr auto g = absl::bind_front(CharAt, data); - EXPECT_EQ(g(1), 'E'); -#endif -} - -struct ManglingCall { - int operator()(int, double, std::string) const { return 0; } -}; - -TEST(BindTest, Mangling) { - // We just want to generate a particular instantiation to see its mangling. - absl::bind_front(ManglingCall{}, 1, 3.3)("A"); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/functional/function_ref.h b/third_party/abseil_cpp/absl/functional/function_ref.h deleted file mode 100644 index 6e03ac2e04e9..000000000000 --- a/third_party/abseil_cpp/absl/functional/function_ref.h +++ /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. -// -// ----------------------------------------------------------------------------- -// File: function_ref.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::FunctionRef` type for holding a -// non-owning reference to an object of any invocable type. This function -// reference is typically most useful as a type-erased argument type for -// accepting function types that neither take ownership nor copy the type; using -// the reference type in this case avoids a copy and an allocation. Best -// practices of other non-owning reference-like objects (such as -// `absl::string_view`) apply here. -// -// An `absl::FunctionRef` is similar in usage to a `std::function` but has the -// following differences: -// -// * It doesn't own the underlying object. -// * It doesn't have a null or empty state. -// * It never performs deep copies or allocations. -// * It's much faster and cheaper to construct. -// * It's trivially copyable and destructable. -// -// Generally, `absl::FunctionRef` should not be used as a return value, data -// member, or to initialize a `std::function`. Such usages will often lead to -// problematic lifetime issues. Once you convert something to an -// `absl::FunctionRef` you cannot make a deep copy later. -// -// This class is suitable for use wherever a "const std::function<>&" -// would be used without making a copy. ForEach functions and other versions of -// the visitor pattern are a good example of when this class should be used. -// -// This class is trivial to copy and should be passed by value. -#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_ -#define ABSL_FUNCTIONAL_FUNCTION_REF_H_ - -#include <cassert> -#include <functional> -#include <type_traits> - -#include "absl/functional/internal/function_ref.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// FunctionRef -// -// Dummy class declaration to allow the partial specialization based on function -// types below. -template <typename T> -class FunctionRef; - -// FunctionRef -// -// An `absl::FunctionRef` is a lightweight wrapper to any invokable object with -// a compatible signature. Generally, an `absl::FunctionRef` should only be used -// as an argument type and should be preferred as an argument over a const -// reference to a `std::function`. -// -// Example: -// -// // The following function takes a function callback by const reference -// bool Visitor(const std::function<void(my_proto&, -// absl::string_view)>& callback); -// -// // Assuming that the function is not stored or otherwise copied, it can be -// // replaced by an `absl::FunctionRef`: -// bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)> -// callback); -// -// Note: the assignment operator within an `absl::FunctionRef` is intentionally -// deleted to prevent misuse; because the `absl::FunctionRef` does not own the -// underlying type, assignment likely indicates misuse. -template <typename R, typename... Args> -class FunctionRef<R(Args...)> { - private: - // Used to disable constructors for objects that are not compatible with the - // signature of this FunctionRef. - template <typename F, - typename FR = absl::base_internal::invoke_result_t<F, Args&&...>> - using EnableIfCompatible = - typename std::enable_if<std::is_void<R>::value || - std::is_convertible<FR, R>::value>::type; - - public: - // Constructs a FunctionRef from any invokable type. - template <typename F, typename = EnableIfCompatible<const F&>> - FunctionRef(const F& f) // NOLINT(runtime/explicit) - : invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) { - absl::functional_internal::AssertNonNull(f); - ptr_.obj = &f; - } - - // Overload for function pointers. This eliminates a level of indirection that - // would happen if the above overload was used (it lets us store the pointer - // instead of a pointer to a pointer). - // - // This overload is also used for references to functions, since references to - // functions can decay to function pointers implicitly. - template < - typename F, typename = EnableIfCompatible<F*>, - absl::functional_internal::EnableIf<absl::is_function<F>::value> = 0> - FunctionRef(F* f) // NOLINT(runtime/explicit) - : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) { - assert(f != nullptr); - ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f); - } - - // To help prevent subtle lifetime bugs, FunctionRef is not assignable. - // Typically, it should only be used as an argument type. - FunctionRef& operator=(const FunctionRef& rhs) = delete; - - // Call the underlying object. - R operator()(Args... args) const { - return invoker_(ptr_, std::forward<Args>(args)...); - } - - private: - absl::functional_internal::VoidPtr ptr_; - absl::functional_internal::Invoker<R, Args...> invoker_; -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FUNCTIONAL_FUNCTION_REF_H_ diff --git a/third_party/abseil_cpp/absl/functional/function_ref_benchmark.cc b/third_party/abseil_cpp/absl/functional/function_ref_benchmark.cc deleted file mode 100644 index 045305bfef30..000000000000 --- a/third_party/abseil_cpp/absl/functional/function_ref_benchmark.cc +++ /dev/null @@ -1,142 +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/functional/function_ref.h" - -#include <memory> - -#include "benchmark/benchmark.h" -#include "absl/base/attributes.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -int dummy = 0; - -void FreeFunction() { benchmark::DoNotOptimize(dummy); } - -struct TrivialFunctor { - void operator()() const { benchmark::DoNotOptimize(dummy); } -}; - -struct LargeFunctor { - void operator()() const { benchmark::DoNotOptimize(this); } - std::string a, b, c; -}; - -template <typename Function, typename... Args> -void ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) { - f(std::forward<Args>(args)...); -} - -template <typename Function, typename Callable, typename... Args> -void ConstructAndCallFunctionBenchmark(benchmark::State& state, - const Callable& c, Args&&... args) { - for (auto _ : state) { - CallFunction<Function>(c, std::forward<Args>(args)...); - } -} - -void BM_TrivialStdFunction(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<std::function<void()>>(state, - TrivialFunctor{}); -} -BENCHMARK(BM_TrivialStdFunction); - -void BM_TrivialFunctionRef(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, - TrivialFunctor{}); -} -BENCHMARK(BM_TrivialFunctionRef); - -void BM_LargeStdFunction(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<std::function<void()>>(state, - LargeFunctor{}); -} -BENCHMARK(BM_LargeStdFunction); - -void BM_LargeFunctionRef(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{}); -} -BENCHMARK(BM_LargeFunctionRef); - -void BM_FunPtrStdFunction(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction); -} -BENCHMARK(BM_FunPtrStdFunction); - -void BM_FunPtrFunctionRef(benchmark::State& state) { - ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction); -} -BENCHMARK(BM_FunPtrFunctionRef); - -// Doesn't include construction or copy overhead in the loop. -template <typename Function, typename Callable, typename... Args> -void CallFunctionBenchmark(benchmark::State& state, const Callable& c, - Args... args) { - Function f = c; - for (auto _ : state) { - benchmark::DoNotOptimize(&f); - f(args...); - } -} - -struct FunctorWithTrivialArgs { - void operator()(int a, int b, int c) const { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - benchmark::DoNotOptimize(c); - } -}; - -void BM_TrivialArgsStdFunction(benchmark::State& state) { - CallFunctionBenchmark<std::function<void(int, int, int)>>( - state, FunctorWithTrivialArgs{}, 1, 2, 3); -} -BENCHMARK(BM_TrivialArgsStdFunction); - -void BM_TrivialArgsFunctionRef(benchmark::State& state) { - CallFunctionBenchmark<FunctionRef<void(int, int, int)>>( - state, FunctorWithTrivialArgs{}, 1, 2, 3); -} -BENCHMARK(BM_TrivialArgsFunctionRef); - -struct FunctorWithNonTrivialArgs { - void operator()(std::string a, std::string b, std::string c) const { - benchmark::DoNotOptimize(&a); - benchmark::DoNotOptimize(&b); - benchmark::DoNotOptimize(&c); - } -}; - -void BM_NonTrivialArgsStdFunction(benchmark::State& state) { - std::string a, b, c; - CallFunctionBenchmark< - std::function<void(std::string, std::string, std::string)>>( - state, FunctorWithNonTrivialArgs{}, a, b, c); -} -BENCHMARK(BM_NonTrivialArgsStdFunction); - -void BM_NonTrivialArgsFunctionRef(benchmark::State& state) { - std::string a, b, c; - CallFunctionBenchmark< - FunctionRef<void(std::string, std::string, std::string)>>( - state, FunctorWithNonTrivialArgs{}, a, b, c); -} -BENCHMARK(BM_NonTrivialArgsFunctionRef); - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/functional/function_ref_test.cc b/third_party/abseil_cpp/absl/functional/function_ref_test.cc deleted file mode 100644 index 3aa59745873d..000000000000 --- a/third_party/abseil_cpp/absl/functional/function_ref_test.cc +++ /dev/null @@ -1,257 +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/functional/function_ref.h" - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/memory/memory.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -void RunFun(FunctionRef<void()> f) { f(); } - -TEST(FunctionRefTest, Lambda) { - bool ran = false; - RunFun([&] { ran = true; }); - EXPECT_TRUE(ran); -} - -int Function() { return 1337; } - -TEST(FunctionRefTest, Function1) { - FunctionRef<int()> ref(&Function); - EXPECT_EQ(1337, ref()); -} - -TEST(FunctionRefTest, Function2) { - FunctionRef<int()> ref(Function); - EXPECT_EQ(1337, ref()); -} - -int NoExceptFunction() noexcept { return 1337; } - -// TODO(jdennett): Add a test for noexcept member functions. -TEST(FunctionRefTest, NoExceptFunction) { - FunctionRef<int()> ref(NoExceptFunction); - EXPECT_EQ(1337, ref()); -} - -TEST(FunctionRefTest, ForwardsArgs) { - auto l = [](std::unique_ptr<int> i) { return *i; }; - FunctionRef<int(std::unique_ptr<int>)> ref(l); - EXPECT_EQ(42, ref(absl::make_unique<int>(42))); -} - -TEST(FunctionRef, ReturnMoveOnly) { - auto l = [] { return absl::make_unique<int>(29); }; - FunctionRef<std::unique_ptr<int>()> ref(l); - EXPECT_EQ(29, *ref()); -} - -TEST(FunctionRef, ManyArgs) { - auto l = [](int a, int b, int c) { return a + b + c; }; - FunctionRef<int(int, int, int)> ref(l); - EXPECT_EQ(6, ref(1, 2, 3)); -} - -TEST(FunctionRef, VoidResultFromNonVoidFunctor) { - bool ran = false; - auto l = [&]() -> int { - ran = true; - return 2; - }; - FunctionRef<void()> ref(l); - ref(); - EXPECT_TRUE(ran); -} - -TEST(FunctionRef, CastFromDerived) { - struct Base {}; - struct Derived : public Base {}; - - Derived d; - auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); }; - FunctionRef<void(Derived*)> ref1(l1); - ref1(&d); - - auto l2 = [&]() -> Derived* { return &d; }; - FunctionRef<Base*()> ref2(l2); - EXPECT_EQ(&d, ref2()); -} - -TEST(FunctionRef, VoidResultFromNonVoidFuncton) { - FunctionRef<void()> ref(Function); - ref(); -} - -TEST(FunctionRef, MemberPtr) { - struct S { - int i; - }; - - S s{1100111}; - auto mem_ptr = &S::i; - FunctionRef<int(const S& s)> ref(mem_ptr); - EXPECT_EQ(1100111, ref(s)); -} - -TEST(FunctionRef, MemberFun) { - struct S { - int i; - int get_i() const { return i; } - }; - - S s{22}; - auto mem_fun_ptr = &S::get_i; - FunctionRef<int(const S& s)> ref(mem_fun_ptr); - EXPECT_EQ(22, ref(s)); -} - -TEST(FunctionRef, MemberFunRefqualified) { - struct S { - int i; - int get_i() && { return i; } - }; - auto mem_fun_ptr = &S::get_i; - S s{22}; - FunctionRef<int(S && s)> ref(mem_fun_ptr); - EXPECT_EQ(22, ref(std::move(s))); -} - -#if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST) - -TEST(FunctionRef, MemberFunRefqualifiedNull) { - struct S { - int i; - int get_i() && { return i; } - }; - auto mem_fun_ptr = &S::get_i; - mem_fun_ptr = nullptr; - EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, ""); -} - -TEST(FunctionRef, NullMemberPtrAssertFails) { - struct S { - int i; - }; - using MemberPtr = int S::*; - MemberPtr mem_ptr = nullptr; - EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, ""); -} - -#endif // GTEST_HAS_DEATH_TEST - -TEST(FunctionRef, CopiesAndMovesPerPassByValue) { - absl::test_internal::InstanceTracker tracker; - absl::test_internal::CopyableMovableInstance instance(0); - auto l = [](absl::test_internal::CopyableMovableInstance) {}; - FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l); - ref(instance); - EXPECT_EQ(tracker.copies(), 1); - EXPECT_EQ(tracker.moves(), 1); -} - -TEST(FunctionRef, CopiesAndMovesPerPassByRef) { - absl::test_internal::InstanceTracker tracker; - absl::test_internal::CopyableMovableInstance instance(0); - auto l = [](const absl::test_internal::CopyableMovableInstance&) {}; - FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l); - ref(instance); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 0); -} - -TEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) { - absl::test_internal::InstanceTracker tracker; - absl::test_internal::CopyableMovableInstance instance(0); - auto l = [](absl::test_internal::CopyableMovableInstance) {}; - FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l); - ref(std::move(instance)); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 2); -} - -TEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) { - absl::test_internal::InstanceTracker tracker; - absl::test_internal::CopyableMovableInstance instance(0); - auto l = [](const absl::test_internal::CopyableMovableInstance&) {}; - FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l); - ref(std::move(instance)); - EXPECT_EQ(tracker.copies(), 0); - EXPECT_EQ(tracker.moves(), 1); -} - -TEST(FunctionRef, PassByValueTypes) { - using absl::functional_internal::Invoker; - using absl::functional_internal::VoidPtr; - using absl::test_internal::CopyableMovableInstance; - struct Trivial { - void* p[2]; - }; - struct LargeTrivial { - void* p[3]; - }; - - static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value, - "Scalar types should be passed by value"); - static_assert( - std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value, - "Small trivial types should be passed by value"); - static_assert(std::is_same<Invoker<void, LargeTrivial>, - void (*)(VoidPtr, LargeTrivial &&)>::value, - "Large trivial types should be passed by rvalue reference"); - static_assert( - std::is_same<Invoker<void, CopyableMovableInstance>, - void (*)(VoidPtr, CopyableMovableInstance &&)>::value, - "Types with copy/move ctor should be passed by rvalue reference"); - - // References are passed as references. - static_assert( - std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value, - "Reference types should be preserved"); - static_assert( - std::is_same<Invoker<void, CopyableMovableInstance&>, - void (*)(VoidPtr, CopyableMovableInstance&)>::value, - "Reference types should be preserved"); - static_assert( - std::is_same<Invoker<void, CopyableMovableInstance&&>, - void (*)(VoidPtr, CopyableMovableInstance &&)>::value, - "Reference types should be preserved"); - - // Make sure the address of an object received by reference is the same as the - // addess of the object passed by the caller. - { - LargeTrivial obj; - auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); }; - absl::FunctionRef<void(LargeTrivial&)> ref(test); - ref(obj); - } - - { - Trivial obj; - auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); }; - absl::FunctionRef<void(Trivial&)> ref(test); - ref(obj); - } -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/functional/internal/front_binder.h b/third_party/abseil_cpp/absl/functional/internal/front_binder.h deleted file mode 100644 index 45f52de73d25..000000000000 --- a/third_party/abseil_cpp/absl/functional/internal/front_binder.h +++ /dev/null @@ -1,95 +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. - -// Implementation details for `absl::bind_front()`. - -#ifndef ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ -#define ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ - -#include <cstddef> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/invoke.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/meta/type_traits.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace functional_internal { - -// Invoke the method, expanding the tuple of bound arguments. -template <class R, class Tuple, size_t... Idx, class... Args> -R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) { - return base_internal::invoke( - absl::forward<Tuple>(bound).template get<Idx>()..., - absl::forward<Args>(free)...); -} - -template <class F, class... BoundArgs> -class FrontBinder { - using BoundArgsT = absl::container_internal::CompressedTuple<F, BoundArgs...>; - using Idx = absl::make_index_sequence<sizeof...(BoundArgs) + 1>; - - BoundArgsT bound_args_; - - public: - template <class... Ts> - constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts) - : bound_args_(absl::forward<Ts>(ts)...) {} - - template <class... FreeArgs, class R = base_internal::invoke_result_t< - F&, BoundArgs&..., FreeArgs&&...>> - R operator()(FreeArgs&&... free_args) & { - return functional_internal::Apply<R>(bound_args_, Idx(), - absl::forward<FreeArgs>(free_args)...); - } - - template <class... FreeArgs, - class R = base_internal::invoke_result_t< - const F&, const BoundArgs&..., FreeArgs&&...>> - R operator()(FreeArgs&&... free_args) const& { - return functional_internal::Apply<R>(bound_args_, Idx(), - absl::forward<FreeArgs>(free_args)...); - } - - template <class... FreeArgs, class R = base_internal::invoke_result_t< - F&&, BoundArgs&&..., FreeArgs&&...>> - R operator()(FreeArgs&&... free_args) && { - // This overload is called when *this is an rvalue. If some of the bound - // arguments are stored by value or rvalue reference, we move them. - return functional_internal::Apply<R>(absl::move(bound_args_), Idx(), - absl::forward<FreeArgs>(free_args)...); - } - - template <class... FreeArgs, - class R = base_internal::invoke_result_t< - const F&&, const BoundArgs&&..., FreeArgs&&...>> - R operator()(FreeArgs&&... free_args) const&& { - // This overload is called when *this is an rvalue. If some of the bound - // arguments are stored by value or rvalue reference, we move them. - return functional_internal::Apply<R>(absl::move(bound_args_), Idx(), - absl::forward<FreeArgs>(free_args)...); - } -}; - -template <class F, class... BoundArgs> -using bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>; - -} // namespace functional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ diff --git a/third_party/abseil_cpp/absl/functional/internal/function_ref.h b/third_party/abseil_cpp/absl/functional/internal/function_ref.h deleted file mode 100644 index b5bb8b430a81..000000000000 --- a/third_party/abseil_cpp/absl/functional/internal/function_ref.h +++ /dev/null @@ -1,106 +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_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_ -#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_ - -#include <cassert> -#include <functional> -#include <type_traits> - -#include "absl/base/internal/invoke.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace functional_internal { - -// Like a void* that can handle function pointers as well. The standard does not -// allow function pointers to round-trip through void*, but void(*)() is fine. -// -// Note: It's important that this class remains trivial and is the same size as -// a pointer, since this allows the compiler to perform tail-call optimizations -// when the underlying function is a callable object with a matching signature. -union VoidPtr { - const void* obj; - void (*fun)(); -}; - -// Chooses the best type for passing T as an argument. -// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are -// passed by value. -template <typename T> -constexpr bool PassByValue() { - return !std::is_lvalue_reference<T>::value && - absl::is_trivially_copy_constructible<T>::value && - absl::is_trivially_copy_assignable< - typename std::remove_cv<T>::type>::value && - std::is_trivially_destructible<T>::value && - sizeof(T) <= 2 * sizeof(void*); -} - -template <typename T> -struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {}; - -// An Invoker takes a pointer to the type-erased invokable object, followed by -// the arguments that the invokable object expects. -// -// Note: The order of arguments here is an optimization, since member functions -// have an implicit "this" pointer as their first argument, putting VoidPtr -// first allows the compiler to perform tail-call optimization in many cases. -template <typename R, typename... Args> -using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...); - -// -// InvokeObject and InvokeFunction provide static "Invoke" functions that can be -// used as Invokers for objects or functions respectively. -// -// static_cast<R> handles the case the return type is void. -template <typename Obj, typename R, typename... Args> -R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) { - auto o = static_cast<const Obj*>(ptr.obj); - return static_cast<R>( - absl::base_internal::invoke(*o, std::forward<Args>(args)...)); -} - -template <typename Fun, typename R, typename... Args> -R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) { - auto f = reinterpret_cast<Fun>(ptr.fun); - return static_cast<R>( - absl::base_internal::invoke(f, std::forward<Args>(args)...)); -} - -template <typename Sig> -void AssertNonNull(const std::function<Sig>& f) { - assert(f != nullptr); - (void)f; -} - -template <typename F> -void AssertNonNull(const F&) {} - -template <typename F, typename C> -void AssertNonNull(F C::*f) { - assert(f != nullptr); - (void)f; -} - -template <bool C> -using EnableIf = typename ::std::enable_if<C, int>::type; - -} // namespace functional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_ diff --git a/third_party/abseil_cpp/absl/hash/BUILD.bazel b/third_party/abseil_cpp/absl/hash/BUILD.bazel deleted file mode 100644 index 5b1e2d01fd3c..000000000000 --- a/third_party/abseil_cpp/absl/hash/BUILD.bazel +++ /dev/null @@ -1,122 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "hash", - srcs = [ - "internal/hash.cc", - "internal/hash.h", - ], - hdrs = ["hash.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":city", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/container:fixed_array", - "//absl/meta:type_traits", - "//absl/numeric:int128", - "//absl/strings", - "//absl/types:optional", - "//absl/types:variant", - "//absl/utility", - ], -) - -cc_library( - name = "hash_testing", - testonly = 1, - hdrs = ["hash_testing.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":spy_hash_state", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/types:variant", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "hash_test", - srcs = ["hash_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":hash", - ":hash_testing", - ":spy_hash_state", - "//absl/base:core_headers", - "//absl/container:flat_hash_set", - "//absl/meta:type_traits", - "//absl/numeric:int128", - "//absl/strings:cord_test_helpers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "spy_hash_state", - testonly = 1, - hdrs = ["internal/spy_hash_state.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - ":hash", - "//absl/strings", - "//absl/strings:str_format", - ], -) - -cc_library( - name = "city", - srcs = ["internal/city.cc"], - hdrs = [ - "internal/city.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - ], -) - -cc_test( - name = "city_test", - srcs = ["internal/city_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":city", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/hash/CMakeLists.txt b/third_party/abseil_cpp/absl/hash/CMakeLists.txt deleted file mode 100644 index 61365e9bb5a1..000000000000 --- a/third_party/abseil_cpp/absl/hash/CMakeLists.txt +++ /dev/null @@ -1,116 +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. -# - -absl_cc_library( - NAME - hash - HDRS - "hash.h" - SRCS - "internal/hash.cc" - "internal/hash.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::endian - absl::fixed_array - absl::meta - absl::int128 - absl::strings - absl::optional - absl::variant - absl::utility - absl::city - PUBLIC -) - -absl_cc_library( - NAME - hash_testing - HDRS - "hash_testing.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::spy_hash_state - absl::meta - absl::strings - absl::variant - gmock - TESTONLY -) - -absl_cc_test( - NAME - hash_test - SRCS - "hash_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::cord_test_helpers - absl::hash - absl::hash_testing - absl::core_headers - absl::flat_hash_set - absl::spy_hash_state - absl::meta - absl::int128 - gmock_main -) - -absl_cc_library( - NAME - spy_hash_state - HDRS - "internal/spy_hash_state.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::hash - absl::strings - absl::str_format - TESTONLY -) - -absl_cc_library( - NAME - city - HDRS - "internal/city.h" - SRCS - "internal/city.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - absl::endian -) - -absl_cc_test( - NAME - city_test - SRCS - "internal/city_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::city - gmock_main -) - diff --git a/third_party/abseil_cpp/absl/hash/hash.h b/third_party/abseil_cpp/absl/hash/hash.h deleted file mode 100644 index 5de132cac8ac..000000000000 --- a/third_party/abseil_cpp/absl/hash/hash.h +++ /dev/null @@ -1,325 +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: hash.h -// ----------------------------------------------------------------------------- -// -// This header file defines the Abseil `hash` library and the Abseil hashing -// framework. This framework consists of the following: -// -// * The `absl::Hash` functor, which is used to invoke the hasher within the -// Abseil hashing framework. `absl::Hash<T>` supports most basic types and -// a number of Abseil types out of the box. -// * `AbslHashValue`, an extension point that allows you to extend types to -// support Abseil hashing without requiring you to define a hashing -// algorithm. -// * `HashState`, a type-erased class which implements the manipulation of the -// hash state (H) itself, contains member functions `combine()` and -// `combine_contiguous()`, which you can use to contribute to an existing -// hash state when hashing your types. -// -// Unlike `std::hash` or other hashing frameworks, the Abseil hashing framework -// provides most of its utility by abstracting away the hash algorithm (and its -// implementation) entirely. Instead, a type invokes the Abseil hashing -// framework by simply combining its state with the state of known, hashable -// types. Hashing of that combined state is separately done by `absl::Hash`. -// -// One should assume that a hash algorithm is chosen randomly at the start of -// each process. E.g., `absl::Hash<int>{}(9)` in one process and -// `absl::Hash<int>{}(9)` in another process are likely to differ. -// -// `absl::Hash` is intended to strongly mix input bits with a target of passing -// an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect). -// -// Example: -// -// // Suppose we have a class `Circle` for which we want to add hashing: -// class Circle { -// public: -// ... -// private: -// std::pair<int, int> center_; -// int radius_; -// }; -// -// // To add hashing support to `Circle`, we simply need to add a free -// // (non-member) function `AbslHashValue()`, and return the combined hash -// // state of the existing hash state and the class state. You can add such a -// // free function using a friend declaration within the body of the class: -// class Circle { -// public: -// ... -// template <typename H> -// friend H AbslHashValue(H h, const Circle& c) { -// return H::combine(std::move(h), c.center_, c.radius_); -// } -// ... -// }; -// -// For more information, see Adding Type Support to `absl::Hash` below. -// -#ifndef ABSL_HASH_HASH_H_ -#define ABSL_HASH_HASH_H_ - -#include "absl/hash/internal/hash.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// `absl::Hash` -// ----------------------------------------------------------------------------- -// -// `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T` -// satisfying any of the following conditions (in order): -// -// * 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 `std::hash<T>` -// -// `absl::Hash` intrinsically supports the following types: -// -// * All integral types (including bool) -// * All enum types -// * All floating-point types (although hashing them is discouraged) -// * All pointer types, including nullptr_t -// * std::pair<T1, T2>, if T1 and T2 are hashable -// * 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) -// * All the standard sequence containers (provided the elements are hashable) -// * All the standard ordered associative containers (provided the elements are -// hashable) -// * absl types such as the following: -// * absl::string_view -// * absl::InlinedVector -// * absl::FixedArray -// * absl::uint128 -// * absl::Time, absl::Duration, and absl::TimeZone -// -// Note: the list above is not meant to be exhaustive. Additional type support -// may be added, in which case the above list will be updated. -// -// ----------------------------------------------------------------------------- -// absl::Hash Invocation Evaluation -// ----------------------------------------------------------------------------- -// -// When invoked, `absl::Hash<T>` searches for supplied hash functions in the -// following order: -// -// * 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 `std::hash<T>` specialization -// -// The fallback to legacy hash functions exists mainly for backwards -// compatibility. If you have a choice, prefer defining an `AbslHashValue` -// overload instead of specializing any legacy hash functors. -// -// ----------------------------------------------------------------------------- -// The Hash State Concept, and using `HashState` for Type Erasure -// ----------------------------------------------------------------------------- -// -// The `absl::Hash` framework relies on the Concept of a "hash state." Such a -// hash state is used in several places: -// -// * Within existing implementations of `absl::Hash<T>` to store the hashed -// state of an object. Note that it is up to the implementation how it stores -// such state. A hash table, for example, may mix the state to produce an -// integer value; a testing framework may simply hold a vector of that state. -// * Within implementations of `AbslHashValue()` used to extend user-defined -// types. (See "Adding Type Support to absl::Hash" below.) -// * Inside a `HashState`, providing type erasure for the concept of a hash -// state, which you can use to extend the `absl::Hash` framework for types -// that are otherwise difficult to extend using `AbslHashValue()`. (See the -// `HashState` class below.) -// -// The "hash state" concept contains two member functions for mixing hash state: -// -// * `H::combine(state, values...)` -// -// Combines an arbitrary number of values into a hash state, returning the -// updated state. Note that the existing hash state is move-only and must be -// passed by value. -// -// Each of the value types T must be hashable by H. -// -// NOTE: -// -// state = H::combine(std::move(state), value1, value2, value3); -// -// must be guaranteed to produce the same hash expansion as -// -// state = H::combine(std::move(state), value1); -// state = H::combine(std::move(state), value2); -// state = H::combine(std::move(state), value3); -// -// * `H::combine_contiguous(state, data, size)` -// -// Combines a contiguous array of `size` elements into a hash state, -// returning the updated state. Note that the existing hash state is -// move-only and must be passed by value. -// -// NOTE: -// -// state = H::combine_contiguous(std::move(state), data, size); -// -// need NOT be guaranteed to produce the same hash expansion as a loop -// (it may perform internal optimizations). If you need this guarantee, use a -// loop instead. -// -// ----------------------------------------------------------------------------- -// Adding Type Support to `absl::Hash` -// ----------------------------------------------------------------------------- -// -// To add support for your user-defined type, add a proper `AbslHashValue()` -// overload as a free (non-member) function. The overload will take an -// existing hash state and should combine that state with state from the type. -// -// Example: -// -// template <typename H> -// H AbslHashValue(H state, const MyType& v) { -// return H::combine(std::move(state), v.field1, ..., v.fieldN); -// } -// -// where `(field1, ..., fieldN)` are the members you would use on your -// `operator==` to define equality. -// -// Notice that `AbslHashValue` is not a class member, but an ordinary function. -// An `AbslHashValue` overload for a type should only be declared in the same -// file and namespace as said type. The proper `AbslHashValue` implementation -// for a given type will be discovered via ADL. -// -// Note: unlike `std::hash', `absl::Hash` should never be specialized. It must -// only be extended by adding `AbslHashValue()` overloads. -// -template <typename T> -using Hash = absl::hash_internal::Hash<T>; - -// HashState -// -// A type erased version of the hash state concept, for use in user-defined -// `AbslHashValue` implementations that can't use templates (such as PImpl -// classes, virtual functions, etc.). The type erasure adds overhead so it -// should be avoided unless necessary. -// -// Note: This wrapper will only erase calls to: -// combine_contiguous(H, const unsigned char*, size_t) -// -// All other calls will be handled internally and will not invoke overloads -// provided by the wrapped class. -// -// Users of this class should still define a template `AbslHashValue` function, -// but can use `absl::HashState::Create(&state)` to erase the type of the hash -// state and dispatch to their private hashing logic. -// -// This state can be used like any other hash state. In particular, you can call -// `HashState::combine()` and `HashState::combine_contiguous()` on it. -// -// Example: -// -// class Interface { -// public: -// template <typename H> -// friend H AbslHashValue(H state, const Interface& value) { -// state = H::combine(std::move(state), std::type_index(typeid(*this))); -// value.HashValue(absl::HashState::Create(&state)); -// return state; -// } -// private: -// virtual void HashValue(absl::HashState state) const = 0; -// }; -// -// class Impl : Interface { -// private: -// void HashValue(absl::HashState state) const override { -// absl::HashState::combine(std::move(state), v1_, v2_); -// } -// int v1_; -// std::string v2_; -// }; -class HashState : public hash_internal::HashStateBase<HashState> { - public: - // HashState::Create() - // - // Create a new `HashState` instance that wraps `state`. All calls to - // `combine()` and `combine_contiguous()` on the new instance will be - // redirected to the original `state` object. The `state` object must outlive - // the `HashState` instance. - template <typename T> - static HashState Create(T* state) { - HashState s; - s.Init(state); - return s; - } - - HashState(const HashState&) = delete; - HashState& operator=(const HashState&) = delete; - HashState(HashState&&) = default; - HashState& operator=(HashState&&) = default; - - // HashState::combine() - // - // Combines an arbitrary number of values into a hash state, returning the - // updated state. - using HashState::HashStateBase::combine; - - // HashState::combine_contiguous() - // - // Combines a contiguous array of `size` elements into a hash state, returning - // the updated state. - static HashState combine_contiguous(HashState hash_state, - const unsigned char* first, size_t size) { - hash_state.combine_contiguous_(hash_state.state_, first, size); - return hash_state; - } - using HashState::HashStateBase::combine_contiguous; - - private: - HashState() = default; - - template <typename T> - static void CombineContiguousImpl(void* p, const unsigned char* first, - size_t size) { - T& state = *static_cast<T*>(p); - state = T::combine_contiguous(std::move(state), first, size); - } - - template <typename T> - void Init(T* state) { - state_ = state; - combine_contiguous_ = &CombineContiguousImpl<T>; - } - - // Do not erase an already erased state. - void Init(HashState* state) { - state_ = state->state_; - combine_contiguous_ = state->combine_contiguous_; - } - - void* state_; - void (*combine_contiguous_)(void*, const unsigned char*, size_t); -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HASH_HASH_H_ diff --git a/third_party/abseil_cpp/absl/hash/hash_test.cc b/third_party/abseil_cpp/absl/hash/hash_test.cc deleted file mode 100644 index 1d2e6cf0df44..000000000000 --- a/third_party/abseil_cpp/absl/hash/hash_test.cc +++ /dev/null @@ -1,976 +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/hash/hash.h" - -#include <array> -#include <bitset> -#include <cstring> -#include <deque> -#include <forward_list> -#include <functional> -#include <iterator> -#include <limits> -#include <list> -#include <map> -#include <memory> -#include <numeric> -#include <random> -#include <set> -#include <string> -#include <tuple> -#include <type_traits> -#include <unordered_map> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/flat_hash_set.h" -#include "absl/hash/hash_testing.h" -#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 { - -using absl::Hash; -using absl::hash_internal::SpyHashState; - -template <typename T> -class HashValueIntTest : public testing::Test { -}; -TYPED_TEST_SUITE_P(HashValueIntTest); - -template <typename T> -SpyHashState SpyHash(const T& value) { - return SpyHashState::combine(SpyHashState(), value); -} - -// Helper trait to verify if T is hashable. We use absl::Hash's poison status to -// detect it. -template <typename T> -using is_hashable = std::is_default_constructible<absl::Hash<T>>; - -TYPED_TEST_P(HashValueIntTest, BasicUsage) { - EXPECT_TRUE((is_hashable<TypeParam>::value)); - - TypeParam n = 42; - EXPECT_EQ(SpyHash(n), SpyHash(TypeParam{42})); - EXPECT_NE(SpyHash(n), SpyHash(TypeParam{0})); - EXPECT_NE(SpyHash(std::numeric_limits<TypeParam>::max()), - SpyHash(std::numeric_limits<TypeParam>::min())); -} - -TYPED_TEST_P(HashValueIntTest, FastPath) { - // Test the fast-path to make sure the values are the same. - TypeParam n = 42; - EXPECT_EQ(absl::Hash<TypeParam>{}(n), - absl::Hash<std::tuple<TypeParam>>{}(std::tuple<TypeParam>(n))); -} - -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>; -INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes); - -enum LegacyEnum { kValue1, kValue2, kValue3 }; - -enum class EnumClass { kValue4, kValue5, kValue6 }; - -TEST(HashValueTest, EnumAndBool) { - EXPECT_TRUE((is_hashable<LegacyEnum>::value)); - EXPECT_TRUE((is_hashable<EnumClass>::value)); - EXPECT_TRUE((is_hashable<bool>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3))); - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6))); - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(true, false))); -} - -TEST(HashValueTest, FloatingPoint) { - EXPECT_TRUE((is_hashable<float>::value)); - EXPECT_TRUE((is_hashable<double>::value)); - EXPECT_TRUE((is_hashable<long double>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(), - -std::numeric_limits<float>::infinity()))); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(), - -std::numeric_limits<double>::infinity()))); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - // Add some values with small exponent to test that NORMAL values also - // append their category. - .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L, - 17 * static_cast<long double>(std::numeric_limits<double>::max()), - std::numeric_limits<long double>::infinity(), - -std::numeric_limits<long double>::infinity()))); -} - -TEST(HashValueTest, Pointer) { - EXPECT_TRUE((is_hashable<int*>::value)); - - int i; - int* ptr = &i; - int* n = nullptr; - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(&i, ptr, nullptr, ptr + 1, n))); -} - -TEST(HashValueTest, PointerAlignment) { - // We want to make sure that pointer alignment will not cause bits to be - // stuck. - - constexpr size_t kTotalSize = 1 << 20; - std::unique_ptr<char[]> data(new char[kTotalSize]); - constexpr size_t kLog2NumValues = 5; - constexpr size_t kNumValues = 1 << kLog2NumValues; - - for (size_t align = 1; align < kTotalSize / kNumValues; - align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) { - SCOPED_TRACE(align); - ASSERT_LE(align * kNumValues, kTotalSize); - - size_t bits_or = 0; - size_t bits_and = ~size_t{}; - - for (size_t i = 0; i < kNumValues; ++i) { - size_t hash = absl::Hash<void*>()(data.get() + i * align); - bits_or |= hash; - bits_and &= hash; - } - - // Limit the scope to the bits we would be using for Swisstable. - constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1; - size_t stuck_bits = (~bits_or | bits_and) & kMask; - EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits; - } -} - -TEST(HashValueTest, PairAndTuple) { - EXPECT_TRUE((is_hashable<std::pair<int, int>>::value)); - EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value)); - EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value)); - EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0), - std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42)))); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42), - std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0), - std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9), - std::make_tuple(0, 0, -42)))); - - // Test that tuples of lvalue references work (so we need a few lvalues): - int a = 0, b = 1, c = 17, d = 23; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d)))); - - // Test that tuples of rvalue references work: - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42), - std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0), - std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9), - std::forward_as_tuple(0, 0, -42)))); -} - -TEST(HashValueTest, CombineContiguousWorks) { - std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)}; - std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)}; - - auto vh1 = SpyHash(v1); - auto vh2 = SpyHash(v2); - EXPECT_NE(vh1, vh2); -} - -struct DummyDeleter { - template <typename T> - void operator() (T* ptr) {} -}; - -struct SmartPointerEq { - template <typename T, typename U> - bool operator()(const T& t, const U& u) const { - return GetPtr(t) == GetPtr(u); - } - - template <typename T> - static auto GetPtr(const T& t) -> decltype(&*t) { - return t ? &*t : nullptr; - } - - static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; } -}; - -TEST(HashValueTest, SmartPointers) { - EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value)); - EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value)); - EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value)); - - int i, j; - std::unique_ptr<int, DummyDeleter> unique1(&i); - std::unique_ptr<int, DummyDeleter> unique2(&i); - std::unique_ptr<int, DummyDeleter> unique_other(&j); - std::unique_ptr<int, DummyDeleter> unique_null; - - std::shared_ptr<int> shared1(&i, DummyDeleter()); - std::shared_ptr<int> shared2(&i, DummyDeleter()); - std::shared_ptr<int> shared_other(&j, DummyDeleter()); - std::shared_ptr<int> shared_null; - - // Sanity check of the Eq function. - ASSERT_TRUE(SmartPointerEq{}(unique1, shared1)); - ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other)); - ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr)); - ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::forward_as_tuple(&i, nullptr, // - unique1, unique2, unique_null, // - absl::make_unique<int>(), // - shared1, shared2, shared_null, // - std::make_shared<int>()), - SmartPointerEq{})); -} - -TEST(HashValueTest, FunctionPointer) { - using Func = int (*)(); - EXPECT_TRUE(is_hashable<Func>::value); - - Func p1 = [] { return 2; }, p2 = [] { return 1; }; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(p1, p2, nullptr))); -} - -struct WrapInTuple { - template <typename T> - std::tuple<int, T, size_t> operator()(const T& t) const { - return std::make_tuple(7, t, 0xdeadbeef); - } -}; - -absl::Cord FlatCord(absl::string_view sv) { - absl::Cord c(sv); - c.Flatten(); - return c; -} - -absl::Cord FragmentedCord(absl::string_view sv) { - if (sv.size() < 2) { - return absl::Cord(sv); - } - size_t halfway = sv.size() / 2; - std::vector<absl::string_view> parts = {sv.substr(0, halfway), - sv.substr(halfway)}; - return absl::MakeFragmentedCord(parts); -} - -TEST(HashValueTest, Strings) { - EXPECT_TRUE((is_hashable<std::string>::value)); - - const std::string small = "foo"; - const std::string dup = "foofoo"; - const std::string large = std::string(2048, 'x'); // multiple of chunk size - const std::string huge = std::string(5000, 'a'); // not a multiple - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( // - std::string(), absl::string_view(), absl::Cord(), // - std::string(""), absl::string_view(""), absl::Cord(""), // - std::string(small), absl::string_view(small), absl::Cord(small), // - std::string(dup), absl::string_view(dup), absl::Cord(dup), // - std::string(large), absl::string_view(large), absl::Cord(large), // - std::string(huge), absl::string_view(huge), FlatCord(huge), // - FragmentedCord(huge)))); - - // Also check that nested types maintain the same hash. - const WrapInTuple t{}; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( // - t(std::string()), t(absl::string_view()), t(absl::Cord()), // - t(std::string("")), t(absl::string_view("")), t(absl::Cord("")), // - t(std::string(small)), t(absl::string_view(small)), // - t(absl::Cord(small)), // - t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)), // - t(std::string(large)), t(absl::string_view(large)), // - t(absl::Cord(large)), // - t(std::string(huge)), t(absl::string_view(huge)), // - t(FlatCord(huge)), t(FragmentedCord(huge))))); - - // Make sure that hashing a `const char*` does not use its string-value. - EXPECT_NE(SpyHash(static_cast<const char*>("ABC")), - SpyHash(absl::string_view("ABC"))); -} - -TEST(HashValueTest, WString) { - EXPECT_TRUE((is_hashable<std::wstring>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"), - std::wstring(L"Some other different string"), - std::wstring(L"Iñtërnâtiônàlizætiøn")))); -} - -TEST(HashValueTest, U16String) { - EXPECT_TRUE((is_hashable<std::u16string>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"), - std::u16string(u"Some other different string"), - std::u16string(u"Iñtërnâtiônàlizætiøn")))); -} - -TEST(HashValueTest, U32String) { - EXPECT_TRUE((is_hashable<std::u32string>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"), - std::u32string(U"Some other different string"), - std::u32string(U"Iñtërnâtiônàlizætiøn")))); -} - -TEST(HashValueTest, StdArray) { - EXPECT_TRUE((is_hashable<std::array<int, 3>>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}}))); -} - -TEST(HashValueTest, StdBitset) { - EXPECT_TRUE((is_hashable<std::bitset<257>>::value)); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"), - std::bitset<2>("11")})); - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()})); - - constexpr int kNumBits = 256; - std::array<std::string, 6> bit_strings; - bit_strings.fill(std::string(kNumBits, '1')); - bit_strings[1][0] = '0'; - bit_strings[2][1] = '0'; - bit_strings[3][kNumBits / 3] = '0'; - bit_strings[4][kNumBits - 2] = '0'; - bit_strings[5][kNumBits - 1] = '0'; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {std::bitset<kNumBits>(bit_strings[0].c_str()), - std::bitset<kNumBits>(bit_strings[1].c_str()), - std::bitset<kNumBits>(bit_strings[2].c_str()), - std::bitset<kNumBits>(bit_strings[3].c_str()), - std::bitset<kNumBits>(bit_strings[4].c_str()), - std::bitset<kNumBits>(bit_strings[5].c_str())})); -} // namespace - -template <typename T> -class HashValueSequenceTest : public testing::Test { -}; -TYPED_TEST_SUITE_P(HashValueSequenceTest); - -TYPED_TEST_P(HashValueSequenceTest, BasicUsage) { - EXPECT_TRUE((is_hashable<TypeParam>::value)); - - using ValueType = typename TypeParam::value_type; - auto a = static_cast<ValueType>(0); - auto b = static_cast<ValueType>(23); - auto c = static_cast<ValueType>(42); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(TypeParam(), TypeParam{}, TypeParam{a, b, c}, - TypeParam{a, b}, TypeParam{b, c}))); -} - -REGISTER_TYPED_TEST_CASE_P(HashValueSequenceTest, BasicUsage); -using IntSequenceTypes = - testing::Types<std::deque<int>, std::forward_list<int>, std::list<int>, - std::vector<int>, std::vector<bool>, std::set<int>, - std::multiset<int>>; -INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes); - -// Private type that only supports AbslHashValue to make sure our chosen hash -// implementation is recursive within absl::Hash. -// It uses std::abs() on the value to provide different bitwise representations -// of the same logical value. -struct Private { - int i; - template <typename H> - friend H AbslHashValue(H h, Private p) { - return H::combine(std::move(h), std::abs(p.i)); - } - - friend bool operator==(Private a, Private b) { - return std::abs(a.i) == std::abs(b.i); - } - - friend std::ostream& operator<<(std::ostream& o, Private p) { - return o << p.i; - } -}; - -// Test helper for combine_piecewise_buffer. It holds a string_view to the -// buffer-to-be-hashed. Its AbslHashValue specialization will split up its -// contents at the character offsets requested. -class PiecewiseHashTester { - public: - // Create a hash view of a buffer to be hashed contiguously. - explicit PiecewiseHashTester(absl::string_view buf) - : buf_(buf), piecewise_(false), split_locations_() {} - - // Create a hash view of a buffer to be hashed piecewise, with breaks at the - // given locations. - PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations) - : buf_(buf), - piecewise_(true), - split_locations_(std::move(split_locations)) {} - - template <typename H> - friend H AbslHashValue(H h, const PiecewiseHashTester& p) { - if (!p.piecewise_) { - return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size()); - } - absl::hash_internal::PiecewiseCombiner combiner; - if (p.split_locations_.empty()) { - h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size()); - return combiner.finalize(std::move(h)); - } - size_t begin = 0; - for (size_t next : p.split_locations_) { - absl::string_view chunk = p.buf_.substr(begin, next - begin); - h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size()); - begin = next; - } - absl::string_view last_chunk = p.buf_.substr(begin); - if (!last_chunk.empty()) { - h = combiner.add_buffer(std::move(h), last_chunk.data(), - last_chunk.size()); - } - return combiner.finalize(std::move(h)); - } - - private: - absl::string_view buf_; - bool piecewise_; - std::set<size_t> split_locations_; -}; - -// Dummy object that hashes as two distinct contiguous buffers, "foo" followed -// by "bar" -struct DummyFooBar { - template <typename H> - friend H AbslHashValue(H h, const DummyFooBar&) { - const char* foo = "foo"; - const char* bar = "bar"; - h = H::combine_contiguous(std::move(h), foo, 3); - h = H::combine_contiguous(std::move(h), bar, 3); - return h; - } -}; - -TEST(HashValueTest, CombinePiecewiseBuffer) { - absl::Hash<PiecewiseHashTester> hash; - - // Check that hashing an empty buffer through the piecewise API works. - EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {}))); - - // Similarly, small buffers should give consistent results - EXPECT_EQ(hash(PiecewiseHashTester("foobar")), - hash(PiecewiseHashTester("foobar", {}))); - EXPECT_EQ(hash(PiecewiseHashTester("foobar")), - hash(PiecewiseHashTester("foobar", {3}))); - - // But hashing "foobar" in pieces gives a different answer than hashing "foo" - // contiguously, then "bar" contiguously. - EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})), - absl::Hash<DummyFooBar>()(DummyFooBar{})); - - // Test hashing a large buffer incrementally, broken up in several different - // ways. Arrange for breaks on and near the stride boundaries to look for - // off-by-one errors in the implementation. - // - // This test is run on a buffer that is a multiple of the stride size, and one - // that isn't. - for (size_t big_buffer_size : {1024 * 2 + 512, 1024 * 3}) { - SCOPED_TRACE(big_buffer_size); - std::string big_buffer; - for (int i = 0; i < big_buffer_size; ++i) { - // Arbitrary string - big_buffer.push_back(32 + (i * (i / 3)) % 64); - } - auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer)); - - const int possible_breaks = 9; - size_t breaks[possible_breaks] = {1, 512, 1023, 1024, 1025, - 1536, 2047, 2048, 2049}; - for (unsigned test_mask = 0; test_mask < (1u << possible_breaks); - ++test_mask) { - SCOPED_TRACE(test_mask); - std::set<size_t> break_locations; - for (int j = 0; j < possible_breaks; ++j) { - if (test_mask & (1u << j)) { - break_locations.insert(breaks[j]); - } - } - EXPECT_EQ( - hash(PiecewiseHashTester(big_buffer, std::move(break_locations))), - big_buffer_hash); - } - } -} - -TEST(HashValueTest, PrivateSanity) { - // Sanity check that Private is working as the tests below expect it to work. - EXPECT_TRUE(is_hashable<Private>::value); - EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1})); - EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1})); -} - -TEST(HashValueTest, Optional) { - EXPECT_TRUE(is_hashable<absl::optional<Private>>::value); - - using O = absl::optional<Private>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}}))); -} - -TEST(HashValueTest, Variant) { - using V = absl::variant<Private, std::string>; - EXPECT_TRUE(is_hashable<V>::value); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD")))); - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - struct S {}; - EXPECT_FALSE(is_hashable<absl::variant<S>>::value); -#endif -} - -TEST(HashValueTest, Maps) { - EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value)); - - using M = std::map<int, std::string>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - M{}, M{{0, "foo"}}, M{{1, "foo"}}, M{{0, "bar"}}, M{{1, "bar"}}, - M{{0, "foo"}, {42, "bar"}}, M{{1, "foo"}, {42, "bar"}}, - M{{1, "foo"}, {43, "bar"}}, M{{1, "foo"}, {43, "baz"}}))); - - using MM = std::multimap<int, std::string>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - MM{}, MM{{0, "foo"}}, MM{{1, "foo"}}, MM{{0, "bar"}}, MM{{1, "bar"}}, - MM{{0, "foo"}, {0, "bar"}}, MM{{0, "bar"}, {0, "foo"}}, - MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}}, - MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}}))); -} - -TEST(HashValueTest, ReferenceWrapper) { - EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value); - - Private p1{1}, p10{10}; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10)))); - - EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value); - int one = 1, ten = 10; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( - one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten)))); - - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)), - std::tuple<std::reference_wrapper<int>>(std::ref(ten)), - std::tuple<int>(one), std::tuple<int>(ten)))); -} - -template <typename T, typename = void> -struct IsHashCallable : std::false_type {}; - -template <typename T> -struct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()( - std::declval<const T&>()))>> : std::true_type {}; - -template <typename T, typename = void> -struct IsAggregateInitializable : std::false_type {}; - -template <typename T> -struct IsAggregateInitializable<T, absl::void_t<decltype(T{})>> - : std::true_type {}; - -TEST(IsHashableTest, ValidHash) { - EXPECT_TRUE((is_hashable<int>::value)); - EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value); - EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value); - EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value); - EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value); - EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value); - EXPECT_TRUE(IsHashCallable<int>::value); - EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value); -} - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -TEST(IsHashableTest, PoisonHash) { - struct X {}; - EXPECT_FALSE((is_hashable<X>::value)); - EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value); - EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value); - EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value); - EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value); - EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value); - EXPECT_FALSE(IsHashCallable<X>::value); -#if !defined(__GNUC__) || __GNUC__ < 9 - // This doesn't compile on GCC 9. - EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value); -#endif -} -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - -// Hashable types -// -// These types exist simply to exercise various AbslHashValue behaviors, so -// they are named by what their AbslHashValue overload does. -struct NoOp { - template <typename HashCode> - friend HashCode AbslHashValue(HashCode h, NoOp n) { - return h; - } -}; - -struct EmptyCombine { - template <typename HashCode> - friend HashCode AbslHashValue(HashCode h, EmptyCombine e) { - return HashCode::combine(std::move(h)); - } -}; - -template <typename Int> -struct CombineIterative { - template <typename HashCode> - friend HashCode AbslHashValue(HashCode h, CombineIterative c) { - for (int i = 0; i < 5; ++i) { - h = HashCode::combine(std::move(h), Int(i)); - } - return h; - } -}; - -template <typename Int> -struct CombineVariadic { - template <typename HashCode> - friend HashCode AbslHashValue(HashCode h, CombineVariadic c) { - return HashCode::combine(std::move(h), Int(0), Int(1), Int(2), Int(3), - Int(4)); - } -}; -enum class InvokeTag { - kUniquelyRepresented, - kHashValue, -#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ - kLegacyHash, -#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ - kStdHash, - kNone -}; - -template <InvokeTag T> -using InvokeTagConstant = std::integral_constant<InvokeTag, T>; - -template <InvokeTag... Tags> -struct MinTag; - -template <InvokeTag a, InvokeTag b, InvokeTag... Tags> -struct MinTag<a, b, Tags...> : MinTag<(a < b ? a : b), Tags...> {}; - -template <InvokeTag a> -struct MinTag<a> : InvokeTagConstant<a> {}; - -template <InvokeTag... Tags> -struct CustomHashType { - explicit CustomHashType(size_t val) : value(val) {} - size_t value; -}; - -template <InvokeTag allowed, InvokeTag... tags> -struct EnableIfContained - : std::enable_if<absl::disjunction< - std::integral_constant<bool, allowed == tags>...>::value> {}; - -template < - typename H, InvokeTag... Tags, - typename = typename EnableIfContained<InvokeTag::kHashValue, Tags...>::type> -H AbslHashValue(H state, CustomHashType<Tags...> t) { - static_assert(MinTag<Tags...>::value == InvokeTag::kHashValue, ""); - return H::combine(std::move(state), - t.value + static_cast<int>(InvokeTag::kHashValue)); -} - -} // namespace - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { -template <InvokeTag... Tags> -struct is_uniquely_represented< - CustomHashType<Tags...>, - typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type> - : std::true_type {}; -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl - -#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ -namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE { -template <InvokeTag... Tags> -struct hash<CustomHashType<Tags...>> { - template <InvokeTag... TagsIn, typename = typename EnableIfContained< - InvokeTag::kLegacyHash, TagsIn...>::type> - size_t operator()(CustomHashType<TagsIn...> t) const { - static_assert(MinTag<Tags...>::value == InvokeTag::kLegacyHash, ""); - return t.value + static_cast<int>(InvokeTag::kLegacyHash); - } -}; -} // namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE -#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ - -namespace std { -template <InvokeTag... Tags> // NOLINT -struct hash<CustomHashType<Tags...>> { - template <InvokeTag... TagsIn, typename = typename EnableIfContained< - InvokeTag::kStdHash, TagsIn...>::type> - size_t operator()(CustomHashType<TagsIn...> t) const { - static_assert(MinTag<Tags...>::value == InvokeTag::kStdHash, ""); - return t.value + static_cast<int>(InvokeTag::kStdHash); - } -}; -} // namespace std - -namespace { - -template <typename... T> -void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) { - using type = CustomHashType<T::value...>; - SCOPED_TRACE(testing::PrintToString(std::vector<InvokeTag>{T::value...})); - EXPECT_TRUE(is_hashable<type>()); - EXPECT_TRUE(is_hashable<const type>()); - EXPECT_TRUE(is_hashable<const type&>()); - - const size_t offset = static_cast<int>(std::min({T::value...})); - EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset})); -} - -void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) { -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - // is_hashable is false if we don't support any of the hooks. - using type = CustomHashType<>; - EXPECT_FALSE(is_hashable<type>()); - EXPECT_FALSE(is_hashable<const type>()); - EXPECT_FALSE(is_hashable<const type&>()); -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -} - -template <InvokeTag Tag, typename... T> -void TestCustomHashType(InvokeTagConstant<Tag> tag, T... t) { - constexpr auto next = static_cast<InvokeTag>(static_cast<int>(Tag) + 1); - TestCustomHashType(InvokeTagConstant<next>(), tag, t...); - TestCustomHashType(InvokeTagConstant<next>(), t...); -} - -TEST(HashTest, CustomHashType) { - TestCustomHashType(InvokeTagConstant<InvokeTag{}>()); -} - -TEST(HashTest, NoOpsAreEquivalent) { - EXPECT_EQ(Hash<NoOp>()({}), Hash<NoOp>()({})); - EXPECT_EQ(Hash<NoOp>()({}), Hash<EmptyCombine>()({})); -} - -template <typename T> -class HashIntTest : public testing::Test { -}; -TYPED_TEST_SUITE_P(HashIntTest); - -TYPED_TEST_P(HashIntTest, BasicUsage) { - EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0)); - EXPECT_NE(Hash<NoOp>()({}), - Hash<TypeParam>()(std::numeric_limits<TypeParam>::max())); - if (std::numeric_limits<TypeParam>::min() != 0) { - EXPECT_NE(Hash<NoOp>()({}), - Hash<TypeParam>()(std::numeric_limits<TypeParam>::min())); - } - - EXPECT_EQ(Hash<CombineIterative<TypeParam>>()({}), - Hash<CombineVariadic<TypeParam>>()({})); -} - -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>; -INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes); - -struct StructWithPadding { - char c; - int i; - - template <typename H> - friend H AbslHashValue(H hash_state, const StructWithPadding& s) { - return H::combine(std::move(hash_state), s.c, s.i); - } -}; - -static_assert(sizeof(StructWithPadding) > sizeof(char) + sizeof(int), - "StructWithPadding doesn't have padding"); -static_assert(std::is_standard_layout<StructWithPadding>::value, ""); - -// This check has to be disabled because libstdc++ doesn't support it. -// static_assert(std::is_trivially_constructible<StructWithPadding>::value, ""); - -template <typename T> -struct ArraySlice { - T* begin; - T* end; - - template <typename H> - friend H AbslHashValue(H hash_state, const ArraySlice& slice) { - for (auto t = slice.begin; t != slice.end; ++t) { - hash_state = H::combine(std::move(hash_state), *t); - } - return hash_state; - } -}; - -TEST(HashTest, HashNonUniquelyRepresentedType) { - // Create equal StructWithPadding objects that are known to have non-equal - // padding bytes. - static const size_t kNumStructs = 10; - unsigned char buffer1[kNumStructs * sizeof(StructWithPadding)]; - std::memset(buffer1, 0, sizeof(buffer1)); - auto* s1 = reinterpret_cast<StructWithPadding*>(buffer1); - - unsigned char buffer2[kNumStructs * sizeof(StructWithPadding)]; - std::memset(buffer2, 255, sizeof(buffer2)); - auto* s2 = reinterpret_cast<StructWithPadding*>(buffer2); - for (int i = 0; i < kNumStructs; ++i) { - SCOPED_TRACE(i); - s1[i].c = s2[i].c = '0' + i; - s1[i].i = s2[i].i = i; - ASSERT_FALSE(memcmp(buffer1 + i * sizeof(StructWithPadding), - buffer2 + i * sizeof(StructWithPadding), - sizeof(StructWithPadding)) == 0) - << "Bug in test code: objects do not have unequal" - << " object representations"; - } - - EXPECT_EQ(Hash<StructWithPadding>()(s1[0]), Hash<StructWithPadding>()(s2[0])); - EXPECT_EQ(Hash<ArraySlice<StructWithPadding>>()({s1, s1 + kNumStructs}), - Hash<ArraySlice<StructWithPadding>>()({s2, s2 + kNumStructs})); -} - -TEST(HashTest, StandardHashContainerUsage) { - std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"}, - {42, "bar"}}; - - EXPECT_NE(map.find(0), map.end()); - EXPECT_EQ(map.find(1), map.end()); - EXPECT_NE(map.find(0u), map.end()); -} - -struct ConvertibleFromNoOp { - ConvertibleFromNoOp(NoOp) {} // NOLINT(runtime/explicit) - - template <typename H> - friend H AbslHashValue(H hash_state, ConvertibleFromNoOp) { - return H::combine(std::move(hash_state), 1); - } -}; - -TEST(HashTest, HeterogeneousCall) { - EXPECT_NE(Hash<ConvertibleFromNoOp>()(NoOp()), - Hash<NoOp>()(NoOp())); -} - -TEST(IsUniquelyRepresentedTest, SanityTest) { - using absl::hash_internal::is_uniquely_represented; - - EXPECT_TRUE(is_uniquely_represented<unsigned char>::value); - EXPECT_TRUE(is_uniquely_represented<int>::value); - EXPECT_FALSE(is_uniquely_represented<bool>::value); - EXPECT_FALSE(is_uniquely_represented<int*>::value); -} - -struct IntAndString { - int i; - std::string s; - - template <typename H> - friend H AbslHashValue(H hash_state, IntAndString int_and_string) { - return H::combine(std::move(hash_state), int_and_string.s, - int_and_string.i); - } -}; - -TEST(HashTest, SmallValueOn64ByteBoundary) { - Hash<IntAndString>()(IntAndString{0, std::string(63, '0')}); -} - -struct TypeErased { - size_t n; - - template <typename H> - friend H AbslHashValue(H hash_state, const TypeErased& v) { - v.HashValue(absl::HashState::Create(&hash_state)); - return hash_state; - } - - void HashValue(absl::HashState state) const { - absl::HashState::combine(std::move(state), n); - } -}; - -TEST(HashTest, TypeErased) { - EXPECT_TRUE((is_hashable<TypeErased>::value)); - EXPECT_TRUE((is_hashable<std::pair<TypeErased, int>>::value)); - - EXPECT_EQ(SpyHash(TypeErased{7}), SpyHash(size_t{7})); - EXPECT_NE(SpyHash(TypeErased{7}), SpyHash(size_t{13})); - - EXPECT_EQ(SpyHash(std::make_pair(TypeErased{7}, 17)), - SpyHash(std::make_pair(size_t{7}, 17))); -} - -struct ValueWithBoolConversion { - operator bool() const { return false; } - int i; -}; - -} // namespace -namespace std { -template <> -struct hash<ValueWithBoolConversion> { - size_t operator()(ValueWithBoolConversion v) { return v.i; } -}; -} // namespace std - -namespace { - -TEST(HashTest, DoesNotUseImplicitConversionsToBool) { - EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}), - absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1})); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/hash/hash_testing.h b/third_party/abseil_cpp/absl/hash/hash_testing.h deleted file mode 100644 index 1e1c5741491e..000000000000 --- a/third_party/abseil_cpp/absl/hash/hash_testing.h +++ /dev/null @@ -1,378 +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. - -#ifndef ABSL_HASH_HASH_TESTING_H_ -#define ABSL_HASH_HASH_TESTING_H_ - -#include <initializer_list> -#include <tuple> -#include <type_traits> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/hash/internal/spy_hash_state.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/str_cat.h" -#include "absl/types/variant.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Run the absl::Hash algorithm over all the elements passed in and verify that -// their hash expansion is congruent with their `==` operator. -// -// It is used in conjunction with EXPECT_TRUE. Failures will output information -// on what requirement failed and on which objects. -// -// Users should pass a collection of types as either an initializer list or a -// container of cases. -// -// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( -// {v1, v2, ..., vN})); -// -// std::vector<MyType> cases; -// // Fill cases... -// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases)); -// -// Users can pass a variety of types for testing heterogeneous lookup with -// `std::make_tuple`: -// -// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( -// std::make_tuple(v1, v2, ..., vN))); -// -// -// Ideally, the values passed should provide enough coverage of the `==` -// operator and the AbslHashValue implementations. -// For dynamically sized types, the empty state should usually be included in -// the values. -// -// The function accepts an optional comparator function, in case that `==` is -// not enough for the values provided. -// -// Usage: -// -// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( -// std::make_tuple(v1, v2, ..., vN), MyCustomEq{})); -// -// It checks the following requirements: -// 1. The expansion for a value is deterministic. -// 2. For any two objects `a` and `b` in the sequence, if `a == b` evaluates -// to true, then their hash expansion must be equal. -// 3. If `a == b` evaluates to false their hash expansion must be unequal. -// 4. If `a == b` evaluates to false neither hash expansion can be a -// suffix of the other. -// 5. AbslHashValue overloads should not be called by the user. They are only -// meant to be called by the framework. Users should call H::combine() and -// H::combine_contiguous(). -// 6. No moved-from instance of the hash state is used in the implementation -// of AbslHashValue. -// -// The values do not have to have the same type. This can be useful for -// equivalent types that support heterogeneous lookup. -// -// A possible reason for breaking (2) is combining state in the hash expansion -// that was not used in `==`. -// For example: -// -// struct Bad2 { -// int a, b; -// template <typename H> -// friend H AbslHashValue(H state, Bad2 x) { -// // Uses a and b. -// return H::combine(std::move(state), x.a, x.b); -// } -// friend bool operator==(Bad2 x, Bad2 y) { -// // Only uses a. -// return x.a == y.a; -// } -// }; -// -// As for (3), breaking this usually means that there is state being passed to -// the `==` operator that is not used in the hash expansion. -// For example: -// -// struct Bad3 { -// int a, b; -// template <typename H> -// friend H AbslHashValue(H state, Bad3 x) { -// // Only uses a. -// return H::combine(std::move(state), x.a); -// } -// friend bool operator==(Bad3 x, Bad3 y) { -// // Uses a and b. -// return x.a == y.a && x.b == y.b; -// } -// }; -// -// Finally, a common way to break 4 is by combining dynamic ranges without -// combining the size of the range. -// For example: -// -// struct Bad4 { -// int *p, size; -// template <typename H> -// friend H AbslHashValue(H state, Bad4 x) { -// return H::combine_contiguous(std::move(state), x.p, x.p + x.size); -// } -// friend bool operator==(Bad4 x, Bad4 y) { -// // Compare two ranges for equality. C++14 code can instead use std::equal. -// return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size); -// } -// }; -// -// An easy solution to this is to combine the size after combining the range, -// like so: -// template <typename H> -// friend H AbslHashValue(H state, Bad4 x) { -// return H::combine( -// H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size); -// } -// -template <int&... ExplicitBarrier, typename Container> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(const Container& values); - -template <int&... ExplicitBarrier, typename Container, typename Eq> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals); - -template <int&..., typename T> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values); - -template <int&..., typename T, typename Eq> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values, - Eq equals); - -namespace hash_internal { - -struct PrintVisitor { - size_t index; - template <typename T> - std::string operator()(const T* value) const { - return absl::StrCat("#", index, "(", testing::PrintToString(*value), ")"); - } -}; - -template <typename Eq> -struct EqVisitor { - Eq eq; - template <typename T, typename U> - bool operator()(const T* t, const U* u) const { - return eq(*t, *u); - } -}; - -struct ExpandVisitor { - template <typename T> - SpyHashState operator()(const T* value) const { - return SpyHashState::combine(SpyHashState(), *value); - } -}; - -template <typename Container, typename Eq> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) { - using V = typename Container::value_type; - - struct Info { - const V& value; - size_t index; - std::string ToString() const { - return absl::visit(PrintVisitor{index}, value); - } - SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); } - }; - - using EqClass = std::vector<Info>; - std::vector<EqClass> classes; - - // Gather the values in equivalence classes. - size_t i = 0; - for (const auto& value : values) { - EqClass* c = nullptr; - for (auto& eqclass : classes) { - if (absl::visit(EqVisitor<Eq>{equals}, value, eqclass[0].value)) { - c = &eqclass; - break; - } - } - if (c == nullptr) { - classes.emplace_back(); - c = &classes.back(); - } - c->push_back({value, i}); - ++i; - - // Verify potential errors captured by SpyHashState. - if (auto error = c->back().expand().error()) { - return testing::AssertionFailure() << *error; - } - } - - if (classes.size() < 2) { - return testing::AssertionFailure() - << "At least two equivalence classes are expected."; - } - - // We assume that equality is correctly implemented. - // Now we verify that AbslHashValue is also correctly implemented. - - for (const auto& c : classes) { - // All elements of the equivalence class must have the same hash - // expansion. - const SpyHashState expected = c[0].expand(); - for (const Info& v : c) { - if (v.expand() != v.expand()) { - return testing::AssertionFailure() - << "Hash expansion for " << v.ToString() - << " is non-deterministic."; - } - if (v.expand() != expected) { - return testing::AssertionFailure() - << "Values " << c[0].ToString() << " and " << v.ToString() - << " evaluate as equal but have an unequal hash expansion."; - } - } - - // Elements from other classes must have different hash expansion. - for (const auto& c2 : classes) { - if (&c == &c2) continue; - const SpyHashState c2_hash = c2[0].expand(); - switch (SpyHashState::Compare(expected, c2_hash)) { - case SpyHashState::CompareResult::kEqual: - return testing::AssertionFailure() - << "Values " << c[0].ToString() << " and " << c2[0].ToString() - << " evaluate as unequal but have an equal hash expansion."; - case SpyHashState::CompareResult::kBSuffixA: - return testing::AssertionFailure() - << "Hash expansion of " << c2[0].ToString() - << " is a suffix of the hash expansion of " << c[0].ToString() - << "."; - case SpyHashState::CompareResult::kASuffixB: - return testing::AssertionFailure() - << "Hash expansion of " << c[0].ToString() - << " is a suffix of the hash expansion of " << c2[0].ToString() - << "."; - case SpyHashState::CompareResult::kUnequal: - break; - } - } - } - return testing::AssertionSuccess(); -} - -template <typename... T> -struct TypeSet { - template <typename U, bool = disjunction<std::is_same<T, U>...>::value> - struct Insert { - using type = TypeSet<U, T...>; - }; - template <typename U> - struct Insert<U, true> { - using type = TypeSet; - }; - - template <template <typename...> class C> - using apply = C<T...>; -}; - -template <typename... T> -struct MakeTypeSet : TypeSet<> {}; -template <typename T, typename... Ts> -struct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {}; - -template <typename... T> -using VariantForTypes = typename MakeTypeSet< - const typename std::decay<T>::type*...>::template apply<absl::variant>; - -template <typename Container> -struct ContainerAsVector { - using V = absl::variant<const typename Container::value_type*>; - using Out = std::vector<V>; - - static Out Do(const Container& values) { - Out out; - for (const auto& v : values) out.push_back(&v); - return out; - } -}; - -template <typename... T> -struct ContainerAsVector<std::tuple<T...>> { - using V = VariantForTypes<T...>; - using Out = std::vector<V>; - - template <size_t... I> - static Out DoImpl(const std::tuple<T...>& tuple, absl::index_sequence<I...>) { - return Out{&std::get<I>(tuple)...}; - } - - static Out Do(const std::tuple<T...>& values) { - return DoImpl(values, absl::index_sequence_for<T...>()); - } -}; - -template <> -struct ContainerAsVector<std::tuple<>> { - static std::vector<VariantForTypes<int>> Do(std::tuple<>) { return {}; } -}; - -struct DefaultEquals { - template <typename T, typename U> - bool operator()(const T& t, const U& u) const { - return t == u; - } -}; - -} // namespace hash_internal - -template <int&..., typename Container> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(const Container& values) { - return hash_internal::VerifyTypeImplementsAbslHashCorrectly( - hash_internal::ContainerAsVector<Container>::Do(values), - hash_internal::DefaultEquals{}); -} - -template <int&..., typename Container, typename Eq> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) { - return hash_internal::VerifyTypeImplementsAbslHashCorrectly( - hash_internal::ContainerAsVector<Container>::Do(values), equals); -} - -template <int&..., typename T> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values) { - return hash_internal::VerifyTypeImplementsAbslHashCorrectly( - hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values), - hash_internal::DefaultEquals{}); -} - -template <int&..., typename T, typename Eq> -ABSL_MUST_USE_RESULT testing::AssertionResult -VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values, - Eq equals) { - return hash_internal::VerifyTypeImplementsAbslHashCorrectly( - hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values), - equals); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HASH_HASH_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/hash/internal/city.cc b/third_party/abseil_cpp/absl/hash/internal/city.cc deleted file mode 100644 index 5460134e5762..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/city.cc +++ /dev/null @@ -1,349 +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. -// -// This file provides CityHash64() and related functions. -// -// It's probably possible to create even faster hash functions by -// writing a program that systematically explores some of the space of -// possible hash functions, by using SIMD instructions, or by -// compromising on hash quality. - -#include "absl/hash/internal/city.h" - -#include <string.h> // for memcpy and memset -#include <algorithm> - -#include "absl/base/config.h" -#include "absl/base/internal/endian.h" -#include "absl/base/internal/unaligned_access.h" -#include "absl/base/optimization.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { - -#ifdef ABSL_IS_BIG_ENDIAN -#define uint32_in_expected_order(x) (absl::gbswap_32(x)) -#define uint64_in_expected_order(x) (absl::gbswap_64(x)) -#else -#define uint32_in_expected_order(x) (x) -#define uint64_in_expected_order(x) (x) -#endif - -static uint64_t Fetch64(const char *p) { - return uint64_in_expected_order(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); -} - -static uint32_t Fetch32(const char *p) { - return uint32_in_expected_order(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); -} - -// Some primes between 2^63 and 2^64 for various uses. -static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; -static const uint64_t k1 = 0xb492b66fbe98f273ULL; -static const uint64_t k2 = 0x9ae16a3b2f90404fULL; - -// Magic numbers for 32-bit hashing. Copied from Murmur3. -static const uint32_t c1 = 0xcc9e2d51; -static const uint32_t c2 = 0x1b873593; - -// A 32-bit to 32-bit integer hash copied from Murmur3. -static uint32_t fmix(uint32_t h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; -} - -static uint32_t Rotate32(uint32_t val, int shift) { - // Avoid shifting by 32: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); -} - -#undef PERMUTE3 -#define PERMUTE3(a, b, c) \ - do { \ - std::swap(a, b); \ - std::swap(a, c); \ - } while (0) - -static uint32_t Mur(uint32_t a, uint32_t h) { - // Helper from Murmur3 for combining two 32-bit values. - a *= c1; - a = Rotate32(a, 17); - a *= c2; - h ^= a; - h = Rotate32(h, 19); - return h * 5 + 0xe6546b64; -} - -static uint32_t Hash32Len13to24(const char *s, size_t len) { - uint32_t a = Fetch32(s - 4 + (len >> 1)); - uint32_t b = Fetch32(s + 4); - uint32_t c = Fetch32(s + len - 8); - uint32_t d = Fetch32(s + (len >> 1)); - uint32_t e = Fetch32(s); - uint32_t f = Fetch32(s + len - 4); - uint32_t h = len; - - return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); -} - -static uint32_t Hash32Len0to4(const char *s, size_t len) { - uint32_t b = 0; - uint32_t c = 9; - for (size_t i = 0; i < len; i++) { - signed char v = s[i]; - b = b * c1 + v; - c ^= b; - } - return fmix(Mur(b, Mur(len, c))); -} - -static uint32_t Hash32Len5to12(const char *s, size_t len) { - uint32_t a = len, b = len * 5, c = 9, d = b; - a += Fetch32(s); - b += Fetch32(s + len - 4); - c += Fetch32(s + ((len >> 1) & 4)); - return fmix(Mur(c, Mur(b, Mur(a, d)))); -} - -uint32_t CityHash32(const char *s, size_t len) { - if (len <= 24) { - return len <= 12 - ? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) - : Hash32Len13to24(s, len); - } - - // len > 24 - uint32_t h = len, g = c1 * len, f = g; - - uint32_t a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; - uint32_t a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; - uint32_t a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; - uint32_t a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2; - uint32_t a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2; - h ^= a0; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - h ^= a2; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= a1; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - g ^= a3; - g = Rotate32(g, 19); - g = g * 5 + 0xe6546b64; - f += a4; - f = Rotate32(f, 19); - f = f * 5 + 0xe6546b64; - size_t iters = (len - 1) / 20; - do { - uint32_t b0 = Rotate32(Fetch32(s) * c1, 17) * c2; - uint32_t b1 = Fetch32(s + 4); - uint32_t b2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; - uint32_t b3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; - uint32_t b4 = Fetch32(s + 16); - h ^= b0; - h = Rotate32(h, 18); - h = h * 5 + 0xe6546b64; - f += b1; - f = Rotate32(f, 19); - f = f * c1; - g += b2; - g = Rotate32(g, 18); - g = g * 5 + 0xe6546b64; - h ^= b3 + b1; - h = Rotate32(h, 19); - h = h * 5 + 0xe6546b64; - g ^= b4; - g = absl::gbswap_32(g) * 5; - h += b4 * 5; - h = absl::gbswap_32(h); - f += b0; - PERMUTE3(f, h, g); - s += 20; - } while (--iters != 0); - g = Rotate32(g, 11) * c1; - g = Rotate32(g, 17) * c1; - f = Rotate32(f, 11) * c1; - f = Rotate32(f, 17) * c1; - h = Rotate32(h + g, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - h = Rotate32(h + f, 19); - h = h * 5 + 0xe6546b64; - h = Rotate32(h, 17) * c1; - return h; -} - -// Bitwise right rotate. Normally this will compile to a single -// instruction, especially if the shift is a manifest constant. -static uint64_t Rotate(uint64_t val, int shift) { - // Avoid shifting by 64: doing so yields an undefined result. - return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); -} - -static uint64_t ShiftMix(uint64_t val) { return val ^ (val >> 47); } - -static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) { - // Murmur-inspired hashing. - uint64_t a = (u ^ v) * mul; - a ^= (a >> 47); - uint64_t b = (v ^ a) * mul; - b ^= (b >> 47); - b *= 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; - uint64_t a = Fetch64(s) + k2; - uint64_t b = Fetch64(s + len - 8); - uint64_t c = Rotate(b, 37) * mul + a; - uint64_t d = (Rotate(a, 25) + b) * mul; - return HashLen16(c, d, mul); - } - if (len >= 4) { - uint64_t mul = k2 + len * 2; - uint64_t a = Fetch32(s); - return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); - } - if (len > 0) { - uint8_t a = s[0]; - uint8_t b = s[len >> 1]; - uint8_t c = s[len - 1]; - uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8); - uint32_t z = len + (static_cast<uint32_t>(c) << 2); - return ShiftMix(y * k2 ^ z * k0) * k2; - } - return k2; -} - -// This probably works well for 16-byte strings as well, but it may be overkill -// in that case. -static uint64_t HashLen17to32(const char *s, size_t len) { - uint64_t mul = k2 + len * 2; - uint64_t a = Fetch64(s) * k1; - uint64_t b = Fetch64(s + 8); - uint64_t c = Fetch64(s + len - 8) * mul; - uint64_t d = Fetch64(s + len - 16) * k2; - return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, - a + Rotate(b + k2, 18) + c, mul); -} - -// 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) { - a += w; - b = Rotate(b + a + z, 21); - uint64_t c = a; - a += x; - a += y; - b += Rotate(a, 44); - return std::make_pair(a + z, b + c); -} - -// 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) { - return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), - Fetch64(s + 24), a, b); -} - -// Return an 8-byte hash for 33 to 64 bytes. -static uint64_t HashLen33to64(const char *s, size_t len) { - uint64_t mul = k2 + len * 2; - uint64_t a = Fetch64(s) * k2; - uint64_t b = Fetch64(s + 8); - uint64_t c = Fetch64(s + len - 24); - uint64_t d = Fetch64(s + len - 32); - uint64_t e = Fetch64(s + 16) * k2; - uint64_t f = Fetch64(s + 24) * 9; - uint64_t g = Fetch64(s + len - 8); - uint64_t h = Fetch64(s + len - 16) * mul; - uint64_t u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; - uint64_t v = ((a + g) ^ d) + f + 1; - uint64_t w = absl::gbswap_64((u + v) * mul) + h; - uint64_t x = Rotate(e + f, 42) + c; - uint64_t y = (absl::gbswap_64((v + w) * mul) + g) * mul; - uint64_t z = e + f + c; - a = absl::gbswap_64((x + z) * mul + y) + b; - b = ShiftMix((z + a) * mul + d + h) * mul; - return b + x; -} - -uint64_t CityHash64(const char *s, size_t len) { - if (len <= 32) { - if (len <= 16) { - return HashLen0to16(s, len); - } else { - return HashLen17to32(s, len); - } - } else if (len <= 64) { - return HashLen33to64(s, len); - } - - // For strings over 64 bytes we hash the end first, and then as we - // loop we keep 56 bytes of state: v, w, x, y, and z. - 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); - x = x * k1 + Fetch64(s); - - // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - len = (len - 1) & ~static_cast<size_t>(63); - do { - x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; - y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; - x ^= w.second; - y += v.first + Fetch64(s + 40); - z = Rotate(z + w.first, 33) * k1; - v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); - w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); - std::swap(z, x); - s += 64; - len -= 64; - } while (len != 0); - return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, - HashLen16(v.second, w.second) + x); -} - -uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) { - return CityHash64WithSeeds(s, len, k2, seed); -} - -uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0, - uint64_t seed1) { - return HashLen16(CityHash64(s, len) - seed0, seed1); -} - -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/hash/internal/city.h b/third_party/abseil_cpp/absl/hash/internal/city.h deleted file mode 100644 index 393da0b95d9f..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/city.h +++ /dev/null @@ -1,78 +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. -// -// https://code.google.com/p/cityhash/ -// -// This file provides a few functions for hashing strings. All of them are -// high-quality functions in the sense that they pass standard tests such -// as Austin Appleby's SMHasher. They are also fast. -// -// For 64-bit x86 code, on short strings, we don't know of anything faster than -// CityHash64 that is of comparable quality. We believe our nearest competitor -// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash -// tables and most other hashing (excluding cryptography). -// -// For 32-bit x86 code, we don't know of anything faster than CityHash32 that -// is of comparable quality. We believe our nearest competitor is Murmur3A. -// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.) -// -// Functions in the CityHash family are not suitable for cryptography. -// -// Please see CityHash's README file for more details on our performance -// measurements and so on. -// -// WARNING: This code has been only lightly tested on big-endian platforms! -// It is known to work well on little-endian platforms that have a small penalty -// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. -// It should work on all 32-bit and 64-bit platforms that allow unaligned reads; -// bug reports are welcome. -// -// By the way, for some hash functions, given strings a and b, the hash -// of a+b is easily derived from the hashes of a and b. This property -// doesn't hold for any hash functions in this file. - -#ifndef ABSL_HASH_INTERNAL_CITY_H_ -#define ABSL_HASH_INTERNAL_CITY_H_ - -#include <stdint.h> -#include <stdlib.h> // for size_t. - -#include <utility> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { - -// Hash function for a byte array. -uint64_t CityHash64(const char *s, size_t len); - -// Hash function for a byte array. For convenience, a 64-bit seed is also -// hashed into the result. -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); - -// Hash function for a byte array. Most useful in 32-bit binaries. -uint32_t CityHash32(const char *s, size_t len); - -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HASH_INTERNAL_CITY_H_ diff --git a/third_party/abseil_cpp/absl/hash/internal/city_test.cc b/third_party/abseil_cpp/absl/hash/internal/city_test.cc deleted file mode 100644 index 251d381d73e1..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/city_test.cc +++ /dev/null @@ -1,595 +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/hash/internal/city.h" - -#include <string.h> -#include <cstdio> -#include <iostream> -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { - -static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; -static const uint64_t kSeed0 = 1234567; -static const uint64_t kSeed1 = k0; -static const int kDataSize = 1 << 20; -static const int kTestSize = 300; - -static char data[kDataSize]; - -// Initialize data to pseudorandom values. -void setup() { - uint64_t a = 9; - uint64_t b = 777; - for (int i = 0; i < kDataSize; i++) { - a += b; - b += a; - a = (a ^ (a >> 41)) * k0; - b = (b ^ (b >> 41)) * k0 + i; - uint8_t u = b >> 37; - memcpy(data + i, &u, 1); // uint8_t -> char - } -} - -#define C(x) 0x##x##ULL -static const uint64_t testdata[kTestSize][4] = { - {C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766), - C(dc56d17a)}, - {C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a), - C(99929334)}, - {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(4252edb7)}, - {C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30), - C(ebc34f3c)}, - {C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30), - C(26f2b463)}, - {C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da), - C(b042c047)}, - {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(e73bb0a8)}, - {C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af), - C(91dfdd75)}, - {C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e), - C(c87f95de)}, - {C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207), - C(3f5538ef)}, - {C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa), - C(70eb1a1f)}, - {C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67), - C(cfd63b83)}, - {C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1), - C(894a52ef)}, - {C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2), - C(9cde6a54)}, - {C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c), - C(6c4898d5)}, - {C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7), - C(13e1978e)}, - {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(51b4ba8)}, - {C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee), - C(b6b06e40)}, - {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(240a2f2)}, - {C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a), - C(5dcefc30)}, - {C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910), - C(7a48b105)}, - {C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00), - C(fd55007b)}, - {C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59), - C(6b95894c)}, - {C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7), - C(3360e827)}, - {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(45177e0b)}, - {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(7c6fffe4)}, - {C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87), - C(bbc78da4)}, - {C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251), - C(c5c25d39)}, - {C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba), - C(b6e5d06e)}, - {C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f), - C(6178504e)}, - {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(bd4c3637)}, - {C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f), - C(6e7ac474)}, - {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(1fb4b518)}, - {C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2), - C(31d13d6d)}, - {C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54), - C(26fa72e3)}, - {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(6a7433bf)}, - {C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c), - C(4e6df758)}, - {C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5), - C(d57f63ea)}, - {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(52ef73b3)}, - {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(3cb36c3)}, - {C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061), - C(72c39bea)}, - {C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155), - C(a65aa25c)}, - {C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6), - C(74740539)}, - {C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773), - C(c3ae3c26)}, - {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(f29db8a2)}, - {C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540), - C(1ef4cbf4)}, - {C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308), - C(a9be6c41)}, - {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(fa31801)}, - {C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205), - C(8331c5d8)}, - {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(e9876db8)}, - {C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7), - C(27b0604e)}, - {C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc), - C(dcec07f2)}, - {C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a), - C(cff0a82a)}, - {C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab), - C(fec83621)}, - {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(743d8dc)}, - {C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e), - C(64d41d26)}, - {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(acd90c81)}, - {C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f), - C(7c746a4b)}, - {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(b1047e99)}, - {C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5), - C(d1fd1068)}, - {C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97), - C(56486077)}, - {C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23), - C(6069be80)}, - {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(2078359b)}, - {C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0), - C(9ea21004)}, - {C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f), - C(9c9cfe88)}, - {C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9), - C(b70a6ddd)}, - {C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6), - C(dea37298)}, - {C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606), - C(8f480819)}, - {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(30b3b16)}, - {C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f), - C(f31bc4e8)}, - {C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516), - C(419f953b)}, - {C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519), - C(20e9e76d)}, - {C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d), - C(646f0ff8)}, - {C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3), - C(eeb7eca8)}, - {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(8112bb9)}, - {C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e), - C(85a6d477)}, - {C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43), - C(56f76c84)}, - {C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159), - C(9af45d55)}, - {C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db), - C(d1c33760)}, - {C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc), - C(c56bbf69)}, - {C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368), - C(abecfb9b)}, - {C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017), - C(8de13255)}, - {C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7), - C(a98ee299)}, - {C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0), - C(3015f556)}, - {C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7), - C(5a430e29)}, - {C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5), - C(2797add0)}, - {C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c), - C(27d55016)}, - {C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e), - C(84945a82)}, - {C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896), - C(3ef7e224)}, - {C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f), - C(35ed8dc8)}, - {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(6a75e43d)}, - {C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36), - C(235d9805)}, - {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(f7d69572)}, - {C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222), - C(bacd0199)}, - {C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031), - C(e428f50e)}, - {C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361), - C(81eaaad3)}, - {C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d), - C(addbd3e3)}, - {C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f), - C(e66dbca0)}, - {C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9), - C(afe11fd5)}, - {C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164), - C(a71a406f)}, - {C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20), - C(9d90eaf5)}, - {C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460), - C(6665db10)}, - {C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d), - C(9c977cbf)}, - {C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339), - C(ee83ddd4)}, - {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(26519cc)}, - {C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a), - C(a485a53f)}, - {C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524), - C(f62bc412)}, - {C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796), - C(8975a436)}, - {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(94ff7f41)}, - {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(760aa031)}, - {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(3bda76df)}, - {C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae), - C(498e2e65)}, - {C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b), - C(d38deb48)}, - {C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507), - C(82b3fb6b)}, - {C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af), - C(e500e25f)}, - {C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4), - C(bd2bb07c)}, - {C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0), - C(3a2b431d)}, - {C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4), - C(7322a83d)}, - {C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922), - C(a645ca1c)}, - {C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d), - C(8909a45a)}, - {C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88), - C(bd30074c)}, - {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(c17cf001)}, - {C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee), - C(26ffd25a)}, - {C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b), - C(f1d8ce3c)}, - {C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9), - C(3ee8fb17)}, - {C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9), - C(a77acc2a)}, - {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(f4556dee)}, - {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(de287a64)}, - {C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367), - C(878e55b9)}, - {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(7648486)}, - {C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc), - C(57ac0fb1)}, - {C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca), - C(d01967ca)}, - {C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba), - C(96ecdf74)}, - {C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7), - C(779f5506)}, - {C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d), - C(3c94c2de)}, - {C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844), - C(39f98faf)}, - {C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65), - C(7af31199)}, - {C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45), - C(e341a9d6)}, - {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(ca24aeeb)}, - {C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728), - C(b2252b57)}, - {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(72c81da1)}, - {C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1), - C(6b9fce95)}, - {C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7), - C(19399857)}, - {C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2), - C(3c57a994)}, - {C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70), - C(c053e729)}, - {C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f), - C(51cbbba7)}, - {C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731), - C(1acde79a)}, - {C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72), - C(2d160d13)}, - {C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203), - C(787f5801)}, - {C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4), - C(c9629828)}, - {C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891), - C(be139231)}, - {C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4), - C(7df699ef)}, - {C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893), - C(8ce6b96d)}, - {C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d), - C(6f9ed99c)}, - {C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c), - C(e0244796)}, - {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4ccf7e75)}, - {C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b), - C(915cef86)}, - {C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3), - C(5cb59482)}, - {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(6ca3f532)}, - {C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659), - C(e24f3859)}, - {C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f), - C(adf5a9c7)}, - {C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1), - C(32264b75)}, - {C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b), - C(a64b3376)}, - {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(d33890e)}, - {C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66), - C(926d4b63)}, - {C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917), - C(d51ba539)}, - {C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5), - C(7f37636d)}, - {C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630), - C(b98026c0)}, - {C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc), - C(b877767e)}, - {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(aefae77)}, - {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(f686911)}, - {C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a), - C(3deadf12)}, - {C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24), - C(ccf02a4e)}, - {C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef), - C(176c1722)}, - {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(26f82ad)}, - {C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b), - C(b5244f42)}, - {C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a), - C(49a689e5)}, - {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(59fcdd3)}, - {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(4f4b04e9)}, - {C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63), - C(8b00f891)}, - {C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630), - C(16e114f3)}, - {C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394), - C(d6b6dadc)}, - {C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466), - C(897e20ac)}, - {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(f996e05d)}, - {C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f), - C(c4306af6)}, - {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(6dcad433)}, - {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(3c07374d)}, - {C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c), - C(f0f4602c)}, - {C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0), - C(3e1ea071)}, - {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(67580f0c)}, - {C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2), - C(4e109454)}, - {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(88a474a7)}, - {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(5b5bedd)}, - {C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716), - C(1aaddfa7)}, - {C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff), - C(5be07fd8)}, - {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(cbca8606)}, - {C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326), - C(bde64d01)}, - {C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f), - C(ee90cf33)}, - {C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546), - C(4305c3ce)}, - {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(4b3a1d76)}, - {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(a8bb6d80)}, - {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(1f9fa607)}, - {C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9), - C(8d0e4ed2)}, - {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(1bf31347)}, - {C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666), - C(1ae3fc5b)}, - {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(459c3930)}, - {C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7), - C(e00c4184)}, - {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(ffc7a781)}, - {C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374), - C(6a125480)}, - {C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc), - C(88a1512b)}, - {C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4), - C(549bbbe5)}, - {C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453), - C(c133d38c)}, - {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(fcace348)}, - {C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d), - C(ed7b6f9a)}, - {C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3), - C(6d907dda)}, - {C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a), - C(7a4d48d5)}, - {C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40), - C(e686f3db)}, - {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(cce7c55)}, - {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(f58b96b)}, - {C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b), - C(1bbf6f60)}, - {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(ce5e0cc2)}, - {C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55), - C(584cfd6f)}, - {C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6), - C(8f9bbc33)}, - {C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd), - C(d7640d95)}, - {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(3d12a2b)}, - {C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427), - C(aaeafed0)}, - {C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03), - C(95b9b814)}, - {C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c), - C(45fbe66e)}, - {C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e), - C(b4baa7a8)}, - {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(83e962fe)}, - {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(aac3531c)}, - {C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91), - C(2b1db7cc)}, - {C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636), - C(cf00cd31)}, - {C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48), - C(7d3c43b8)}, - {C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af), - C(cbd5fac6)}, - {C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627), - C(76d0fec4)}, - {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(405e3402)}, - {C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4), - C(c732c481)}, - {C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40), - C(a8d123c9)}, - {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(1e80ad7d)}, - {C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6), - C(52aeb863)}, - {C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12), - C(ef7c0c18)}, - {C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb), - C(b6ad4b68)}, - {C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4), - C(c1e46b17)}, - {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(57b8df25)}, - {C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345), - C(e9fa36d6)}, - {C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472), - C(8f8daefc)}, - {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(6e1bb7e)}, - {C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c), - C(fd0076f0)}, - {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(899b17b6)}, - {C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82), - C(e3e84e31)}, - {C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832), - C(eef79b6b)}, - {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(868e3315)}, - {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(4639a426)}, - {C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535), - C(f3213646)}, - {C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559), - C(17f148e9)}, - {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(bfd94880)}, - {C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b), - C(bb1fa7f3)}, - {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(88816b1)}, - {C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d), - C(5c2faeb3)}, - {C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f), - C(51b5fc6f)}, - {C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1), - C(33d94752)}, - {C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207), - C(b0c92948)}, - {C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be), - C(c7171590)}, - {C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4), - C(240a67fb)}, - {C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b), - C(e1843cd5)}, - {C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434), - C(fda1452b)}, - {C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3), - C(a2cad330)}, - {C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480), - C(53467e16)}, - {C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d), - C(da14a8d0)}, - {C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa), - C(67333551)}, - {C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5), - C(a0ebd66e)}, - {C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744), - C(4b769593)}, - {C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9), - C(6aa75624)}, - {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(602a3f96)}, - {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(cd183c4d)}, - {C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5), - C(960a4d07)}, - {C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0), - C(9ae998c4)}, - {C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f), - C(74e2179d)}, - {C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec), - C(ee9bae25)}, - {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(b66edf10)}, - {C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb), - C(d6209737)}, - {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(b994a88)}, - {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(a05d43c0)}, - {C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd), - C(c79f73a8)}, - {C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb), - C(a490aff5)}, - {C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812), - C(dfad65b4)}, - {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(1d07dfb)}, - {C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d), - C(416df9a0)}, - {C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1), - C(1f8fb9cc)}, - {C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1), - C(7abf48e3)}, - {C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d), - C(dea4e3dd)}, - {C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166), - C(c6064f22)}, - {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(743bed9c)}, - {C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc), - C(fce254d5)}, - {C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d), - C(e47ec9d1)}, - {C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165), - C(334a145c)}, - {C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d), - C(adec1e3c)}, - {C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed), - C(f6a9fbf8)}, - {C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5), - C(5398210c)}, -}; - -void TestUnchanging(const uint64_t* expected, int offset, int len) { - EXPECT_EQ(expected[0], CityHash64(data + offset, len)); - EXPECT_EQ(expected[3], CityHash32(data + offset, len)); - EXPECT_EQ(expected[1], CityHash64WithSeed(data + offset, len, kSeed0)); - EXPECT_EQ(expected[2], - CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1)); -} - -TEST(CityHashTest, Unchanging) { - setup(); - int i = 0; - for (; i < kTestSize - 1; i++) { - TestUnchanging(testdata[i], i * i, i); - } - TestUnchanging(testdata[i], 0, kDataSize); -} - -} // 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 deleted file mode 100644 index b44ecb3a6b66..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/hash.cc +++ /dev/null @@ -1,55 +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/hash/internal/hash.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { - -uint64_t CityHashState::CombineLargeContiguousImpl32(uint64_t state, - const unsigned char* first, - size_t len) { - while (len >= PiecewiseChunkSize()) { - state = - Mix(state, absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first), - PiecewiseChunkSize())); - len -= PiecewiseChunkSize(); - first += PiecewiseChunkSize(); - } - // Handle the remainder. - return CombineContiguousImpl(state, first, len, - std::integral_constant<int, 4>{}); -} - -uint64_t CityHashState::CombineLargeContiguousImpl64(uint64_t state, - const unsigned char* first, - size_t len) { - while (len >= PiecewiseChunkSize()) { - state = - Mix(state, absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first), - PiecewiseChunkSize())); - len -= PiecewiseChunkSize(); - first += PiecewiseChunkSize(); - } - // Handle the remainder. - return CombineContiguousImpl(state, first, len, - std::integral_constant<int, 8>{}); -} - -ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed; - -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/hash/internal/hash.h b/third_party/abseil_cpp/absl/hash/internal/hash.h deleted file mode 100644 index b0132da2069d..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/hash.h +++ /dev/null @@ -1,1003 +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: hash.h -// ----------------------------------------------------------------------------- -// -#ifndef ABSL_HASH_INTERNAL_HASH_H_ -#define ABSL_HASH_INTERNAL_HASH_H_ - -#include <algorithm> -#include <array> -#include <cmath> -#include <cstring> -#include <deque> -#include <forward_list> -#include <functional> -#include <iterator> -#include <limits> -#include <list> -#include <map> -#include <memory> -#include <set> -#include <string> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> - -#include "absl/base/internal/endian.h" -#include "absl/base/port.h" -#include "absl/container/fixed_array.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 { - -// 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 -// of an unspecified hash algorithm. `HashStateBase` provides a CRTP style -// base class for hash state implementations. Developers adding type support -// for `absl::Hash` should not rely on any parts of the state object other than -// the following member functions: -// -// * HashStateBase::combine() -// * HashStateBase::combine_contiguous() -// -// A derived hash state class of type `H` must provide a static member function -// with a signature similar to the following: -// -// `static H combine_contiguous(H state, const unsigned char*, size_t)`. -// -// `HashStateBase` will provide a complete implementation for a hash state -// object in terms of this method. -// -// Example: -// -// // Use CRTP to define your derived class. -// struct MyHashState : HashStateBase<MyHashState> { -// static H combine_contiguous(H state, const unsigned char*, size_t); -// using MyHashState::HashStateBase::combine; -// using MyHashState::HashStateBase::combine_contiguous; -// }; -template <typename H> -class HashStateBase { - public: - // HashStateBase::combine() - // - // Combines an arbitrary number of values into a hash state, returning the - // updated state. - // - // Each of the value types `T` must be separately hashable by the Abseil - // hashing framework. - // - // NOTE: - // - // state = H::combine(std::move(state), value1, value2, value3); - // - // is guaranteed to produce the same hash expansion as: - // - // state = H::combine(std::move(state), value1); - // state = H::combine(std::move(state), value2); - // state = H::combine(std::move(state), value3); - template <typename T, typename... Ts> - static H combine(H state, const T& value, const Ts&... values); - static H combine(H state) { return state; } - - // HashStateBase::combine_contiguous() - // - // Combines a contiguous array of `size` elements into a hash state, returning - // the updated state. - // - // NOTE: - // - // state = H::combine_contiguous(std::move(state), data, size); - // - // is NOT guaranteed to produce the same hash expansion as a for-loop (it may - // perform internal optimizations). If you need this guarantee, use the - // for-loop instead. - template <typename T> - static H combine_contiguous(H state, const T* data, size_t size); - - using AbslInternalPiecewiseCombiner = PiecewiseCombiner; -}; - -// is_uniquely_represented -// -// `is_uniquely_represented<T>` is a trait class that indicates whether `T` -// is uniquely represented. -// -// A type is "uniquely represented" if two equal values of that type are -// guaranteed to have the same bytes in their underlying storage. In other -// words, if `a == b`, then `memcmp(&a, &b, sizeof(T))` is guaranteed to be -// zero. This property cannot be detected automatically, so this trait is false -// by default, but can be specialized by types that wish to assert that they are -// uniquely represented. This makes them eligible for certain optimizations. -// -// If you have any doubt whatsoever, do not specialize this template. -// The default is completely safe, and merely disables some optimizations -// that will not matter for most types. Specializing this template, -// on the other hand, can be very hazardous. -// -// To be uniquely represented, a type must not have multiple ways of -// representing the same value; for example, float and double are not -// uniquely represented, because they have distinct representations for -// +0 and -0. Furthermore, the type's byte representation must consist -// solely of user-controlled data, with no padding bits and no compiler- -// controlled data such as vptrs or sanitizer metadata. This is usually -// very difficult to guarantee, because in most cases the compiler can -// insert data and padding bits at its own discretion. -// -// If you specialize this template for a type `T`, you must do so in the file -// that defines that type (or in this file). If you define that specialization -// anywhere else, `is_uniquely_represented<T>` could have different meanings -// in different places. -// -// The Enable parameter is meaningless; it is provided as a convenience, -// to support certain SFINAE techniques when defining specializations. -template <typename T, typename Enable = void> -struct is_uniquely_represented : std::false_type {}; - -// is_uniquely_represented<unsigned char> -// -// unsigned char is a synonym for "byte", so it is guaranteed to be -// uniquely represented. -template <> -struct is_uniquely_represented<unsigned char> : std::true_type {}; - -// is_uniquely_represented for non-standard integral types -// -// Integral types other than bool should be uniquely represented on any -// platform that this will plausibly be ported to. -template <typename Integral> -struct is_uniquely_represented< - Integral, typename std::enable_if<std::is_integral<Integral>::value>::type> - : std::true_type {}; - -// is_uniquely_represented<bool> -// -// -template <> -struct is_uniquely_represented<bool> : std::false_type {}; - -// hash_bytes() -// -// Convenience function that combines `hash_state` with the byte representation -// of `value`. -template <typename H, typename T> -H hash_bytes(H hash_state, const T& value) { - const unsigned char* start = reinterpret_cast<const unsigned char*>(&value); - return H::combine_contiguous(std::move(hash_state), start, sizeof(value)); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Basic Types -// ----------------------------------------------------------------------------- - -// Note: Default `AbslHashValue` implementations live in `hash_internal`. This -// allows us to block lexical scope lookup when doing an unqualified call to -// `AbslHashValue` below. User-defined implementations of `AbslHashValue` can -// only be found via ADL. - -// AbslHashValue() for hashing bool values -// -// We use SFINAE to ensure that this overload only accepts bool, not types that -// are convertible to bool. -template <typename H, typename B> -typename std::enable_if<std::is_same<B, bool>::value, H>::type AbslHashValue( - H hash_state, B value) { - return H::combine(std::move(hash_state), - static_cast<unsigned char>(value ? 1 : 0)); -} - -// AbslHashValue() for hashing enum values -template <typename H, typename Enum> -typename std::enable_if<std::is_enum<Enum>::value, H>::type AbslHashValue( - H hash_state, Enum e) { - // In practice, we could almost certainly just invoke hash_bytes directly, - // but it's possible that a sanitizer might one day want to - // store data in the unused bits of an enum. To avoid that risk, we - // convert to the underlying type before hashing. Hopefully this will get - // optimized away; if not, we can reopen discussion with c-toolchain-team. - return H::combine(std::move(hash_state), - static_cast<typename std::underlying_type<Enum>::type>(e)); -} -// AbslHashValue() for hashing floating-point values -template <typename H, typename Float> -typename std::enable_if<std::is_same<Float, float>::value || - std::is_same<Float, double>::value, - H>::type -AbslHashValue(H hash_state, Float value) { - return hash_internal::hash_bytes(std::move(hash_state), - value == 0 ? 0 : value); -} - -// Long double has the property that it might have extra unused bytes in it. -// For example, in x86 sizeof(long double)==16 but it only really uses 80-bits -// of it. This means we can't use hash_bytes on a long double and have to -// convert it to something else first. -template <typename H, typename LongDouble> -typename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type -AbslHashValue(H hash_state, LongDouble value) { - const int category = std::fpclassify(value); - switch (category) { - case FP_INFINITE: - // Add the sign bit to differentiate between +Inf and -Inf - hash_state = H::combine(std::move(hash_state), std::signbit(value)); - break; - - case FP_NAN: - case FP_ZERO: - default: - // Category is enough for these. - break; - - case FP_NORMAL: - case FP_SUBNORMAL: - // We can't convert `value` directly to double because this would have - // undefined behavior if the value is out of range. - // std::frexp gives us a value in the range (-1, -.5] or [.5, 1) that is - // guaranteed to be in range for `double`. The truncation is - // implementation defined, but that works as long as it is deterministic. - int exp; - auto mantissa = static_cast<double>(std::frexp(value, &exp)); - hash_state = H::combine(std::move(hash_state), mantissa, exp); - } - - return H::combine(std::move(hash_state), category); -} - -// AbslHashValue() for hashing pointers -template <typename H, typename T> -H AbslHashValue(H hash_state, T* ptr) { - auto v = reinterpret_cast<uintptr_t>(ptr); - // Due to alignment, pointers tend to have low bits as zero, and the next few - // bits follow a pattern since they are also multiples of some base value. - // Mixing the pointer twice helps prevent stuck low bits for certain alignment - // values. - return H::combine(std::move(hash_state), v, v); -} - -// AbslHashValue() for hashing nullptr_t -template <typename H> -H AbslHashValue(H hash_state, std::nullptr_t) { - return H::combine(std::move(hash_state), static_cast<void*>(nullptr)); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Composite Types -// ----------------------------------------------------------------------------- - -// is_hashable() -// -// Trait class which returns true if T is hashable by the absl::Hash framework. -// Used for the AbslHashValue implementations for composite types below. -template <typename T> -struct is_hashable; - -// AbslHashValue() for hashing pairs -template <typename H, typename T1, typename T2> -typename std::enable_if<is_hashable<T1>::value && is_hashable<T2>::value, - H>::type -AbslHashValue(H hash_state, const std::pair<T1, T2>& p) { - return H::combine(std::move(hash_state), p.first, p.second); -} - -// hash_tuple() -// -// Helper function for hashing a tuple. The third argument should -// be an index_sequence running from 0 to tuple_size<Tuple> - 1. -template <typename H, typename Tuple, size_t... Is> -H hash_tuple(H hash_state, const Tuple& t, absl::index_sequence<Is...>) { - return H::combine(std::move(hash_state), std::get<Is>(t)...); -} - -// AbslHashValue for hashing tuples -template <typename H, typename... Ts> -#if defined(_MSC_VER) -// This SFINAE gets MSVC confused under some conditions. Let's just disable it -// for now. -H -#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) { - return hash_internal::hash_tuple(std::move(hash_state), t, - absl::make_index_sequence<sizeof...(Ts)>()); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Pointers -// ----------------------------------------------------------------------------- - -// AbslHashValue for hashing unique_ptr -template <typename H, typename T, typename D> -H AbslHashValue(H hash_state, const std::unique_ptr<T, D>& ptr) { - return H::combine(std::move(hash_state), ptr.get()); -} - -// AbslHashValue for hashing shared_ptr -template <typename H, typename T> -H AbslHashValue(H hash_state, const std::shared_ptr<T>& ptr) { - return H::combine(std::move(hash_state), ptr.get()); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for String-Like Types -// ----------------------------------------------------------------------------- - -// AbslHashValue for hashing strings -// -// 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` -// -// For simplicity, we currently support only `char` strings. This support may -// be broadened, if necessary, but with some caution - this overload would -// misbehave in cases where the traits' `eq()` member isn't equivalent to `==` -// on the underlying character type. -template <typename H> -H AbslHashValue(H hash_state, absl::string_view str) { - return H::combine( - H::combine_contiguous(std::move(hash_state), str.data(), str.size()), - str.size()); -} - -// Support std::wstring, std::u16string and std::u32string. -template <typename Char, typename Alloc, typename H, - typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value || - std::is_same<Char, char16_t>::value || - std::is_same<Char, char32_t>::value>> -H AbslHashValue( - H hash_state, - const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) { - return H::combine( - H::combine_contiguous(std::move(hash_state), str.data(), str.size()), - str.size()); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Sequence Containers -// ----------------------------------------------------------------------------- - -// AbslHashValue for hashing std::array -template <typename H, typename T, size_t N> -typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue( - H hash_state, const std::array<T, N>& array) { - return H::combine_contiguous(std::move(hash_state), array.data(), - array.size()); -} - -// AbslHashValue for hashing std::deque -template <typename H, typename T, typename Allocator> -typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue( - H hash_state, const std::deque<T, Allocator>& deque) { - // TODO(gromer): investigate a more efficient implementation taking - // advantage of the chunk structure. - for (const auto& t : deque) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), deque.size()); -} - -// AbslHashValue for hashing std::forward_list -template <typename H, typename T, typename Allocator> -typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue( - H hash_state, const std::forward_list<T, Allocator>& list) { - size_t size = 0; - for (const T& t : list) { - hash_state = H::combine(std::move(hash_state), t); - ++size; - } - return H::combine(std::move(hash_state), size); -} - -// AbslHashValue for hashing std::list -template <typename H, typename T, typename Allocator> -typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue( - H hash_state, const std::list<T, Allocator>& list) { - for (const auto& t : list) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), list.size()); -} - -// AbslHashValue for hashing std::vector -// -// 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 -AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) { - return H::combine(H::combine_contiguous(std::move(hash_state), vector.data(), - vector.size()), - vector.size()); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Ordered Associative Containers -// ----------------------------------------------------------------------------- - -// AbslHashValue for hashing std::map -template <typename H, typename Key, typename T, typename Compare, - typename Allocator> -typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value, - H>::type -AbslHashValue(H hash_state, const std::map<Key, T, Compare, Allocator>& map) { - for (const auto& t : map) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), map.size()); -} - -// AbslHashValue for hashing std::multimap -template <typename H, typename Key, typename T, typename Compare, - typename Allocator> -typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value, - H>::type -AbslHashValue(H hash_state, - const std::multimap<Key, T, Compare, Allocator>& map) { - for (const auto& t : map) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), map.size()); -} - -// AbslHashValue for hashing std::set -template <typename H, typename Key, typename Compare, typename Allocator> -typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue( - H hash_state, const std::set<Key, Compare, Allocator>& set) { - for (const auto& t : set) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), set.size()); -} - -// AbslHashValue for hashing std::multiset -template <typename H, typename Key, typename Compare, typename Allocator> -typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue( - H hash_state, const std::multiset<Key, Compare, Allocator>& set) { - for (const auto& t : set) { - hash_state = H::combine(std::move(hash_state), t); - } - return H::combine(std::move(hash_state), set.size()); -} - -// ----------------------------------------------------------------------------- -// 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( - H hash_state, const absl::optional<T>& opt) { - if (opt) hash_state = H::combine(std::move(hash_state), *opt); - return H::combine(std::move(hash_state), opt.has_value()); -} - -// VariantVisitor -template <typename H> -struct VariantVisitor { - H&& hash_state; - template <typename T> - H operator()(const T& t) const { - return H::combine(std::move(hash_state), t); - } -}; - -// AbslHashValue for hashing absl::variant -template <typename H, typename... T> -typename std::enable_if<conjunction<is_hashable<T>...>::value, H>::type -AbslHashValue(H hash_state, const absl::variant<T...>& v) { - if (!v.valueless_by_exception()) { - hash_state = absl::visit(VariantVisitor<H>{std::move(hash_state)}, v); - } - return H::combine(std::move(hash_state), v.index()); -} - -// ----------------------------------------------------------------------------- -// AbslHashValue for Other Types -// ----------------------------------------------------------------------------- - -// 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. - -// ----------------------------------------------------------------------------- - -// hash_range_or_bytes() -// -// Mixes all values in the range [data, data+size) into the hash state. -// This overload accepts only uniquely-represented types, and hashes them by -// hashing the entire range of bytes. -template <typename H, typename T> -typename std::enable_if<is_uniquely_represented<T>::value, H>::type -hash_range_or_bytes(H hash_state, const T* data, size_t size) { - const auto* bytes = reinterpret_cast<const unsigned char*>(data); - return H::combine_contiguous(std::move(hash_state), bytes, sizeof(T) * size); -} - -// hash_range_or_bytes() -template <typename H, typename T> -typename std::enable_if<!is_uniquely_represented<T>::value, H>::type -hash_range_or_bytes(H hash_state, const T* data, size_t size) { - for (const auto end = data + size; data < end; ++data) { - hash_state = H::combine(std::move(hash_state), *data); - } - return hash_state; -} - -#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \ - ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1 -#else -#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0 -#endif - -// HashSelect -// -// Type trait to select the appropriate hash implementation to use. -// HashSelect::type<T> will give the proper hash implementation, to be invoked -// as: -// HashSelect::type<T>::Invoke(state, value) -// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a -// valid `Invoke` function. Types that are not hashable will have a ::value of -// `false`. -struct HashSelect { - private: - struct State : HashStateBase<State> { - static State combine_contiguous(State hash_state, const unsigned char*, - size_t); - using State::HashStateBase::combine_contiguous; - }; - - struct UniquelyRepresentedProbe { - template <typename H, typename T> - static auto Invoke(H state, const T& value) - -> absl::enable_if_t<is_uniquely_represented<T>::value, H> { - return hash_internal::hash_bytes(std::move(state), value); - } - }; - - struct HashValueProbe { - template <typename H, typename T> - static auto Invoke(H state, const T& value) -> absl::enable_if_t< - std::is_same<H, - decltype(AbslHashValue(std::move(state), value))>::value, - H> { - return AbslHashValue(std::move(state), value); - } - }; - - struct LegacyHashProbe { -#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ - template <typename H, typename T> - static auto Invoke(H state, const T& value) -> absl::enable_if_t< - std::is_convertible< - decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)), - size_t>::value, - H> { - return hash_internal::hash_bytes( - std::move(state), - ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value)); - } -#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ - }; - - struct StdHashProbe { - template <typename H, typename T> - static auto Invoke(H state, const T& value) - -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> { - return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value)); - } - }; - - template <typename Hash, typename T> - struct Probe : Hash { - private: - template <typename H, typename = decltype(H::Invoke( - std::declval<State>(), std::declval<const T&>()))> - static std::true_type Test(int); - template <typename U> - static std::false_type Test(char); - - public: - static constexpr bool value = decltype(Test<Hash>(0))::value; - }; - - public: - // Probe each implementation in order. - // disjunction provides short circuiting wrt instantiation. - template <typename T> - using Apply = absl::disjunction< // - Probe<UniquelyRepresentedProbe, T>, // - Probe<HashValueProbe, T>, // - Probe<LegacyHashProbe, T>, // - Probe<StdHashProbe, T>, // - std::false_type>; -}; - -template <typename T> -struct is_hashable - : std::integral_constant<bool, HashSelect::template Apply<T>::value> {}; - -// 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 - using uint128 = __uint128_t; -#else // ABSL_HAVE_INTRINSIC_INT128 - using uint128 = absl::uint128; -#endif // ABSL_HAVE_INTRINSIC_INT128 - - static constexpr uint64_t kMul = - sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51} - : uint64_t{0x9ddfea08eb382d69}; - - template <typename T> - using IntegralFastPath = - conjunction<std::is_integral<T>, is_uniquely_represented<T>>; - - public: - // Move only - CityHashState(CityHashState&&) = default; - CityHashState& operator=(CityHashState&&) = default; - - // CityHashState::combine_contiguous() - // - // Fundamental base case for hash recursion: mixes the given range of bytes - // into the hash state. - static CityHashState combine_contiguous(CityHashState hash_state, - const unsigned char* first, - size_t size) { - return CityHashState( - CombineContiguousImpl(hash_state.state_, first, size, - std::integral_constant<int, sizeof(size_t)>{})); - } - using CityHashState::HashStateBase::combine_contiguous; - - // CityHashState::hash() - // - // For performance reasons in non-opt mode, we specialize this for - // integral types. - // Otherwise we would be instantiating and calling dozens of functions for - // something that is just one multiplication and a couple xor's. - // The result should be the same as running the whole algorithm, but faster. - template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0> - static size_t hash(T value) { - return static_cast<size_t>(Mix(Seed(), static_cast<uint64_t>(value))); - } - - // 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(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. - 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. - CityHashState(const CityHashState&) = default; - - explicit CityHashState(uint64_t state) : state_(state) {} - - // Implementation of the base case for combine_contiguous where we actually - // mix the bytes into the state. - // Dispatch to different implementations of the combine_contiguous depending - // on the value of `sizeof(size_t)`. - static uint64_t CombineContiguousImpl(uint64_t state, - const unsigned char* first, size_t len, - std::integral_constant<int, 4> - /* sizeof_size_t */); - static uint64_t CombineContiguousImpl(uint64_t state, - const unsigned char* first, size_t len, - std::integral_constant<int, 8> - /* sizeof_size_t*/); - - // Slow dispatch path for calls to CombineContiguousImpl with a size argument - // larger than PiecewiseChunkSize(). Has the same effect as calling - // CombineContiguousImpl() repeatedly with the chunk stride size. - static uint64_t CombineLargeContiguousImpl32(uint64_t state, - const unsigned char* first, - size_t len); - static uint64_t CombineLargeContiguousImpl64(uint64_t state, - const unsigned char* first, - size_t len); - - // Reads 9 to 16 bytes from p. - // The first 8 bytes are in .first, the rest (zero padded) bytes are in - // .second. - static std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p, - size_t len) { - uint64_t high = little_endian::Load64(p + len - 8); - return {little_endian::Load64(p), high >> (128 - len * 8)}; - } - - // Reads 4 to 8 bytes from p. Zero pads to fill uint64_t. - static uint64_t Read4To8(const unsigned char* p, size_t len) { - return (static_cast<uint64_t>(little_endian::Load32(p + len - 4)) - << (len - 4) * 8) | - little_endian::Load32(p); - } - - // Reads 1 to 3 bytes from p. Zero pads to fill uint32_t. - static uint32_t Read1To3(const unsigned char* p, size_t len) { - return static_cast<uint32_t>((p[0]) | // - (p[len / 2] << (len / 2 * 8)) | // - (p[len - 1] << ((len - 1) * 8))); - } - - ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) { - using MultType = - absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>; - // 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 - // multiplications instead of one. - MultType m = state + v; - m *= kMul; - return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2))); - } - - // Seed() - // - // A non-deterministic seed. - // - // The current purpose of this seed is to generate non-deterministic results - // and prevent having users depend on the particular hash values. - // It is not meant as a security feature right now, but it leaves the door - // open to upgrade it to a true per-process random seed. A true random seed - // costs more and we don't need to pay for that right now. - // - // On platforms with ASLR, we take advantage of it to make a per-process - // random value. - // See https://en.wikipedia.org/wiki/Address_space_layout_randomization - // - // On other platforms this is still going to be non-deterministic but most - // probably per-build and not per-process. - ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() { -#if (!defined(__clang__) || __clang_major__ > 11) && \ - !defined(__apple_build_version__) - return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed)); -#else - // Workaround the absence of - // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021. - return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed)); -#endif - } - static const void* const kSeed; - - uint64_t state_; -}; - -// CityHashState::CombineContiguousImpl() -inline uint64_t CityHashState::CombineContiguousImpl( - uint64_t state, const unsigned char* first, size_t len, - std::integral_constant<int, 4> /* sizeof_size_t */) { - // For large values we use CityHash, for small ones we just use a - // multiplicative hash. - uint64_t v; - if (len > 8) { - if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) { - return CombineLargeContiguousImpl32(state, first, len); - } - v = absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first), len); - } else if (len >= 4) { - v = Read4To8(first, len); - } else if (len > 0) { - v = Read1To3(first, len); - } else { - // Empty ranges have no effect. - return state; - } - return Mix(state, v); -} - -// 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 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 = absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first), len); - } else if (len > 8) { - auto p = Read9To16(first, len); - state = Mix(state, p.first); - v = p.second; - } else if (len >= 4) { - v = Read4To8(first, len); - } else if (len > 0) { - v = Read1To3(first, len); - } else { - // Empty ranges have no effect. - return state; - } - return Mix(state, v); -} - -struct AggregateBarrier {}; - -// HashImpl - -// Add a private base class to make sure this type is not an aggregate. -// Aggregates can be aggregate initialized even if the default constructor is -// deleted. -struct PoisonedHash : private AggregateBarrier { - PoisonedHash() = delete; - PoisonedHash(const PoisonedHash&) = delete; - PoisonedHash& operator=(const PoisonedHash&) = delete; -}; - -template <typename T> -struct HashImpl { - size_t operator()(const T& value) const { return CityHashState::hash(value); } -}; - -template <typename T> -struct Hash - : absl::conditional_t<is_hashable<T>::value, HashImpl<T>, PoisonedHash> {}; - -template <typename H> -template <typename T, typename... Ts> -H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) { - return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke( - std::move(state), value), - values...); -} - -// HashStateBase::combine_contiguous() -template <typename H> -template <typename T> -H HashStateBase<H>::combine_contiguous(H state, const T* data, size_t size) { - return hash_internal::hash_range_or_bytes(std::move(state), data, size); -} - -// HashStateBase::PiecewiseCombiner::add_buffer() -template <typename H> -H PiecewiseCombiner::add_buffer(H state, const unsigned char* data, - size_t size) { - if (position_ + size < PiecewiseChunkSize()) { - // This partial chunk does not fill our existing buffer - memcpy(buf_ + position_, data, size); - position_ += size; - return state; - } - - // If the buffer is partially filled we need to complete the buffer - // and hash it. - if (position_ != 0) { - const size_t bytes_needed = PiecewiseChunkSize() - position_; - memcpy(buf_ + position_, data, bytes_needed); - state = H::combine_contiguous(std::move(state), buf_, PiecewiseChunkSize()); - data += bytes_needed; - size -= bytes_needed; - } - - // Hash whatever chunks we can without copying - while (size >= PiecewiseChunkSize()) { - state = H::combine_contiguous(std::move(state), data, PiecewiseChunkSize()); - data += PiecewiseChunkSize(); - size -= PiecewiseChunkSize(); - } - // Fill the buffer with the remainder - memcpy(buf_, data, size); - position_ = size; - return state; -} - -// HashStateBase::PiecewiseCombiner::finalize() -template <typename H> -H PiecewiseCombiner::finalize(H state) { - // Hash the remainder left in the buffer, which may be empty - return H::combine_contiguous(std::move(state), buf_, position_); -} - -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HASH_INTERNAL_HASH_H_ diff --git a/third_party/abseil_cpp/absl/hash/internal/print_hash_of.cc b/third_party/abseil_cpp/absl/hash/internal/print_hash_of.cc deleted file mode 100644 index c392125a69fa..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/print_hash_of.cc +++ /dev/null @@ -1,23 +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 <cstdlib> - -#include "absl/hash/hash.h" - -// Prints the hash of argv[1]. -int main(int argc, char** argv) { - if (argc < 2) return 1; - printf("%zu\n", absl::Hash<int>{}(std::atoi(argv[1]))); // NOLINT -} diff --git a/third_party/abseil_cpp/absl/hash/internal/spy_hash_state.h b/third_party/abseil_cpp/absl/hash/internal/spy_hash_state.h deleted file mode 100644 index c08312081180..000000000000 --- a/third_party/abseil_cpp/absl/hash/internal/spy_hash_state.h +++ /dev/null @@ -1,231 +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. - -#ifndef ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ -#define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ - -#include <ostream> -#include <string> -#include <vector> - -#include "absl/hash/hash.h" -#include "absl/strings/match.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_join.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace hash_internal { - -// SpyHashState is an implementation of the HashState API that simply -// accumulates all input bytes in an internal buffer. This makes it useful -// for testing AbslHashValue overloads (so long as they are templated on the -// HashState parameter), since it can report the exact hash representation -// that the AbslHashValue overload produces. -// -// Sample usage: -// EXPECT_EQ(SpyHashState::combine(SpyHashState(), foo), -// SpyHashState::combine(SpyHashState(), bar)); -template <typename T> -class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> { - public: - SpyHashStateImpl() : error_(std::make_shared<absl::optional<std::string>>()) { - static_assert(std::is_void<T>::value, ""); - } - - // Move-only - SpyHashStateImpl(const SpyHashStateImpl&) = delete; - SpyHashStateImpl& operator=(const SpyHashStateImpl&) = delete; - - SpyHashStateImpl(SpyHashStateImpl&& other) noexcept { - *this = std::move(other); - } - - SpyHashStateImpl& operator=(SpyHashStateImpl&& other) noexcept { - hash_representation_ = std::move(other.hash_representation_); - error_ = other.error_; - moved_from_ = other.moved_from_; - other.moved_from_ = true; - return *this; - } - - template <typename U> - SpyHashStateImpl(SpyHashStateImpl<U>&& other) { // NOLINT - hash_representation_ = std::move(other.hash_representation_); - error_ = other.error_; - moved_from_ = other.moved_from_; - other.moved_from_ = true; - } - - template <typename A, typename... Args> - static SpyHashStateImpl combine(SpyHashStateImpl s, const A& a, - const Args&... args) { - // Pass an instance of SpyHashStateImpl<A> when trying to combine `A`. This - // allows us to test that the user only uses this instance for combine calls - // and does not call AbslHashValue directly. - // See AbslHashValue implementation at the bottom. - s = SpyHashStateImpl<A>::HashStateBase::combine(std::move(s), a); - return SpyHashStateImpl::combine(std::move(s), args...); - } - static SpyHashStateImpl combine(SpyHashStateImpl s) { - if (direct_absl_hash_value_error_) { - *s.error_ = "AbslHashValue should not be invoked directly."; - } else if (s.moved_from_) { - *s.error_ = "Used moved-from instance of the hash state object."; - } - return s; - } - - static void SetDirectAbslHashValueError() { - direct_absl_hash_value_error_ = true; - } - - // Two SpyHashStateImpl objects are equal if they hold equal hash - // representations. - friend bool operator==(const SpyHashStateImpl& lhs, - const SpyHashStateImpl& rhs) { - return lhs.hash_representation_ == rhs.hash_representation_; - } - - friend bool operator!=(const SpyHashStateImpl& lhs, - const SpyHashStateImpl& rhs) { - return !(lhs == rhs); - } - - enum class CompareResult { - kEqual, - kASuffixB, - kBSuffixA, - kUnequal, - }; - - static CompareResult Compare(const SpyHashStateImpl& a, - const SpyHashStateImpl& b) { - const std::string a_flat = absl::StrJoin(a.hash_representation_, ""); - const std::string b_flat = absl::StrJoin(b.hash_representation_, ""); - if (a_flat == b_flat) return CompareResult::kEqual; - if (absl::EndsWith(a_flat, b_flat)) return CompareResult::kBSuffixA; - if (absl::EndsWith(b_flat, a_flat)) return CompareResult::kASuffixB; - return CompareResult::kUnequal; - } - - // operator<< prints the hash representation as a hex and ASCII dump, to - // facilitate debugging. - friend std::ostream& operator<<(std::ostream& out, - const SpyHashStateImpl& hash_state) { - out << "[\n"; - for (auto& s : hash_state.hash_representation_) { - size_t offset = 0; - for (char c : s) { - if (offset % 16 == 0) { - out << absl::StreamFormat("\n0x%04x: ", offset); - } - if (offset % 2 == 0) { - out << " "; - } - out << absl::StreamFormat("%02x", c); - ++offset; - } - out << "\n"; - } - return out << "]"; - } - - // The base case of the combine recursion, which writes raw bytes into the - // internal buffer. - static SpyHashStateImpl combine_contiguous(SpyHashStateImpl hash_state, - const unsigned char* begin, - size_t size) { - const size_t large_chunk_stride = PiecewiseChunkSize(); - if (size > large_chunk_stride) { - // Combining a large contiguous buffer must have the same effect as - // doing it piecewise by the stride length, followed by the (possibly - // empty) remainder. - while (size >= large_chunk_stride) { - hash_state = SpyHashStateImpl::combine_contiguous( - std::move(hash_state), begin, large_chunk_stride); - begin += large_chunk_stride; - size -= large_chunk_stride; - } - } - - hash_state.hash_representation_.emplace_back( - reinterpret_cast<const char*>(begin), size); - return hash_state; - } - - using SpyHashStateImpl::HashStateBase::combine_contiguous; - - absl::optional<std::string> error() const { - if (moved_from_) { - return "Returned a moved-from instance of the hash state object."; - } - return *error_; - } - - private: - template <typename U> - friend class SpyHashStateImpl; - - // This is true if SpyHashStateImpl<T> has been passed to a call of - // AbslHashValue with the wrong type. This detects that the user called - // AbslHashValue directly (because the hash state type does not match). - static bool direct_absl_hash_value_error_; - - std::vector<std::string> hash_representation_; - // This is a shared_ptr because we want all instances of the particular - // SpyHashState run to share the field. This way we can set the error for - // use-after-move and all the copies will see it. - std::shared_ptr<absl::optional<std::string>> error_; - bool moved_from_ = false; -}; - -template <typename T> -bool SpyHashStateImpl<T>::direct_absl_hash_value_error_; - -template <bool& B> -struct OdrUse { - constexpr OdrUse() {} - bool& b = B; -}; - -template <void (*)()> -struct RunOnStartup { - static bool run; - static constexpr OdrUse<run> kOdrUse{}; -}; - -template <void (*f)()> -bool RunOnStartup<f>::run = (f(), true); - -template < - typename T, typename U, - // Only trigger for when (T != U), - typename = absl::enable_if_t<!std::is_same<T, U>::value>, - // This statement works in two ways: - // - First, it instantiates RunOnStartup and forces the initialization of - // `run`, which set the global variable. - // - Second, it triggers a SFINAE error disabling the overload to prevent - // compile time errors. If we didn't disable the overload we would get - // ambiguous overload errors, which we don't want. - int = RunOnStartup<SpyHashStateImpl<T>::SetDirectAbslHashValueError>::run> -void AbslHashValue(SpyHashStateImpl<T>, const U&); - -using SpyHashState = SpyHashStateImpl<void>; - -} // namespace hash_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ diff --git a/third_party/abseil_cpp/absl/memory/BUILD.bazel b/third_party/abseil_cpp/absl/memory/BUILD.bazel deleted file mode 100644 index d2824a05adda..000000000000 --- a/third_party/abseil_cpp/absl/memory/BUILD.bazel +++ /dev/null @@ -1,65 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "memory", - hdrs = ["memory.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:core_headers", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "memory_test", - srcs = ["memory_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":memory", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "memory_exception_safety_test", - srcs = [ - "memory_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":memory", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/memory/CMakeLists.txt b/third_party/abseil_cpp/absl/memory/CMakeLists.txt deleted file mode 100644 index 78fb7e1b316b..000000000000 --- a/third_party/abseil_cpp/absl/memory/CMakeLists.txt +++ /dev/null @@ -1,55 +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. -# - -absl_cc_library( - NAME - memory - HDRS - "memory.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::meta - PUBLIC -) - -absl_cc_test( - NAME - memory_test - SRCS - "memory_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::memory - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - memory_exception_safety_test - SRCS - "memory_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::memory - absl::config - absl::exception_safety_testing - gmock_main -) diff --git a/third_party/abseil_cpp/absl/memory/memory.h b/third_party/abseil_cpp/absl/memory/memory.h deleted file mode 100644 index 2b5ff623d430..000000000000 --- a/third_party/abseil_cpp/absl/memory/memory.h +++ /dev/null @@ -1,699 +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. -// -// ----------------------------------------------------------------------------- -// File: memory.h -// ----------------------------------------------------------------------------- -// -// This header file contains utility functions for managing the creation and -// conversion of smart pointers. This file is an extension to the C++ -// standard <memory> library header file. - -#ifndef ABSL_MEMORY_MEMORY_H_ -#define ABSL_MEMORY_MEMORY_H_ - -#include <cstddef> -#include <limits> -#include <memory> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// Function Template: WrapUnique() -// ----------------------------------------------------------------------------- -// -// Adopts ownership from a raw pointer and transfers it to the returned -// `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not* -// specify the template type `T` when calling `WrapUnique`. -// -// Example: -// X* NewX(int, int); -// auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>. -// -// Do not call WrapUnique with an explicit type, as in -// `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically -// deduce the pointer type. If you wish to make the type explicit, just use -// `std::unique_ptr` directly. -// -// auto x = std::unique_ptr<X>(NewX(1, 2)); -// - or - -// std::unique_ptr<X> x(NewX(1, 2)); -// -// While `absl::WrapUnique` is useful for capturing the output of a raw -// pointer factory, prefer 'absl::make_unique<T>(args...)' over -// 'absl::WrapUnique(new T(args...))'. -// -// auto x = WrapUnique(new X(1, 2)); // works, but nonideal. -// auto x = make_unique<X>(1, 2); // safer, standard, avoids raw 'new'. -// -// Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid -// expression. In particular, `absl::WrapUnique()` cannot wrap pointers to -// arrays, functions or void, and it must not be used to capture pointers -// obtained from array-new expressions (even though that would compile!). -template <typename T> -std::unique_ptr<T> WrapUnique(T* ptr) { - static_assert(!std::is_array<T>::value, "array types are unsupported"); - static_assert(std::is_object<T>::value, "non-object types are unsupported"); - return std::unique_ptr<T>(ptr); -} - -namespace memory_internal { - -// Traits to select proper overload and return type for `absl::make_unique<>`. -template <typename T> -struct MakeUniqueResult { - using scalar = std::unique_ptr<T>; -}; -template <typename T> -struct MakeUniqueResult<T[]> { - using array = std::unique_ptr<T[]>; -}; -template <typename T, size_t N> -struct MakeUniqueResult<T[N]> { - using invalid = void; -}; - -} // namespace memory_internal - -// gcc 4.8 has __cplusplus at 201301 but the libstdc++ shipped with it doesn't -// define make_unique. Other supported compilers either just define __cplusplus -// as 201103 but have make_unique (msvc), or have make_unique whenever -// __cplusplus > 201103 (clang). -#if (__cplusplus > 201103L || defined(_MSC_VER)) && \ - !(defined(__GLIBCXX__) && !defined(__cpp_lib_make_unique)) -using std::make_unique; -#else -// ----------------------------------------------------------------------------- -// Function Template: make_unique<T>() -// ----------------------------------------------------------------------------- -// -// Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries -// during the construction process. `absl::make_unique<>` also avoids redundant -// type declarations, by avoiding the need to explicitly use the `new` operator. -// -// This implementation of `absl::make_unique<>` is designed for C++11 code and -// will be replaced in C++14 by the equivalent `std::make_unique<>` abstraction. -// `absl::make_unique<>` is designed to be 100% compatible with -// `std::make_unique<>` so that the eventual migration will involve a simple -// rename operation. -// -// For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic, -// see Herb Sutter's explanation on -// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/]. -// (In general, reviewers should treat `new T(a,b)` with scrutiny.) -// -// Example usage: -// -// auto p = make_unique<X>(args...); // 'p' is a std::unique_ptr<X> -// auto pa = make_unique<X[]>(5); // 'pa' is a std::unique_ptr<X[]> -// -// Three overloads of `absl::make_unique` are required: -// -// - For non-array T: -// -// Allocates a T with `new T(std::forward<Args> args...)`, -// forwarding all `args` to T's constructor. -// Returns a `std::unique_ptr<T>` owning that object. -// -// - For an array of unknown bounds T[]: -// -// `absl::make_unique<>` will allocate an array T of type U[] with -// `new U[n]()` and return a `std::unique_ptr<U[]>` owning that array. -// -// Note that 'U[n]()' is different from 'U[n]', and elements will be -// value-initialized. Note as well that `std::unique_ptr` will perform its -// own destruction of the array elements upon leaving scope, even though -// the array [] does not have a default destructor. -// -// NOTE: an array of unknown bounds T[] may still be (and often will be) -// initialized to have a size, and will still use this overload. E.g: -// -// auto my_array = absl::make_unique<int[]>(10); -// -// - For an array of known bounds T[N]: -// -// `absl::make_unique<>` is deleted (like with `std::make_unique<>`) as -// this overload is not useful. -// -// NOTE: an array of known bounds T[N] is not considered a useful -// construction, and may cause undefined behavior in templates. E.g: -// -// auto my_array = absl::make_unique<int[10]>(); -// -// In those cases, of course, you can still use the overload above and -// simply initialize it to its desired size: -// -// auto my_array = absl::make_unique<int[]>(10); - -// `absl::make_unique` overload for non-array types. -template <typename T, typename... Args> -typename memory_internal::MakeUniqueResult<T>::scalar make_unique( - Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); -} - -// `absl::make_unique` overload for an array T[] of unknown bounds. -// The array allocation needs to use the `new T[size]` form and cannot take -// element constructor arguments. The `std::unique_ptr` will manage destructing -// these array elements. -template <typename T> -typename memory_internal::MakeUniqueResult<T>::array make_unique(size_t n) { - return std::unique_ptr<T>(new typename absl::remove_extent_t<T>[n]()); -} - -// `absl::make_unique` overload for an array T[N] of known bounds. -// This construction will be rejected. -template <typename T, typename... Args> -typename memory_internal::MakeUniqueResult<T>::invalid make_unique( - Args&&... /* args */) = delete; -#endif - -// ----------------------------------------------------------------------------- -// Function Template: RawPtr() -// ----------------------------------------------------------------------------- -// -// Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is -// useful within templates that need to handle a complement of raw pointers, -// `std::nullptr_t`, and smart pointers. -template <typename T> -auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) { - // ptr is a forwarding reference to support Ts with non-const operators. - return (ptr != nullptr) ? std::addressof(*ptr) : nullptr; -} -inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; } - -// ----------------------------------------------------------------------------- -// Function Template: ShareUniquePtr() -// ----------------------------------------------------------------------------- -// -// Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced -// type. Ownership (if any) of the held value is transferred to the returned -// shared pointer. -// -// Example: -// -// auto up = absl::make_unique<int>(10); -// auto sp = absl::ShareUniquePtr(std::move(up)); // shared_ptr<int> -// CHECK_EQ(*sp, 10); -// CHECK(up == nullptr); -// -// Note that this conversion is correct even when T is an array type, and more -// generally it works for *any* deleter of the `unique_ptr` (single-object -// deleter, array deleter, or any custom deleter), since the deleter is adopted -// by the shared pointer as well. The deleter is copied (unless it is a -// reference). -// -// Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a -// null shared pointer does not attempt to call the deleter. -template <typename T, typename D> -std::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) { - return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>(); -} - -// ----------------------------------------------------------------------------- -// Function Template: WeakenPtr() -// ----------------------------------------------------------------------------- -// -// Creates a weak pointer associated with a given shared pointer. The returned -// value is a `std::weak_ptr` of deduced type. -// -// Example: -// -// auto sp = std::make_shared<int>(10); -// auto wp = absl::WeakenPtr(sp); -// CHECK_EQ(sp.get(), wp.lock().get()); -// sp.reset(); -// CHECK(wp.lock() == nullptr); -// -template <typename T> -std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) { - return std::weak_ptr<T>(ptr); -} - -namespace memory_internal { - -// ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D. -template <template <typename> class Extract, typename Obj, typename Default, - typename> -struct ExtractOr { - using type = Default; -}; - -template <template <typename> class Extract, typename Obj, typename Default> -struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> { - using type = Extract<Obj>; -}; - -template <template <typename> class Extract, typename Obj, typename Default> -using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type; - -// Extractors for the features of allocators. -template <typename T> -using GetPointer = typename T::pointer; - -template <typename T> -using GetConstPointer = typename T::const_pointer; - -template <typename T> -using GetVoidPointer = typename T::void_pointer; - -template <typename T> -using GetConstVoidPointer = typename T::const_void_pointer; - -template <typename T> -using GetDifferenceType = typename T::difference_type; - -template <typename T> -using GetSizeType = typename T::size_type; - -template <typename T> -using GetPropagateOnContainerCopyAssignment = - typename T::propagate_on_container_copy_assignment; - -template <typename T> -using GetPropagateOnContainerMoveAssignment = - typename T::propagate_on_container_move_assignment; - -template <typename T> -using GetPropagateOnContainerSwap = typename T::propagate_on_container_swap; - -template <typename T> -using GetIsAlwaysEqual = typename T::is_always_equal; - -template <typename T> -struct GetFirstArg; - -template <template <typename...> class Class, typename T, typename... Args> -struct GetFirstArg<Class<T, Args...>> { - using type = T; -}; - -template <typename Ptr, typename = void> -struct ElementType { - using type = typename GetFirstArg<Ptr>::type; -}; - -template <typename T> -struct ElementType<T, void_t<typename T::element_type>> { - using type = typename T::element_type; -}; - -template <typename T, typename U> -struct RebindFirstArg; - -template <template <typename...> class Class, typename T, typename... Args, - typename U> -struct RebindFirstArg<Class<T, Args...>, U> { - using type = Class<U, Args...>; -}; - -template <typename T, typename U, typename = void> -struct RebindPtr { - using type = typename RebindFirstArg<T, U>::type; -}; - -template <typename T, typename U> -struct RebindPtr<T, U, void_t<typename T::template rebind<U>>> { - using type = typename T::template rebind<U>; -}; - -template <typename T, typename U> -constexpr bool HasRebindAlloc(...) { - return false; -} - -template <typename T, typename U> -constexpr bool HasRebindAlloc(typename T::template rebind<U>::other*) { - return true; -} - -template <typename T, typename U, bool = HasRebindAlloc<T, U>(nullptr)> -struct RebindAlloc { - using type = typename RebindFirstArg<T, U>::type; -}; - -template <typename T, typename U> -struct RebindAlloc<T, U, true> { - using type = typename T::template rebind<U>::other; -}; - -} // namespace memory_internal - -// ----------------------------------------------------------------------------- -// Class Template: pointer_traits -// ----------------------------------------------------------------------------- -// -// An implementation of C++11's std::pointer_traits. -// -// Provided for portability on toolchains that have a working C++11 compiler, -// but the standard library is lacking in C++11 support. For example, some -// version of the Android NDK. -// - -template <typename Ptr> -struct pointer_traits { - using pointer = Ptr; - - // element_type: - // Ptr::element_type if present. Otherwise T if Ptr is a template - // instantiation Template<T, Args...> - using element_type = typename memory_internal::ElementType<Ptr>::type; - - // difference_type: - // Ptr::difference_type if present, otherwise std::ptrdiff_t - using difference_type = - memory_internal::ExtractOrT<memory_internal::GetDifferenceType, Ptr, - std::ptrdiff_t>; - - // rebind: - // Ptr::rebind<U> if exists, otherwise Template<U, Args...> if Ptr is a - // template instantiation Template<T, Args...> - template <typename U> - using rebind = typename memory_internal::RebindPtr<Ptr, U>::type; - - // pointer_to: - // Calls Ptr::pointer_to(r) - static pointer pointer_to(element_type& r) { // NOLINT(runtime/references) - return Ptr::pointer_to(r); - } -}; - -// Specialization for T*. -template <typename T> -struct pointer_traits<T*> { - using pointer = T*; - using element_type = T; - using difference_type = std::ptrdiff_t; - - template <typename U> - using rebind = U*; - - // pointer_to: - // Calls std::addressof(r) - static pointer pointer_to( - element_type& r) noexcept { // NOLINT(runtime/references) - return std::addressof(r); - } -}; - -// ----------------------------------------------------------------------------- -// Class Template: allocator_traits -// ----------------------------------------------------------------------------- -// -// A C++11 compatible implementation of C++17's std::allocator_traits. -// -#if __cplusplus >= 201703L -using std::allocator_traits; -#else // __cplusplus >= 201703L -template <typename Alloc> -struct allocator_traits { - using allocator_type = Alloc; - - // value_type: - // Alloc::value_type - using value_type = typename Alloc::value_type; - - // pointer: - // Alloc::pointer if present, otherwise value_type* - using pointer = memory_internal::ExtractOrT<memory_internal::GetPointer, - Alloc, value_type*>; - - // const_pointer: - // Alloc::const_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<const value_type> - using const_pointer = - memory_internal::ExtractOrT<memory_internal::GetConstPointer, Alloc, - typename absl::pointer_traits<pointer>:: - template rebind<const value_type>>; - - // void_pointer: - // Alloc::void_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<void> - using void_pointer = memory_internal::ExtractOrT< - memory_internal::GetVoidPointer, Alloc, - typename absl::pointer_traits<pointer>::template rebind<void>>; - - // const_void_pointer: - // Alloc::const_void_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<const void> - using const_void_pointer = memory_internal::ExtractOrT< - memory_internal::GetConstVoidPointer, Alloc, - typename absl::pointer_traits<pointer>::template rebind<const void>>; - - // difference_type: - // Alloc::difference_type if present, otherwise - // absl::pointer_traits<pointer>::difference_type - using difference_type = memory_internal::ExtractOrT< - memory_internal::GetDifferenceType, Alloc, - typename absl::pointer_traits<pointer>::difference_type>; - - // size_type: - // Alloc::size_type if present, otherwise - // std::make_unsigned<difference_type>::type - using size_type = memory_internal::ExtractOrT< - memory_internal::GetSizeType, Alloc, - typename std::make_unsigned<difference_type>::type>; - - // propagate_on_container_copy_assignment: - // Alloc::propagate_on_container_copy_assignment if present, otherwise - // std::false_type - using propagate_on_container_copy_assignment = memory_internal::ExtractOrT< - memory_internal::GetPropagateOnContainerCopyAssignment, Alloc, - std::false_type>; - - // propagate_on_container_move_assignment: - // Alloc::propagate_on_container_move_assignment if present, otherwise - // std::false_type - using propagate_on_container_move_assignment = memory_internal::ExtractOrT< - memory_internal::GetPropagateOnContainerMoveAssignment, Alloc, - std::false_type>; - - // propagate_on_container_swap: - // Alloc::propagate_on_container_swap if present, otherwise std::false_type - using propagate_on_container_swap = - memory_internal::ExtractOrT<memory_internal::GetPropagateOnContainerSwap, - Alloc, std::false_type>; - - // is_always_equal: - // Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type - using is_always_equal = - memory_internal::ExtractOrT<memory_internal::GetIsAlwaysEqual, Alloc, - typename std::is_empty<Alloc>::type>; - - // rebind_alloc: - // Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc - // is Alloc<U, Args> - template <typename T> - using rebind_alloc = typename memory_internal::RebindAlloc<Alloc, T>::type; - - // rebind_traits: - // absl::allocator_traits<rebind_alloc<T>> - template <typename T> - using rebind_traits = absl::allocator_traits<rebind_alloc<T>>; - - // allocate(Alloc& a, size_type n): - // Calls a.allocate(n) - static pointer allocate(Alloc& a, // NOLINT(runtime/references) - size_type n) { - return a.allocate(n); - } - - // allocate(Alloc& a, size_type n, const_void_pointer hint): - // Calls a.allocate(n, hint) if possible. - // If not possible, calls a.allocate(n) - static pointer allocate(Alloc& a, size_type n, // NOLINT(runtime/references) - const_void_pointer hint) { - return allocate_impl(0, a, n, hint); - } - - // deallocate(Alloc& a, pointer p, size_type n): - // Calls a.deallocate(p, n) - static void deallocate(Alloc& a, pointer p, // NOLINT(runtime/references) - size_type n) { - a.deallocate(p, n); - } - - // construct(Alloc& a, T* p, Args&&... args): - // Calls a.construct(p, std::forward<Args>(args)...) if possible. - // If not possible, calls - // ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...) - template <typename T, typename... Args> - static void construct(Alloc& a, T* p, // NOLINT(runtime/references) - Args&&... args) { - construct_impl(0, a, p, std::forward<Args>(args)...); - } - - // destroy(Alloc& a, T* p): - // Calls a.destroy(p) if possible. If not possible, calls p->~T(). - template <typename T> - static void destroy(Alloc& a, T* p) { // NOLINT(runtime/references) - destroy_impl(0, a, p); - } - - // max_size(const Alloc& a): - // Returns a.max_size() if possible. If not possible, returns - // std::numeric_limits<size_type>::max() / sizeof(value_type) - static size_type max_size(const Alloc& a) { return max_size_impl(0, a); } - - // select_on_container_copy_construction(const Alloc& a): - // Returns a.select_on_container_copy_construction() if possible. - // If not possible, returns a. - static Alloc select_on_container_copy_construction(const Alloc& a) { - return select_on_container_copy_construction_impl(0, a); - } - - private: - template <typename A> - static auto allocate_impl(int, A& a, // NOLINT(runtime/references) - size_type n, const_void_pointer hint) - -> decltype(a.allocate(n, hint)) { - return a.allocate(n, hint); - } - static pointer allocate_impl(char, Alloc& a, // NOLINT(runtime/references) - size_type n, const_void_pointer) { - return a.allocate(n); - } - - template <typename A, typename... Args> - static auto construct_impl(int, A& a, // NOLINT(runtime/references) - Args&&... args) - -> decltype(a.construct(std::forward<Args>(args)...)) { - a.construct(std::forward<Args>(args)...); - } - - template <typename T, typename... Args> - static void construct_impl(char, Alloc&, T* p, Args&&... args) { - ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); - } - - template <typename A, typename T> - static auto destroy_impl(int, A& a, // NOLINT(runtime/references) - T* p) -> decltype(a.destroy(p)) { - a.destroy(p); - } - template <typename T> - static void destroy_impl(char, Alloc&, T* p) { - p->~T(); - } - - template <typename A> - static auto max_size_impl(int, const A& a) -> decltype(a.max_size()) { - return a.max_size(); - } - static size_type max_size_impl(char, const Alloc&) { - return (std::numeric_limits<size_type>::max)() / sizeof(value_type); - } - - template <typename A> - static auto select_on_container_copy_construction_impl(int, const A& a) - -> decltype(a.select_on_container_copy_construction()) { - return a.select_on_container_copy_construction(); - } - static Alloc select_on_container_copy_construction_impl(char, - const Alloc& a) { - return a; - } -}; -#endif // __cplusplus >= 201703L - -namespace memory_internal { - -// This template alias transforms Alloc::is_nothrow into a metafunction with -// Alloc as a parameter so it can be used with ExtractOrT<>. -template <typename Alloc> -using GetIsNothrow = typename Alloc::is_nothrow; - -} // namespace memory_internal - -// ABSL_ALLOCATOR_NOTHROW is a build time configuration macro for user to -// specify whether the default allocation function can throw or never throws. -// If the allocation function never throws, user should define it to a non-zero -// value (e.g. via `-DABSL_ALLOCATOR_NOTHROW`). -// If the allocation function can throw, user should leave it undefined or -// define it to zero. -// -// allocator_is_nothrow<Alloc> is a traits class that derives from -// Alloc::is_nothrow if present, otherwise std::false_type. It's specialized -// for Alloc = std::allocator<T> for any type T according to the state of -// ABSL_ALLOCATOR_NOTHROW. -// -// default_allocator_is_nothrow is a class that derives from std::true_type -// when the default allocator (global operator new) never throws, and -// std::false_type when it can throw. It is a convenience shorthand for writing -// allocator_is_nothrow<std::allocator<T>> (T can be any type). -// NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from -// the same type for all T, because users should specialize neither -// allocator_is_nothrow nor std::allocator. -template <typename Alloc> -struct allocator_is_nothrow - : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc, - std::false_type> {}; - -#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW -template <typename T> -struct allocator_is_nothrow<std::allocator<T>> : std::true_type {}; -struct default_allocator_is_nothrow : std::true_type {}; -#else -struct default_allocator_is_nothrow : std::false_type {}; -#endif - -namespace memory_internal { -template <typename Allocator, typename Iterator, typename... Args> -void ConstructRange(Allocator& alloc, Iterator first, Iterator last, - const Args&... args) { - for (Iterator cur = first; cur != last; ++cur) { - ABSL_INTERNAL_TRY { - std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), - args...); - } - ABSL_INTERNAL_CATCH_ANY { - while (cur != first) { - --cur; - std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); - } - ABSL_INTERNAL_RETHROW; - } - } -} - -template <typename Allocator, typename Iterator, typename InputIterator> -void CopyRange(Allocator& alloc, Iterator destination, InputIterator first, - InputIterator last) { - for (Iterator cur = destination; first != last; - static_cast<void>(++cur), static_cast<void>(++first)) { - ABSL_INTERNAL_TRY { - std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), - *first); - } - ABSL_INTERNAL_CATCH_ANY { - while (cur != destination) { - --cur; - std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); - } - ABSL_INTERNAL_RETHROW; - } - } -} -} // namespace memory_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_MEMORY_MEMORY_H_ diff --git a/third_party/abseil_cpp/absl/memory/memory_exception_safety_test.cc b/third_party/abseil_cpp/absl/memory/memory_exception_safety_test.cc deleted file mode 100644 index 1df72614c00d..000000000000 --- a/third_party/abseil_cpp/absl/memory/memory_exception_safety_test.cc +++ /dev/null @@ -1,57 +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/memory/memory.h" - -#include "absl/base/config.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -constexpr int kLength = 50; -using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; - -TEST(MakeUnique, CheckForLeaks) { - constexpr int kValue = 321; - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(Thrower(kValue)) - // Ensures make_unique does not modify the input. The real - // test, though, is ConstructorTracker checking for leaks. - .WithContracts(testing::strong_guarantee); - - EXPECT_TRUE(tester.Test([](Thrower* thrower) { - static_cast<void>(absl::make_unique<Thrower>(*thrower)); - })); - - EXPECT_TRUE(tester.Test([](Thrower* thrower) { - static_cast<void>(absl::make_unique<Thrower>(std::move(*thrower))); - })); - - // Test T[n] overload - EXPECT_TRUE(tester.Test([&](Thrower*) { - static_cast<void>(absl::make_unique<Thrower[]>(kLength)); - })); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_EXCEPTIONS diff --git a/third_party/abseil_cpp/absl/memory/memory_test.cc b/third_party/abseil_cpp/absl/memory/memory_test.cc deleted file mode 100644 index 1990c7ba4728..000000000000 --- a/third_party/abseil_cpp/absl/memory/memory_test.cc +++ /dev/null @@ -1,650 +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. - -// Tests for pointer utilities. - -#include "absl/memory/memory.h" - -#include <sys/types.h> - -#include <cstddef> -#include <memory> -#include <string> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace { - -using ::testing::ElementsAre; -using ::testing::Return; - -// This class creates observable behavior to verify that a destructor has -// been called, via the instance_count variable. -class DestructorVerifier { - public: - DestructorVerifier() { ++instance_count_; } - DestructorVerifier(const DestructorVerifier&) = delete; - DestructorVerifier& operator=(const DestructorVerifier&) = delete; - ~DestructorVerifier() { --instance_count_; } - - // The number of instances of this class currently active. - static int instance_count() { return instance_count_; } - - private: - // The number of instances of this class currently active. - static int instance_count_; -}; - -int DestructorVerifier::instance_count_ = 0; - -TEST(WrapUniqueTest, WrapUnique) { - // Test that the unique_ptr is constructed properly by verifying that the - // destructor for its payload gets called at the proper time. - { - auto dv = new DestructorVerifier; - EXPECT_EQ(1, DestructorVerifier::instance_count()); - std::unique_ptr<DestructorVerifier> ptr = absl::WrapUnique(dv); - EXPECT_EQ(1, DestructorVerifier::instance_count()); - } - EXPECT_EQ(0, DestructorVerifier::instance_count()); -} -TEST(MakeUniqueTest, Basic) { - std::unique_ptr<std::string> p = absl::make_unique<std::string>(); - EXPECT_EQ("", *p); - p = absl::make_unique<std::string>("hi"); - EXPECT_EQ("hi", *p); -} - -// InitializationVerifier fills in a pattern when allocated so we can -// distinguish between its default and value initialized states (without -// accessing truly uninitialized memory). -struct InitializationVerifier { - static constexpr int kDefaultScalar = 0x43; - static constexpr int kDefaultArray = 0x4B; - - static void* operator new(size_t n) { - void* ret = ::operator new(n); - memset(ret, kDefaultScalar, n); - return ret; - } - - static void* operator new[](size_t n) { - void* ret = ::operator new[](n); - memset(ret, kDefaultArray, n); - return ret; - } - - int a; - int b; -}; - -TEST(Initialization, MakeUnique) { - auto p = absl::make_unique<InitializationVerifier>(); - - EXPECT_EQ(0, p->a); - EXPECT_EQ(0, p->b); -} - -TEST(Initialization, MakeUniqueArray) { - auto p = absl::make_unique<InitializationVerifier[]>(2); - - EXPECT_EQ(0, p[0].a); - EXPECT_EQ(0, p[0].b); - EXPECT_EQ(0, p[1].a); - EXPECT_EQ(0, p[1].b); -} - -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int i1) : ip1{new int{i1}} {} - MoveOnly(int i1, int i2) : ip1{new int{i1}}, ip2{new int{i2}} {} - std::unique_ptr<int> ip1; - std::unique_ptr<int> ip2; -}; - -struct AcceptMoveOnly { - explicit AcceptMoveOnly(MoveOnly m) : m_(std::move(m)) {} - MoveOnly m_; -}; - -TEST(MakeUniqueTest, MoveOnlyTypeAndValue) { - using ExpectedType = std::unique_ptr<MoveOnly>; - { - auto p = absl::make_unique<MoveOnly>(); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(!p->ip1); - EXPECT_TRUE(!p->ip2); - } - { - auto p = absl::make_unique<MoveOnly>(1); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(p->ip1 && *p->ip1 == 1); - EXPECT_TRUE(!p->ip2); - } - { - auto p = absl::make_unique<MoveOnly>(1, 2); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(p->ip1 && *p->ip1 == 1); - EXPECT_TRUE(p->ip2 && *p->ip2 == 2); - } -} - -TEST(MakeUniqueTest, AcceptMoveOnly) { - auto p = absl::make_unique<AcceptMoveOnly>(MoveOnly()); - p = std::unique_ptr<AcceptMoveOnly>(new AcceptMoveOnly(MoveOnly())); -} - -struct ArrayWatch { - void* operator new[](size_t n) { - allocs().push_back(n); - return ::operator new[](n); - } - 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; - } -}; - -TEST(Make_UniqueTest, Array) { - // Ensure state is clean before we start so that these tests - // are order-agnostic. - ArrayWatch::allocs().clear(); - - auto p = absl::make_unique<ArrayWatch[]>(5); - static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value, - "unexpected return type"); - EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch))); -} - -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) {} - }; - using absl::make_unique; - (void)make_unique<TakesStdType>(std::vector<int>()); -} - -#if 0 -// These tests shouldn't compile. -TEST(MakeUniqueTestNC, AcceptMoveOnlyLvalue) { - auto m = MoveOnly(); - auto p = absl::make_unique<AcceptMoveOnly>(m); -} -TEST(MakeUniqueTestNC, KnownBoundArray) { - auto p = absl::make_unique<ArrayWatch[5]>(); -} -#endif - -TEST(RawPtrTest, RawPointer) { - int i = 5; - EXPECT_EQ(&i, absl::RawPtr(&i)); -} - -TEST(RawPtrTest, SmartPointer) { - int* o = new int(5); - std::unique_ptr<int> p(o); - EXPECT_EQ(o, absl::RawPtr(p)); -} - -class IntPointerNonConstDeref { - public: - explicit IntPointerNonConstDeref(int* p) : p_(p) {} - friend bool operator!=(const IntPointerNonConstDeref& a, std::nullptr_t) { - return a.p_ != nullptr; - } - int& operator*() { return *p_; } - - private: - std::unique_ptr<int> p_; -}; - -TEST(RawPtrTest, SmartPointerNonConstDereference) { - int* o = new int(5); - IntPointerNonConstDeref p(o); - EXPECT_EQ(o, absl::RawPtr(p)); -} - -TEST(RawPtrTest, NullValuedRawPointer) { - int* p = nullptr; - EXPECT_EQ(nullptr, absl::RawPtr(p)); -} - -TEST(RawPtrTest, NullValuedSmartPointer) { - std::unique_ptr<int> p; - EXPECT_EQ(nullptr, absl::RawPtr(p)); -} - -TEST(RawPtrTest, Nullptr) { - auto p = absl::RawPtr(nullptr); - EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value)); - EXPECT_EQ(nullptr, p); -} - -TEST(RawPtrTest, Null) { - auto p = absl::RawPtr(nullptr); - EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value)); - EXPECT_EQ(nullptr, p); -} - -TEST(RawPtrTest, Zero) { - auto p = absl::RawPtr(nullptr); - EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value)); - EXPECT_EQ(nullptr, p); -} - -TEST(ShareUniquePtrTest, Share) { - auto up = absl::make_unique<int>(); - int* rp = up.get(); - auto sp = absl::ShareUniquePtr(std::move(up)); - EXPECT_EQ(sp.get(), rp); -} - -TEST(ShareUniquePtrTest, ShareNull) { - struct NeverDie { - using pointer = void*; - void operator()(pointer) { - ASSERT_TRUE(false) << "Deleter should not have been called."; - } - }; - - std::unique_ptr<void, NeverDie> up; - auto sp = absl::ShareUniquePtr(std::move(up)); -} - -TEST(WeakenPtrTest, Weak) { - auto sp = std::make_shared<int>(); - auto wp = absl::WeakenPtr(sp); - EXPECT_EQ(sp.get(), wp.lock().get()); - sp.reset(); - EXPECT_TRUE(wp.expired()); -} - -// Should not compile. -/* -TEST(RawPtrTest, NotAPointer) { - absl::RawPtr(1.5); -} -*/ - -template <typename T> -struct SmartPointer { - using difference_type = char; -}; - -struct PointerWith { - using element_type = int32_t; - using difference_type = int16_t; - template <typename U> - using rebind = SmartPointer<U>; - - static PointerWith pointer_to( - element_type& r) { // NOLINT(runtime/references) - return PointerWith{&r}; - } - - element_type* ptr; -}; - -template <typename... Args> -struct PointerWithout {}; - -TEST(PointerTraits, Types) { - using TraitsWith = absl::pointer_traits<PointerWith>; - EXPECT_TRUE((std::is_same<TraitsWith::pointer, PointerWith>::value)); - EXPECT_TRUE((std::is_same<TraitsWith::element_type, int32_t>::value)); - EXPECT_TRUE((std::is_same<TraitsWith::difference_type, int16_t>::value)); - EXPECT_TRUE(( - std::is_same<TraitsWith::rebind<int64_t>, SmartPointer<int64_t>>::value)); - - using TraitsWithout = absl::pointer_traits<PointerWithout<double, int>>; - EXPECT_TRUE((std::is_same<TraitsWithout::pointer, - PointerWithout<double, int>>::value)); - EXPECT_TRUE((std::is_same<TraitsWithout::element_type, double>::value)); - EXPECT_TRUE( - (std::is_same<TraitsWithout ::difference_type, std::ptrdiff_t>::value)); - EXPECT_TRUE((std::is_same<TraitsWithout::rebind<int64_t>, - PointerWithout<int64_t, int>>::value)); - - using TraitsRawPtr = absl::pointer_traits<char*>; - EXPECT_TRUE((std::is_same<TraitsRawPtr::pointer, char*>::value)); - EXPECT_TRUE((std::is_same<TraitsRawPtr::element_type, char>::value)); - EXPECT_TRUE( - (std::is_same<TraitsRawPtr::difference_type, std::ptrdiff_t>::value)); - EXPECT_TRUE((std::is_same<TraitsRawPtr::rebind<int64_t>, int64_t*>::value)); -} - -TEST(PointerTraits, Functions) { - int i; - EXPECT_EQ(&i, absl::pointer_traits<PointerWith>::pointer_to(i).ptr); - EXPECT_EQ(&i, absl::pointer_traits<int*>::pointer_to(i)); -} - -TEST(AllocatorTraits, Typedefs) { - struct A { - struct value_type {}; - }; - EXPECT_TRUE(( - std::is_same<A, - typename absl::allocator_traits<A>::allocator_type>::value)); - EXPECT_TRUE( - (std::is_same<A::value_type, - typename absl::allocator_traits<A>::value_type>::value)); - - struct X {}; - struct HasPointer { - using value_type = X; - using pointer = SmartPointer<X>; - }; - EXPECT_TRUE((std::is_same<SmartPointer<X>, typename absl::allocator_traits< - HasPointer>::pointer>::value)); - EXPECT_TRUE( - (std::is_same<A::value_type*, - typename absl::allocator_traits<A>::pointer>::value)); - - EXPECT_TRUE( - (std::is_same< - SmartPointer<const X>, - typename absl::allocator_traits<HasPointer>::const_pointer>::value)); - EXPECT_TRUE( - (std::is_same<const A::value_type*, - typename absl::allocator_traits<A>::const_pointer>::value)); - - struct HasVoidPointer { - using value_type = X; - struct void_pointer {}; - }; - - EXPECT_TRUE((std::is_same<HasVoidPointer::void_pointer, - typename absl::allocator_traits< - HasVoidPointer>::void_pointer>::value)); - EXPECT_TRUE( - (std::is_same<SmartPointer<void>, typename absl::allocator_traits< - HasPointer>::void_pointer>::value)); - - struct HasConstVoidPointer { - using value_type = X; - struct const_void_pointer {}; - }; - - EXPECT_TRUE( - (std::is_same<HasConstVoidPointer::const_void_pointer, - typename absl::allocator_traits< - HasConstVoidPointer>::const_void_pointer>::value)); - EXPECT_TRUE((std::is_same<SmartPointer<const void>, - typename absl::allocator_traits< - HasPointer>::const_void_pointer>::value)); - - struct HasDifferenceType { - using value_type = X; - using difference_type = int; - }; - EXPECT_TRUE( - (std::is_same<int, typename absl::allocator_traits< - HasDifferenceType>::difference_type>::value)); - EXPECT_TRUE((std::is_same<char, typename absl::allocator_traits< - HasPointer>::difference_type>::value)); - - struct HasSizeType { - using value_type = X; - using size_type = unsigned int; - }; - EXPECT_TRUE((std::is_same<unsigned int, typename absl::allocator_traits< - HasSizeType>::size_type>::value)); - EXPECT_TRUE((std::is_same<unsigned char, typename absl::allocator_traits< - HasPointer>::size_type>::value)); - - struct HasPropagateOnCopy { - using value_type = X; - struct propagate_on_container_copy_assignment {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnCopy::propagate_on_container_copy_assignment, - typename absl::allocator_traits<HasPropagateOnCopy>:: - propagate_on_container_copy_assignment>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, - typename absl::allocator_traits< - A>::propagate_on_container_copy_assignment>::value)); - - struct HasPropagateOnMove { - using value_type = X; - struct propagate_on_container_move_assignment {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnMove::propagate_on_container_move_assignment, - typename absl::allocator_traits<HasPropagateOnMove>:: - propagate_on_container_move_assignment>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, - typename absl::allocator_traits< - A>::propagate_on_container_move_assignment>::value)); - - struct HasPropagateOnSwap { - using value_type = X; - struct propagate_on_container_swap {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnSwap::propagate_on_container_swap, - typename absl::allocator_traits<HasPropagateOnSwap>:: - propagate_on_container_swap>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, typename absl::allocator_traits<A>:: - propagate_on_container_swap>::value)); - - struct HasIsAlwaysEqual { - using value_type = X; - struct is_always_equal {}; - }; - - EXPECT_TRUE((std::is_same<HasIsAlwaysEqual::is_always_equal, - typename absl::allocator_traits< - HasIsAlwaysEqual>::is_always_equal>::value)); - EXPECT_TRUE((std::is_same<std::true_type, typename absl::allocator_traits< - A>::is_always_equal>::value)); - struct NonEmpty { - using value_type = X; - int i; - }; - EXPECT_TRUE( - (std::is_same<std::false_type, - absl::allocator_traits<NonEmpty>::is_always_equal>::value)); -} - -template <typename T> -struct AllocWithPrivateInheritance : private std::allocator<T> { - using value_type = T; -}; - -TEST(AllocatorTraits, RebindWithPrivateInheritance) { - // Regression test for some versions of gcc that do not like the sfinae we - // used in combination with private inheritance. - EXPECT_TRUE( - (std::is_same<AllocWithPrivateInheritance<int>, - absl::allocator_traits<AllocWithPrivateInheritance<char>>:: - rebind_alloc<int>>::value)); -} - -template <typename T> -struct Rebound {}; - -struct AllocWithRebind { - using value_type = int; - template <typename T> - struct rebind { - using other = Rebound<T>; - }; -}; - -template <typename T, typename U> -struct AllocWithoutRebind { - using value_type = int; -}; - -TEST(AllocatorTraits, Rebind) { - EXPECT_TRUE( - (std::is_same<Rebound<int>, - typename absl::allocator_traits< - AllocWithRebind>::template rebind_alloc<int>>::value)); - EXPECT_TRUE( - (std::is_same<absl::allocator_traits<Rebound<int>>, - typename absl::allocator_traits< - AllocWithRebind>::template rebind_traits<int>>::value)); - - EXPECT_TRUE( - (std::is_same<AllocWithoutRebind<double, char>, - typename absl::allocator_traits<AllocWithoutRebind< - int, char>>::template rebind_alloc<double>>::value)); - EXPECT_TRUE( - (std::is_same<absl::allocator_traits<AllocWithoutRebind<double, char>>, - typename absl::allocator_traits<AllocWithoutRebind< - int, char>>::template rebind_traits<double>>::value)); -} - -struct TestValue { - TestValue() {} - explicit TestValue(int* trace) : trace(trace) { ++*trace; } - ~TestValue() { - if (trace) --*trace; - } - int* trace = nullptr; -}; - -struct MinimalMockAllocator { - MinimalMockAllocator() : value(0) {} - explicit MinimalMockAllocator(int value) : value(value) {} - 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)); - - int value; -}; - -TEST(AllocatorTraits, FunctionsMinimal) { - int trace = 0; - int hint; - TestValue x(&trace); - MinimalMockAllocator mock; - using Traits = absl::allocator_traits<MinimalMockAllocator>; - EXPECT_CALL(mock, allocate(7)).WillRepeatedly(Return(&x)); - 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))); - EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint))); - Traits::deallocate(mock, &x, 7); - - EXPECT_EQ(1, trace); - Traits::construct(mock, &x, &trace); - EXPECT_EQ(2, trace); - Traits::destroy(mock, &x); - EXPECT_EQ(1, trace); - - EXPECT_EQ(std::numeric_limits<size_t>::max() / sizeof(TestValue), - Traits::max_size(mock)); - - EXPECT_EQ(0, mock.value); - EXPECT_EQ(0, Traits::select_on_container_copy_construction(mock).value); -} - -struct FullMockAllocator { - FullMockAllocator() : value(0) {} - 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)); - - int value; -}; - -TEST(AllocatorTraits, FunctionsFull) { - int trace = 0; - int hint; - TestValue x(&trace), y; - FullMockAllocator mock; - using Traits = absl::allocator_traits<FullMockAllocator>; - EXPECT_CALL(mock, allocate(7)).WillRepeatedly(Return(&x)); - EXPECT_CALL(mock, allocate(13, &hint)).WillRepeatedly(Return(&y)); - EXPECT_CALL(mock, construct(&x, &trace)); - EXPECT_CALL(mock, destroy(&x)); - EXPECT_CALL(mock, max_size()).WillRepeatedly(Return(17)); - EXPECT_CALL(mock, select_on_container_copy_construction()) - .WillRepeatedly(Return(FullMockAllocator(23))); - - EXPECT_EQ(&x, Traits::allocate(mock, 7)); - EXPECT_EQ(&y, Traits::allocate(mock, 13, static_cast<const void*>(&hint))); - - EXPECT_EQ(1, trace); - Traits::construct(mock, &x, &trace); - EXPECT_EQ(1, trace); - Traits::destroy(mock, &x); - EXPECT_EQ(1, trace); - - EXPECT_EQ(17, Traits::max_size(mock)); - - EXPECT_EQ(0, mock.value); - EXPECT_EQ(23, Traits::select_on_container_copy_construction(mock).value); -} - -TEST(AllocatorNoThrowTest, DefaultAllocator) { -#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW - EXPECT_TRUE(absl::default_allocator_is_nothrow::value); -#else - EXPECT_FALSE(absl::default_allocator_is_nothrow::value); -#endif -} - -TEST(AllocatorNoThrowTest, StdAllocator) { -#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW - EXPECT_TRUE(absl::allocator_is_nothrow<std::allocator<int>>::value); -#else - EXPECT_FALSE(absl::allocator_is_nothrow<std::allocator<int>>::value); -#endif -} - -TEST(AllocatorNoThrowTest, CustomAllocator) { - struct NoThrowAllocator { - using is_nothrow = std::true_type; - }; - struct CanThrowAllocator { - using is_nothrow = std::false_type; - }; - 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); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/meta/BUILD.bazel b/third_party/abseil_cpp/absl/meta/BUILD.bazel deleted file mode 100644 index 5585fcca794a..000000000000 --- a/third_party/abseil_cpp/absl/meta/BUILD.bazel +++ /dev/null @@ -1,48 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "type_traits", - hdrs = ["type_traits.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - ], -) - -cc_test( - name = "type_traits_test", - srcs = ["type_traits_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":type_traits", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/meta/CMakeLists.txt b/third_party/abseil_cpp/absl/meta/CMakeLists.txt deleted file mode 100644 index 672ead2fd0a5..000000000000 --- a/third_party/abseil_cpp/absl/meta/CMakeLists.txt +++ /dev/null @@ -1,50 +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. -# - -absl_cc_library( - NAME - type_traits - HDRS - "type_traits.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - PUBLIC -) - -absl_cc_test( - NAME - type_traits_test - SRCS - "type_traits_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::type_traits - gmock_main -) - -# component target -absl_cc_library( - NAME - meta - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::type_traits - PUBLIC -) diff --git a/third_party/abseil_cpp/absl/meta/type_traits.h b/third_party/abseil_cpp/absl/meta/type_traits.h deleted file mode 100644 index d5cb5f3be39d..000000000000 --- a/third_party/abseil_cpp/absl/meta/type_traits.h +++ /dev/null @@ -1,767 +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. -// -// ----------------------------------------------------------------------------- -// type_traits.h -// ----------------------------------------------------------------------------- -// -// This file contains C++11-compatible versions of standard <type_traits> API -// functions for determining the characteristics of types. Such traits can -// support type inference, classification, and transformation, as well as -// make it easier to write templates based on generic type behavior. -// -// See https://en.cppreference.com/w/cpp/header/type_traits -// -// WARNING: use of many of the constructs in this header will count as "complex -// template metaprogramming", so before proceeding, please carefully consider -// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming -// -// WARNING: using template metaprogramming to detect or depend on API -// features is brittle and not guaranteed. Neither the standard library nor -// Abseil provides any guarantee that APIs are stable in the face of template -// metaprogramming. Use with caution. -#ifndef ABSL_META_TYPE_TRAITS_H_ -#define ABSL_META_TYPE_TRAITS_H_ - -#include <stddef.h> -#include <functional> -#include <type_traits> - -#include "absl/base/config.h" - -// MSVC constructibility traits do not detect destructor properties and so our -// implementations should not use them as a source-of-truth. -#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__) -#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Defined and documented later on in this file. -template <typename T> -struct is_trivially_destructible; - -// Defined and documented later on in this file. -template <typename T> -struct is_trivially_move_assignable; - -namespace type_traits_internal { - -// Silence MSVC warnings about the destructor being defined as deleted. -#if defined(_MSC_VER) && !defined(__GNUC__) -#pragma warning(push) -#pragma warning(disable : 4624) -#endif // defined(_MSC_VER) && !defined(__GNUC__) - -template <class T> -union SingleMemberUnion { - T t; -}; - -// Restore the state of the destructor warning that was silenced above. -#if defined(_MSC_VER) && !defined(__GNUC__) -#pragma warning(pop) -#endif // defined(_MSC_VER) && !defined(__GNUC__) - -template <class T> -struct IsTriviallyMoveConstructibleObject - : std::integral_constant< - bool, std::is_move_constructible< - type_traits_internal::SingleMemberUnion<T>>::value && - absl::is_trivially_destructible<T>::value> {}; - -template <class T> -struct IsTriviallyCopyConstructibleObject - : std::integral_constant< - bool, std::is_copy_constructible< - type_traits_internal::SingleMemberUnion<T>>::value && - absl::is_trivially_destructible<T>::value> {}; - -template <class T> -struct IsTriviallyMoveAssignableReference : std::false_type {}; - -template <class T> -struct IsTriviallyMoveAssignableReference<T&> - : absl::is_trivially_move_assignable<T>::type {}; - -template <class T> -struct IsTriviallyMoveAssignableReference<T&&> - : absl::is_trivially_move_assignable<T>::type {}; - -template <typename... Ts> -struct VoidTImpl { - using type = void; -}; - -// This trick to retrieve a default alignment is necessary for our -// implementation of aligned_storage_t to be consistent with any implementation -// of std::aligned_storage. -template <size_t Len, typename T = std::aligned_storage<Len>> -struct default_alignment_of_aligned_storage; - -template <size_t Len, size_t Align> -struct default_alignment_of_aligned_storage<Len, - std::aligned_storage<Len, Align>> { - static constexpr size_t value = Align; -}; - -//////////////////////////////// -// Library Fundamentals V2 TS // -//////////////////////////////// - -// NOTE: The `is_detected` family of templates here differ from the library -// fundamentals specification in that for library fundamentals, `Op<Args...>` is -// evaluated as soon as the type `is_detected<Op, Args...>` undergoes -// substitution, regardless of whether or not the `::value` is accessed. That -// is inconsistent with all other standard traits and prevents lazy evaluation -// in larger contexts (such as if the `is_detected` check is a trailing argument -// of a `conjunction`. This implementation opts to instead be lazy in the same -// way that the standard traits are (this "defect" of the detection idiom -// specifications has been reported). - -template <class Enabler, template <class...> class Op, class... Args> -struct is_detected_impl { - using type = std::false_type; -}; - -template <template <class...> class Op, class... Args> -struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> { - using type = std::true_type; -}; - -template <template <class...> class Op, class... Args> -struct is_detected : is_detected_impl<void, Op, Args...>::type {}; - -template <class Enabler, class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl { - using type = std::false_type; -}; - -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl< - typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type, - To, Op, Args...> { - using type = std::true_type; -}; - -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible - : is_detected_convertible_impl<void, To, Op, Args...>::type {}; - -template <typename T> -using IsCopyAssignableImpl = - decltype(std::declval<T&>() = std::declval<const T&>()); - -template <typename T> -using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>()); - -} // namespace type_traits_internal - -// MSVC 19.20 has a regression that causes our workarounds to fail, but their -// std forms now appear to be compliant. -#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920) - -template <typename T> -using is_copy_assignable = std::is_copy_assignable<T>; - -template <typename T> -using is_move_assignable = std::is_move_assignable<T>; - -#else - -template <typename T> -struct is_copy_assignable : type_traits_internal::is_detected< - type_traits_internal::IsCopyAssignableImpl, T> { -}; - -template <typename T> -struct is_move_assignable : type_traits_internal::is_detected< - type_traits_internal::IsMoveAssignableImpl, T> { -}; - -#endif - -// void_t() -// -// Ignores the type of any its arguments and returns `void`. In general, this -// metafunction allows you to create a general case that maps to `void` while -// allowing specializations that map to specific types. -// -// This metafunction is designed to be a drop-in replacement for the C++17 -// `std::void_t` metafunction. -// -// NOTE: `absl::void_t` does not use the standard-specified implementation so -// that it can remain compatible with gcc < 5.1. This can introduce slightly -// different behavior, such as when ordering partial specializations. -template <typename... Ts> -using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type; - -// conjunction -// -// Performs a compile-time logical AND operation on the passed types (which -// must have `::value` members convertible to `bool`. Short-circuits if it -// encounters any `false` members (and does not compare the `::value` members -// of any remaining arguments). -// -// 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 {}; - -template <typename T, typename... Ts> -struct conjunction<T, Ts...> - : std::conditional<T::value, conjunction<Ts...>, T>::type {}; - -template <typename T> -struct conjunction<T> : T {}; - -// disjunction -// -// Performs a compile-time logical OR operation on the passed types (which -// must have `::value` members convertible to `bool`. Short-circuits if it -// encounters any `true` members (and does not compare the `::value` members -// of any remaining arguments). -// -// 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 {}; - -template <typename T, typename... Ts> -struct disjunction<T, Ts...> : - std::conditional<T::value, T, disjunction<Ts...>>::type {}; - -template <typename T> -struct disjunction<T> : T {}; - -// negation -// -// Performs a compile-time logical NOT operation on the passed type (which -// must have `::value` members convertible to `bool`. -// -// This metafunction is designed to be a drop-in replacement for the C++17 -// `std::negation` metafunction. -template <typename T> -struct negation : std::integral_constant<bool, !T::value> {}; - -// is_function() -// -// Determines whether the passed type `T` is a function type. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_function()` metafunction for platforms that have incomplete C++11 -// support (such as libstdc++ 4.x). -// -// This metafunction works because appending `const` to a type does nothing to -// function types and reference types (and forms a const-qualified type -// otherwise). -template <typename T> -struct is_function - : std::integral_constant< - bool, !(std::is_reference<T>::value || - std::is_const<typename std::add_const<T>::type>::value)> {}; - -// is_trivially_destructible() -// -// Determines whether the passed type `T` is trivially destructible. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_destructible()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do -// fully support C++11, we check whether this yields the same result as the std -// implementation. -// -// NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >= -// 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always -// be present. These extensions are documented at -// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits. -template <typename T> -struct is_trivially_destructible - : std::integral_constant<bool, __has_trivial_destructor(T) && - std::is_destructible<T>::value> { -#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE - private: - static constexpr bool compliant = std::is_trivially_destructible<T>::value == - is_trivially_destructible::value; - static_assert(compliant || std::is_trivially_destructible<T>::value, - "Not compliant with std::is_trivially_destructible; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_destructible<T>::value, - "Not compliant with std::is_trivially_destructible; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE -}; - -// is_trivially_default_constructible() -// -// Determines whether the passed type `T` is trivially default constructible. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_default_constructible()` metafunction for platforms that -// have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that -// do fully support C++11, we check whether this yields the same result as the -// std implementation. -// -// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop] -// "The predicate condition for a template specialization is_constructible<T, -// Args...> shall be satisfied if and only if the following variable -// definition would be well-formed for some invented variable t: -// -// T t(declval<Args>()...); -// -// is_trivially_constructible<T, Args...> additionally requires that the -// variable definition does not call any operation that is not trivial. -// For the purposes of this check, the call to std::declval is considered -// trivial." -// -// Notes from https://en.cppreference.com/w/cpp/types/is_constructible: -// In many implementations, is_nothrow_constructible also checks if the -// destructor throws because it is effectively noexcept(T(arg)). Same -// applies to is_trivially_constructible, which, in these implementations, also -// requires that the destructor is trivial. -// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 -// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116. -// -// "T obj();" need to be well-formed and not call any nontrivial operation. -// Nontrivially destructible types will cause the expression to be nontrivial. -template <typename T> -struct is_trivially_default_constructible - : std::integral_constant<bool, __has_trivial_constructor(T) && - std::is_default_constructible<T>::value && - is_trivially_destructible<T>::value> { -#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \ - !defined( \ - ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION) - private: - static constexpr bool compliant = - std::is_trivially_default_constructible<T>::value == - is_trivially_default_constructible::value; - static_assert(compliant || std::is_trivially_default_constructible<T>::value, - "Not compliant with std::is_trivially_default_constructible; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_default_constructible<T>::value, - "Not compliant with std::is_trivially_default_constructible; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE -}; - -// is_trivially_move_constructible() -// -// Determines whether the passed type `T` is trivially move constructible. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_move_constructible()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do -// fully support C++11, we check whether this yields the same result as the std -// implementation. -// -// NOTE: `T obj(declval<T>());` needs to be well-formed and not call any -// nontrivial operation. Nontrivially destructible types will cause the -// expression to be nontrivial. -template <typename T> -struct is_trivially_move_constructible - : std::conditional< - std::is_object<T>::value && !std::is_array<T>::value, - type_traits_internal::IsTriviallyMoveConstructibleObject<T>, - std::is_reference<T>>::type::type { -#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \ - !defined( \ - ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION) - private: - static constexpr bool compliant = - std::is_trivially_move_constructible<T>::value == - is_trivially_move_constructible::value; - static_assert(compliant || std::is_trivially_move_constructible<T>::value, - "Not compliant with std::is_trivially_move_constructible; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_move_constructible<T>::value, - "Not compliant with std::is_trivially_move_constructible; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE -}; - -// is_trivially_copy_constructible() -// -// Determines whether the passed type `T` is trivially copy constructible. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_copy_constructible()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do -// fully support C++11, we check whether this yields the same result as the std -// implementation. -// -// NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any -// nontrivial operation. Nontrivially destructible types will cause the -// expression to be nontrivial. -template <typename T> -struct is_trivially_copy_constructible - : std::conditional< - std::is_object<T>::value && !std::is_array<T>::value, - type_traits_internal::IsTriviallyCopyConstructibleObject<T>, - std::is_lvalue_reference<T>>::type::type { -#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \ - !defined( \ - ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION) - private: - static constexpr bool compliant = - std::is_trivially_copy_constructible<T>::value == - is_trivially_copy_constructible::value; - static_assert(compliant || std::is_trivially_copy_constructible<T>::value, - "Not compliant with std::is_trivially_copy_constructible; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_copy_constructible<T>::value, - "Not compliant with std::is_trivially_copy_constructible; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE -}; - -// is_trivially_move_assignable() -// -// Determines whether the passed type `T` is trivially move assignable. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_move_assignable()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do -// fully support C++11, we check whether this yields the same result as the std -// implementation. -// -// NOTE: `is_assignable<T, U>::value` is `true` if the expression -// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated -// operand. `is_trivially_assignable<T, U>` requires the assignment to call no -// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply -// `is_trivially_assignable<T&, T>`. -template <typename T> -struct is_trivially_move_assignable - : std::conditional< - std::is_object<T>::value && !std::is_array<T>::value && - std::is_move_assignable<T>::value, - std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>, - type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type:: - type { -#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE - private: - static constexpr bool compliant = - std::is_trivially_move_assignable<T>::value == - is_trivially_move_assignable::value; - static_assert(compliant || std::is_trivially_move_assignable<T>::value, - "Not compliant with std::is_trivially_move_assignable; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_move_assignable<T>::value, - "Not compliant with std::is_trivially_move_assignable; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE -}; - -// is_trivially_copy_assignable() -// -// Determines whether the passed type `T` is trivially copy assignable. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_copy_assignable()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do -// fully support C++11, we check whether this yields the same result as the std -// implementation. -// -// NOTE: `is_assignable<T, U>::value` is `true` if the expression -// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated -// operand. `is_trivially_assignable<T, U>` requires the assignment to call no -// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply -// `is_trivially_assignable<T&, const T&>`. -template <typename T> -struct is_trivially_copy_assignable - : std::integral_constant< - bool, __has_trivial_assign(typename std::remove_reference<T>::type) && - absl::is_copy_assignable<T>::value> { -#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE - private: - static constexpr bool compliant = - std::is_trivially_copy_assignable<T>::value == - is_trivially_copy_assignable::value; - static_assert(compliant || std::is_trivially_copy_assignable<T>::value, - "Not compliant with std::is_trivially_copy_assignable; " - "Standard: false, Implementation: true"); - static_assert(compliant || !std::is_trivially_copy_assignable<T>::value, - "Not compliant with std::is_trivially_copy_assignable; " - "Standard: true, Implementation: false"); -#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE -}; - -namespace type_traits_internal { -// is_trivially_copyable() -// -// Determines whether the passed type `T` is trivially copyable. -// -// This metafunction is designed to be a drop-in replacement for the C++11 -// `std::is_trivially_copyable()` metafunction for platforms that have -// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition -// of TriviallyCopyable. -// -// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move -// constructors/assignment operators are trivial or deleted, T has at least -// one non-deleted copy/move constructor/assignment operator, and T is trivially -// destructible. Arrays of trivially copyable types are trivially copyable. -// -// We expose this metafunction only for internal use within absl. -template <typename T> -class is_trivially_copyable_impl { - using ExtentsRemoved = typename std::remove_all_extents<T>::type; - static constexpr bool kIsCopyOrMoveConstructible = - std::is_copy_constructible<ExtentsRemoved>::value || - std::is_move_constructible<ExtentsRemoved>::value; - static constexpr bool kIsCopyOrMoveAssignable = - absl::is_copy_assignable<ExtentsRemoved>::value || - absl::is_move_assignable<ExtentsRemoved>::value; - - public: - static constexpr bool kValue = - (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) && - (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) && - (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) && - is_trivially_destructible<ExtentsRemoved>::value && - // We need to check for this explicitly because otherwise we'll say - // references are trivial copyable when compiled by MSVC. - !std::is_reference<ExtentsRemoved>::value; -}; - -template <typename T> -struct is_trivially_copyable - : std::integral_constant< - bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {}; -} // namespace type_traits_internal - -// ----------------------------------------------------------------------------- -// C++14 "_t" trait aliases -// ----------------------------------------------------------------------------- - -template <typename T> -using remove_cv_t = typename std::remove_cv<T>::type; - -template <typename T> -using remove_const_t = typename std::remove_const<T>::type; - -template <typename T> -using remove_volatile_t = typename std::remove_volatile<T>::type; - -template <typename T> -using add_cv_t = typename std::add_cv<T>::type; - -template <typename T> -using add_const_t = typename std::add_const<T>::type; - -template <typename T> -using add_volatile_t = typename std::add_volatile<T>::type; - -template <typename T> -using remove_reference_t = typename std::remove_reference<T>::type; - -template <typename T> -using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type; - -template <typename T> -using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type; - -template <typename T> -using remove_pointer_t = typename std::remove_pointer<T>::type; - -template <typename T> -using add_pointer_t = typename std::add_pointer<T>::type; - -template <typename T> -using make_signed_t = typename std::make_signed<T>::type; - -template <typename T> -using make_unsigned_t = typename std::make_unsigned<T>::type; - -template <typename T> -using remove_extent_t = typename std::remove_extent<T>::type; - -template <typename T> -using remove_all_extents_t = typename std::remove_all_extents<T>::type; - -template <size_t Len, size_t Align = type_traits_internal:: - default_alignment_of_aligned_storage<Len>::value> -using aligned_storage_t = typename std::aligned_storage<Len, Align>::type; - -template <typename T> -using decay_t = typename std::decay<T>::type; - -template <bool B, typename T = void> -using enable_if_t = typename std::enable_if<B, T>::type; - -template <bool B, typename T, typename F> -using conditional_t = typename std::conditional<B, T, F>::type; - -template <typename... T> -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 __cplusplus >= 201703L -// std::result_of is deprecated (C++17) or removed (C++20) -template<typename> struct result_of; -template<typename F, typename... Args> -struct result_of<F(Args...)> : std::invoke_result<F, Args...> {}; -#else -template<typename F> using result_of = std::result_of<F>; -#endif - -} // namespace type_traits_internal - -template<typename F> -using result_of_t = typename type_traits_internal::result_of<F>::type; - -namespace type_traits_internal { -// In MSVC we can't probe std::hash or stdext::hash because it triggers a -// static_assert instead of failing substitution. Libc++ prior to 4.0 -// also used a static_assert. -// -#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \ - _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11) -#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0 -#else -#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1 -#endif - -#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -template <typename Key, typename = size_t> -struct IsHashable : std::true_type {}; -#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ -template <typename Key, typename = void> -struct IsHashable : std::false_type {}; - -template <typename Key> -struct IsHashable< - Key, - absl::enable_if_t<std::is_convertible< - decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())), - std::size_t>::value>> : std::true_type {}; -#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - -struct AssertHashEnabledHelper { - private: - static void Sink(...) {} - struct NAT {}; - - template <class Key> - static auto GetReturnType(int) - -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>())); - template <class Key> - static NAT GetReturnType(...); - - template <class Key> - static std::nullptr_t DoIt() { - static_assert(IsHashable<Key>::value, - "std::hash<Key> does not provide a call operator"); - static_assert( - std::is_default_constructible<std::hash<Key>>::value, - "std::hash<Key> must be default constructible when it is enabled"); - static_assert( - std::is_copy_constructible<std::hash<Key>>::value, - "std::hash<Key> must be copy constructible when it is enabled"); - static_assert(absl::is_copy_assignable<std::hash<Key>>::value, - "std::hash<Key> must be copy assignable when it is enabled"); - // is_destructible is unchecked as it's implied by each of the - // is_constructible checks. - using ReturnType = decltype(GetReturnType<Key>(0)); - static_assert(std::is_same<ReturnType, NAT>::value || - std::is_same<ReturnType, size_t>::value, - "std::hash<Key> must return size_t"); - return nullptr; - } - - template <class... Ts> - friend void AssertHashEnabled(); -}; - -template <class... Ts> -inline void AssertHashEnabled() { - using Helper = AssertHashEnabledHelper; - Helper::Sink(Helper::DoIt<Ts>()...); -} - -} // namespace type_traits_internal - -// An internal namespace that is required to implement the C++17 swap traits. -// It is not further nested in type_traits_internal to avoid long symbol names. -namespace swap_internal { - -// Necessary for the traits. -using std::swap; - -// This declaration prevents global `swap` and `absl::swap` overloads from being -// considered unless ADL picks them up. -void swap(); - -template <class T> -using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>())); - -// NOTE: This dance with the default template parameter is for MSVC. -template <class T, - class IsNoexcept = std::integral_constant< - bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>> -using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type; - -// IsSwappable -// -// Determines whether the standard swap idiom is a valid expression for -// arguments of type `T`. -template <class T> -struct IsSwappable - : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {}; - -// IsNothrowSwappable -// -// Determines whether the standard swap idiom is a valid expression for -// arguments of type `T` and is noexcept. -template <class T> -struct IsNothrowSwappable - : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {}; - -// Swap() -// -// Performs the swap idiom from a namespace where valid candidates may only be -// found in `std` or via ADL. -template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0> -void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) { - swap(lhs, rhs); -} - -// StdSwapIsUnconstrained -// -// Some standard library implementations are broken in that they do not -// constrain `std::swap`. This will effectively tell us if we are dealing with -// one of those implementations. -using StdSwapIsUnconstrained = IsSwappable<void()>; - -} // namespace swap_internal - -namespace type_traits_internal { - -// Make the swap-related traits/function accessible from this namespace. -using swap_internal::IsNothrowSwappable; -using swap_internal::IsSwappable; -using swap_internal::Swap; -using swap_internal::StdSwapIsUnconstrained; - -} // namespace type_traits_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_META_TYPE_TRAITS_H_ diff --git a/third_party/abseil_cpp/absl/meta/type_traits_test.cc b/third_party/abseil_cpp/absl/meta/type_traits_test.cc deleted file mode 100644 index 1aafd0d49a83..000000000000 --- a/third_party/abseil_cpp/absl/meta/type_traits_test.cc +++ /dev/null @@ -1,1368 +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/meta/type_traits.h" - -#include <cstdint> -#include <string> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" - -namespace { - -using ::testing::StaticAssertTypeEq; - -template <class T, class U> -struct simple_pair { - T first; - U second; -}; - -struct Dummy {}; - -struct ReturnType {}; -struct ConvertibleToReturnType { - operator ReturnType() const; // NOLINT -}; - -// Unique types used as parameter types for testing the detection idiom. -struct StructA {}; -struct StructB {}; -struct StructC {}; - -struct TypeWithBarFunction { - template <class T, - absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0> - ReturnType bar(T&&, const StructB&, StructC&&) &&; // NOLINT -}; - -struct TypeWithBarFunctionAndConvertibleReturnType { - template <class T, - absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0> - ConvertibleToReturnType bar(T&&, const StructB&, StructC&&) &&; // NOLINT -}; - -template <class Class, class... Ts> -using BarIsCallableImpl = - decltype(std::declval<Class>().bar(std::declval<Ts>()...)); - -template <class Class, class... T> -using BarIsCallable = - absl::type_traits_internal::is_detected<BarIsCallableImpl, Class, T...>; - -template <class Class, class... T> -using BarIsCallableConv = absl::type_traits_internal::is_detected_convertible< - ReturnType, BarIsCallableImpl, Class, T...>; - -// NOTE: Test of detail type_traits_internal::is_detected. -TEST(IsDetectedTest, BasicUsage) { - EXPECT_TRUE((BarIsCallable<TypeWithBarFunction, StructA&, const StructB&, - StructC>::value)); - EXPECT_TRUE( - (BarIsCallable<TypeWithBarFunction, StructA&, StructB&, StructC>::value)); - EXPECT_TRUE( - (BarIsCallable<TypeWithBarFunction, StructA&, StructB, StructC>::value)); - - EXPECT_FALSE((BarIsCallable<int, StructA&, const StructB&, StructC>::value)); - EXPECT_FALSE((BarIsCallable<TypeWithBarFunction&, StructA&, const StructB&, - StructC>::value)); - EXPECT_FALSE((BarIsCallable<TypeWithBarFunction, StructA, const StructB&, - StructC>::value)); -} - -// NOTE: Test of detail type_traits_internal::is_detected_convertible. -TEST(IsDetectedConvertibleTest, BasicUsage) { - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, const StructB&, - StructC>::value)); - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB&, - StructC>::value)); - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB, - StructC>::value)); - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, - StructA&, const StructB&, StructC>::value)); - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, - StructA&, StructB&, StructC>::value)); - EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, - StructA&, StructB, StructC>::value)); - - EXPECT_FALSE( - (BarIsCallableConv<int, StructA&, const StructB&, StructC>::value)); - EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction&, StructA&, - const StructB&, StructC>::value)); - EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction, StructA, const StructB&, - StructC>::value)); - EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType&, - StructA&, const StructB&, StructC>::value)); - EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, - StructA, const StructB&, StructC>::value)); -} - -TEST(VoidTTest, BasicUsage) { - StaticAssertTypeEq<void, absl::void_t<Dummy>>(); - StaticAssertTypeEq<void, absl::void_t<Dummy, Dummy, Dummy>>(); -} - -TEST(ConjunctionTest, BasicBooleanLogic) { - EXPECT_TRUE(absl::conjunction<>::value); - EXPECT_TRUE(absl::conjunction<std::true_type>::value); - EXPECT_TRUE((absl::conjunction<std::true_type, std::true_type>::value)); - EXPECT_FALSE((absl::conjunction<std::true_type, std::false_type>::value)); - EXPECT_FALSE((absl::conjunction<std::false_type, std::true_type>::value)); - EXPECT_FALSE((absl::conjunction<std::false_type, std::false_type>::value)); -} - -struct MyTrueType { - static constexpr bool value = true; -}; - -struct MyFalseType { - static constexpr bool value = false; -}; - -TEST(ConjunctionTest, ShortCircuiting) { - EXPECT_FALSE( - (absl::conjunction<std::true_type, std::false_type, Dummy>::value)); - EXPECT_TRUE((std::is_base_of<MyFalseType, - absl::conjunction<std::true_type, MyFalseType, - std::false_type>>::value)); - EXPECT_TRUE( - (std::is_base_of<MyTrueType, - absl::conjunction<std::true_type, MyTrueType>>::value)); -} - -TEST(DisjunctionTest, BasicBooleanLogic) { - EXPECT_FALSE(absl::disjunction<>::value); - EXPECT_FALSE(absl::disjunction<std::false_type>::value); - EXPECT_TRUE((absl::disjunction<std::true_type, std::true_type>::value)); - EXPECT_TRUE((absl::disjunction<std::true_type, std::false_type>::value)); - EXPECT_TRUE((absl::disjunction<std::false_type, std::true_type>::value)); - EXPECT_FALSE((absl::disjunction<std::false_type, std::false_type>::value)); -} - -TEST(DisjunctionTest, ShortCircuiting) { - EXPECT_TRUE( - (absl::disjunction<std::false_type, std::true_type, Dummy>::value)); - EXPECT_TRUE(( - std::is_base_of<MyTrueType, absl::disjunction<std::false_type, MyTrueType, - std::true_type>>::value)); - EXPECT_TRUE(( - std::is_base_of<MyFalseType, - absl::disjunction<std::false_type, MyFalseType>>::value)); -} - -TEST(NegationTest, BasicBooleanLogic) { - EXPECT_FALSE(absl::negation<std::true_type>::value); - EXPECT_FALSE(absl::negation<MyTrueType>::value); - EXPECT_TRUE(absl::negation<std::false_type>::value); - EXPECT_TRUE(absl::negation<MyFalseType>::value); -} - -// all member functions are trivial -class Trivial { - int n_; -}; - -struct TrivialDestructor { - ~TrivialDestructor() = default; -}; - -struct NontrivialDestructor { - ~NontrivialDestructor() {} -}; - -struct DeletedDestructor { - ~DeletedDestructor() = delete; -}; - -class TrivialDefaultCtor { - public: - TrivialDefaultCtor() = default; - explicit TrivialDefaultCtor(int n) : n_(n) {} - - private: - int n_; -}; - -class NontrivialDefaultCtor { - public: - NontrivialDefaultCtor() : n_(1) {} - - private: - int n_; -}; - -class DeletedDefaultCtor { - public: - DeletedDefaultCtor() = delete; - explicit DeletedDefaultCtor(int n) : n_(n) {} - - private: - int n_; -}; - -class TrivialMoveCtor { - public: - explicit TrivialMoveCtor(int n) : n_(n) {} - TrivialMoveCtor(TrivialMoveCtor&&) = default; - TrivialMoveCtor& operator=(const TrivialMoveCtor& t) { - n_ = t.n_; - return *this; - } - - private: - int n_; -}; - -class NontrivialMoveCtor { - public: - explicit NontrivialMoveCtor(int n) : n_(n) {} - NontrivialMoveCtor(NontrivialMoveCtor&& t) noexcept : n_(t.n_) {} - NontrivialMoveCtor& operator=(const NontrivialMoveCtor&) = default; - - private: - int n_; -}; - -class TrivialCopyCtor { - public: - explicit TrivialCopyCtor(int n) : n_(n) {} - TrivialCopyCtor(const TrivialCopyCtor&) = default; - TrivialCopyCtor& operator=(const TrivialCopyCtor& t) { - n_ = t.n_; - return *this; - } - - private: - int n_; -}; - -class NontrivialCopyCtor { - public: - explicit NontrivialCopyCtor(int n) : n_(n) {} - NontrivialCopyCtor(const NontrivialCopyCtor& t) : n_(t.n_) {} - NontrivialCopyCtor& operator=(const NontrivialCopyCtor&) = default; - - private: - int n_; -}; - -class DeletedCopyCtor { - public: - explicit DeletedCopyCtor(int n) : n_(n) {} - DeletedCopyCtor(const DeletedCopyCtor&) = delete; - DeletedCopyCtor& operator=(const DeletedCopyCtor&) = default; - - private: - int n_; -}; - -class TrivialMoveAssign { - public: - explicit TrivialMoveAssign(int n) : n_(n) {} - TrivialMoveAssign(const TrivialMoveAssign& t) : n_(t.n_) {} - TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default; - ~TrivialMoveAssign() {} // can have nontrivial destructor - private: - int n_; -}; - -class NontrivialMoveAssign { - public: - explicit NontrivialMoveAssign(int n) : n_(n) {} - NontrivialMoveAssign(const NontrivialMoveAssign&) = default; - NontrivialMoveAssign& operator=(NontrivialMoveAssign&& t) noexcept { - n_ = t.n_; - return *this; - } - - private: - int n_; -}; - -class TrivialCopyAssign { - public: - explicit TrivialCopyAssign(int n) : n_(n) {} - TrivialCopyAssign(const TrivialCopyAssign& t) : n_(t.n_) {} - TrivialCopyAssign& operator=(const TrivialCopyAssign& t) = default; - ~TrivialCopyAssign() {} // can have nontrivial destructor - private: - int n_; -}; - -class NontrivialCopyAssign { - public: - explicit NontrivialCopyAssign(int n) : n_(n) {} - NontrivialCopyAssign(const NontrivialCopyAssign&) = default; - NontrivialCopyAssign& operator=(const NontrivialCopyAssign& t) { - n_ = t.n_; - return *this; - } - - private: - int n_; -}; - -class DeletedCopyAssign { - public: - explicit DeletedCopyAssign(int n) : n_(n) {} - DeletedCopyAssign(const DeletedCopyAssign&) = default; - DeletedCopyAssign& operator=(const DeletedCopyAssign&) = delete; - - private: - int n_; -}; - -struct MovableNonCopyable { - MovableNonCopyable() = default; - MovableNonCopyable(const MovableNonCopyable&) = delete; - MovableNonCopyable(MovableNonCopyable&&) = default; - MovableNonCopyable& operator=(const MovableNonCopyable&) = delete; - MovableNonCopyable& operator=(MovableNonCopyable&&) = default; -}; - -struct NonCopyableOrMovable { - NonCopyableOrMovable() = default; - NonCopyableOrMovable(const NonCopyableOrMovable&) = delete; - NonCopyableOrMovable(NonCopyableOrMovable&&) = delete; - NonCopyableOrMovable& operator=(const NonCopyableOrMovable&) = delete; - NonCopyableOrMovable& operator=(NonCopyableOrMovable&&) = delete; -}; - -class Base { - public: - virtual ~Base() {} -}; - -// Old versions of libc++, around Clang 3.5 to 3.6, consider deleted destructors -// as also being trivial. With the resolution of CWG 1928 and CWG 1734, this -// is no longer considered true and has thus been amended. -// Compiler Explorer: https://godbolt.org/g/zT59ZL -// CWG issue 1734: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1734 -// CWG issue 1928: http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1928 -#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 3700 -#define ABSL_TRIVIALLY_DESTRUCTIBLE_CONSIDER_DELETED_DESTRUCTOR_NOT_TRIVIAL 1 -#endif - -// As of the moment, GCC versions >5.1 have a problem compiling for -// std::is_trivially_default_constructible<NontrivialDestructor[10]>, where -// NontrivialDestructor is a struct with a custom nontrivial destructor. Note -// that this problem only occurs for arrays of a known size, so something like -// std::is_trivially_default_constructible<NontrivialDestructor[]> does not -// have any problems. -// Compiler Explorer: https://godbolt.org/g/dXRbdK -// GCC bug 83689: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83689 -#if defined(__clang__) || defined(_MSC_VER) || \ - (defined(__GNUC__) && __GNUC__ < 5) -#define ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL 1 -#endif - -TEST(TypeTraitsTest, TestIsFunction) { - struct Callable { - void operator()() {} - }; - EXPECT_TRUE(absl::is_function<void()>::value); - EXPECT_TRUE(absl::is_function<void()&>::value); - EXPECT_TRUE(absl::is_function<void() const>::value); - EXPECT_TRUE(absl::is_function<void() noexcept>::value); - EXPECT_TRUE(absl::is_function<void(...) noexcept>::value); - - EXPECT_FALSE(absl::is_function<void(*)()>::value); - EXPECT_FALSE(absl::is_function<void(&)()>::value); - EXPECT_FALSE(absl::is_function<int>::value); - EXPECT_FALSE(absl::is_function<Callable>::value); -} - -TEST(TypeTraitsTest, TestTrivialDestructor) { - // Verify that arithmetic types and pointers have trivial destructors. - EXPECT_TRUE(absl::is_trivially_destructible<bool>::value); - EXPECT_TRUE(absl::is_trivially_destructible<char>::value); - EXPECT_TRUE(absl::is_trivially_destructible<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_destructible<signed char>::value); - EXPECT_TRUE(absl::is_trivially_destructible<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_destructible<int>::value); - EXPECT_TRUE(absl::is_trivially_destructible<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_destructible<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_destructible<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_destructible<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_destructible<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_destructible<float>::value); - EXPECT_TRUE(absl::is_trivially_destructible<double>::value); - EXPECT_TRUE(absl::is_trivially_destructible<long double>::value); - EXPECT_TRUE(absl::is_trivially_destructible<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_destructible<Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_destructible<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_destructible<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_destructible<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_destructible<Trivial**>::value); - - // classes with destructors - EXPECT_TRUE(absl::is_trivially_destructible<Trivial>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivialDestructor>::value); - - // Verify that types with a nontrivial or deleted destructor - // are marked as such. - EXPECT_FALSE(absl::is_trivially_destructible<NontrivialDestructor>::value); -#ifdef ABSL_TRIVIALLY_DESTRUCTIBLE_CONSIDER_DELETED_DESTRUCTOR_NOT_TRIVIAL - EXPECT_FALSE(absl::is_trivially_destructible<DeletedDestructor>::value); -#endif - - // simple_pair of such types is trivial - EXPECT_TRUE((absl::is_trivially_destructible<simple_pair<int, int>>::value)); - EXPECT_TRUE((absl::is_trivially_destructible< - simple_pair<Trivial, TrivialDestructor>>::value)); - - // Verify that types without trivial destructors are correctly marked as such. - EXPECT_FALSE(absl::is_trivially_destructible<std::string>::value); - EXPECT_FALSE(absl::is_trivially_destructible<std::vector<int>>::value); - - // Verify that simple_pairs of types without trivial destructors - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_destructible< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_destructible< - simple_pair<std::string, int>>::value)); - - // array of such types is trivial - using int10 = int[10]; - EXPECT_TRUE(absl::is_trivially_destructible<int10>::value); - using Trivial10 = Trivial[10]; - EXPECT_TRUE(absl::is_trivially_destructible<Trivial10>::value); - using TrivialDestructor10 = TrivialDestructor[10]; - EXPECT_TRUE(absl::is_trivially_destructible<TrivialDestructor10>::value); - - // Conversely, the opposite also holds. - using NontrivialDestructor10 = NontrivialDestructor[10]; - EXPECT_FALSE(absl::is_trivially_destructible<NontrivialDestructor10>::value); -} - -TEST(TypeTraitsTest, TestTrivialDefaultCtor) { - // arithmetic types and pointers have trivial default constructors. - EXPECT_TRUE(absl::is_trivially_default_constructible<bool>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<char>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<signed char>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<int>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<float>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<double>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<long double>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial*>::value); - EXPECT_TRUE( - absl::is_trivially_default_constructible<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial**>::value); - - // types with compiler generated default ctors - EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial>::value); - EXPECT_TRUE( - absl::is_trivially_default_constructible<TrivialDefaultCtor>::value); - - // Verify that types without them are not. - EXPECT_FALSE( - absl::is_trivially_default_constructible<NontrivialDefaultCtor>::value); - EXPECT_FALSE( - absl::is_trivially_default_constructible<DeletedDefaultCtor>::value); - - // types with nontrivial destructor are nontrivial - EXPECT_FALSE( - absl::is_trivially_default_constructible<NontrivialDestructor>::value); - - // types with vtables - EXPECT_FALSE(absl::is_trivially_default_constructible<Base>::value); - - // Verify that simple_pair has trivial constructors where applicable. - EXPECT_TRUE((absl::is_trivially_default_constructible< - simple_pair<int, char*>>::value)); - EXPECT_TRUE((absl::is_trivially_default_constructible< - simple_pair<int, Trivial>>::value)); - EXPECT_TRUE((absl::is_trivially_default_constructible< - simple_pair<int, TrivialDefaultCtor>>::value)); - - // Verify that types without trivial constructors are - // correctly marked as such. - EXPECT_FALSE(absl::is_trivially_default_constructible<std::string>::value); - EXPECT_FALSE( - absl::is_trivially_default_constructible<std::vector<int>>::value); - - // Verify that simple_pairs of types without trivial constructors - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_default_constructible< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_default_constructible< - simple_pair<std::string, int>>::value)); - - // Verify that arrays of such types are trivially default constructible - using int10 = int[10]; - EXPECT_TRUE(absl::is_trivially_default_constructible<int10>::value); - using Trivial10 = Trivial[10]; - EXPECT_TRUE(absl::is_trivially_default_constructible<Trivial10>::value); - using TrivialDefaultCtor10 = TrivialDefaultCtor[10]; - EXPECT_TRUE( - absl::is_trivially_default_constructible<TrivialDefaultCtor10>::value); - - // Conversely, the opposite also holds. -#ifdef ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL - using NontrivialDefaultCtor10 = NontrivialDefaultCtor[10]; - EXPECT_FALSE( - absl::is_trivially_default_constructible<NontrivialDefaultCtor10>::value); -#endif -} - -// GCC prior to 7.4 had a bug in its trivially-constructible traits -// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654). -// This test makes sure that we do not depend on the trait in these cases when -// implementing absl triviality traits. - -template <class T> -struct BadConstructors { - BadConstructors() { static_assert(T::value, ""); } - - BadConstructors(BadConstructors&&) { static_assert(T::value, ""); } - - BadConstructors(const BadConstructors&) { static_assert(T::value, ""); } -}; - -TEST(TypeTraitsTest, TestTrivialityBadConstructors) { - using BadType = BadConstructors<int>; - - EXPECT_FALSE(absl::is_trivially_default_constructible<BadType>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<BadType>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<BadType>::value); -} - -TEST(TypeTraitsTest, TestTrivialMoveCtor) { - // Verify that arithmetic types and pointers have trivial move - // constructors. - EXPECT_TRUE(absl::is_trivially_move_constructible<bool>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<char>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<signed char>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<int>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<float>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<double>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<long double>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial**>::value); - - // Reference types - EXPECT_TRUE(absl::is_trivially_move_constructible<int&>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<int&&>::value); - - // types with compiler generated move ctors - EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial>::value); - EXPECT_TRUE(absl::is_trivially_move_constructible<TrivialMoveCtor>::value); - - // Verify that types without them (i.e. nontrivial or deleted) are not. - EXPECT_FALSE( - absl::is_trivially_move_constructible<NontrivialCopyCtor>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<DeletedCopyCtor>::value); - EXPECT_FALSE( - absl::is_trivially_move_constructible<NonCopyableOrMovable>::value); - - // type with nontrivial destructor are nontrivial move construbtible - EXPECT_FALSE( - absl::is_trivially_move_constructible<NontrivialDestructor>::value); - - // types with vtables - EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value); - - // Verify that simple_pair of such types is trivially move constructible - EXPECT_TRUE( - (absl::is_trivially_move_constructible<simple_pair<int, char*>>::value)); - EXPECT_TRUE(( - absl::is_trivially_move_constructible<simple_pair<int, Trivial>>::value)); - EXPECT_TRUE((absl::is_trivially_move_constructible< - simple_pair<int, TrivialMoveCtor>>::value)); - - // Verify that types without trivial move constructors are - // correctly marked as such. - EXPECT_FALSE(absl::is_trivially_move_constructible<std::string>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<std::vector<int>>::value); - - // Verify that simple_pairs of types without trivial move constructors - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_move_constructible< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_move_constructible< - simple_pair<std::string, int>>::value)); - - // Verify that arrays are not - using int10 = int[10]; - EXPECT_FALSE(absl::is_trivially_move_constructible<int10>::value); -} - -TEST(TypeTraitsTest, TestTrivialCopyCtor) { - // Verify that arithmetic types and pointers have trivial copy - // constructors. - EXPECT_TRUE(absl::is_trivially_copy_constructible<bool>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<char>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<signed char>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<int>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<float>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<double>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<long double>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial**>::value); - - // Reference types - EXPECT_TRUE(absl::is_trivially_copy_constructible<int&>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<int&&>::value); - - // types with compiler generated copy ctors - EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivialCopyCtor>::value); - - // Verify that types without them (i.e. nontrivial or deleted) are not. - EXPECT_FALSE( - absl::is_trivially_copy_constructible<NontrivialCopyCtor>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<DeletedCopyCtor>::value); - EXPECT_FALSE( - absl::is_trivially_copy_constructible<MovableNonCopyable>::value); - EXPECT_FALSE( - absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value); - - // type with nontrivial destructor are nontrivial copy construbtible - EXPECT_FALSE( - absl::is_trivially_copy_constructible<NontrivialDestructor>::value); - - // types with vtables - EXPECT_FALSE(absl::is_trivially_copy_constructible<Base>::value); - - // Verify that simple_pair of such types is trivially copy constructible - EXPECT_TRUE( - (absl::is_trivially_copy_constructible<simple_pair<int, char*>>::value)); - EXPECT_TRUE(( - absl::is_trivially_copy_constructible<simple_pair<int, Trivial>>::value)); - EXPECT_TRUE((absl::is_trivially_copy_constructible< - simple_pair<int, TrivialCopyCtor>>::value)); - - // Verify that types without trivial copy constructors are - // correctly marked as such. - EXPECT_FALSE(absl::is_trivially_copy_constructible<std::string>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<std::vector<int>>::value); - - // Verify that simple_pairs of types without trivial copy constructors - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_copy_constructible< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_copy_constructible< - simple_pair<std::string, int>>::value)); - - // Verify that arrays are not - using int10 = int[10]; - EXPECT_FALSE(absl::is_trivially_copy_constructible<int10>::value); -} - -TEST(TypeTraitsTest, TestTrivialMoveAssign) { - // Verify that arithmetic types and pointers have trivial move - // assignment operators. - EXPECT_TRUE(absl::is_trivially_move_assignable<bool>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<char>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<signed char>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<int>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<float>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<double>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<long double>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial**>::value); - - // const qualified types are not assignable - EXPECT_FALSE(absl::is_trivially_move_assignable<const int>::value); - - // types with compiler generated move assignment - EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<TrivialMoveAssign>::value); - - // Verify that types without them (i.e. nontrivial or deleted) are not. - EXPECT_FALSE(absl::is_trivially_move_assignable<NontrivialCopyAssign>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<DeletedCopyAssign>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<NonCopyableOrMovable>::value); - - // types with vtables - EXPECT_FALSE(absl::is_trivially_move_assignable<Base>::value); - - // Verify that simple_pair is trivially assignable - EXPECT_TRUE( - (absl::is_trivially_move_assignable<simple_pair<int, char*>>::value)); - EXPECT_TRUE( - (absl::is_trivially_move_assignable<simple_pair<int, Trivial>>::value)); - EXPECT_TRUE((absl::is_trivially_move_assignable< - simple_pair<int, TrivialMoveAssign>>::value)); - - // Verify that types not trivially move assignable are - // correctly marked as such. - EXPECT_FALSE(absl::is_trivially_move_assignable<std::string>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<std::vector<int>>::value); - - // Verify that simple_pairs of types not trivially move assignable - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_move_assignable< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_move_assignable< - simple_pair<std::string, int>>::value)); - - // Verify that arrays are not trivially move assignable - using int10 = int[10]; - EXPECT_FALSE(absl::is_trivially_move_assignable<int10>::value); - - // Verify that references are handled correctly - EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&&>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&>::value); -} - -TEST(TypeTraitsTest, TestTrivialCopyAssign) { - // Verify that arithmetic types and pointers have trivial copy - // assignment operators. - EXPECT_TRUE(absl::is_trivially_copy_assignable<bool>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<char>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<unsigned char>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<signed char>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<wchar_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<unsigned int>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<int16_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<uint16_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<int64_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<uint64_t>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<float>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<double>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<long double>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<std::string*>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<const std::string*>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<const Trivial*>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<std::string**>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial**>::value); - - // const qualified types are not assignable - EXPECT_FALSE(absl::is_trivially_copy_assignable<const int>::value); - - // types with compiler generated copy assignment - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivialCopyAssign>::value); - - // Verify that types without them (i.e. nontrivial or deleted) are not. - EXPECT_FALSE(absl::is_trivially_copy_assignable<NontrivialCopyAssign>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<DeletedCopyAssign>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<MovableNonCopyable>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyableOrMovable>::value); - - // types with vtables - EXPECT_FALSE(absl::is_trivially_copy_assignable<Base>::value); - - // Verify that simple_pair is trivially assignable - EXPECT_TRUE( - (absl::is_trivially_copy_assignable<simple_pair<int, char*>>::value)); - EXPECT_TRUE( - (absl::is_trivially_copy_assignable<simple_pair<int, Trivial>>::value)); - EXPECT_TRUE((absl::is_trivially_copy_assignable< - simple_pair<int, TrivialCopyAssign>>::value)); - - // Verify that types not trivially copy assignable are - // correctly marked as such. - EXPECT_FALSE(absl::is_trivially_copy_assignable<std::string>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<std::vector<int>>::value); - - // Verify that simple_pairs of types not trivially copy assignable - // are not marked as trivial. - EXPECT_FALSE((absl::is_trivially_copy_assignable< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::is_trivially_copy_assignable< - simple_pair<std::string, int>>::value)); - - // Verify that arrays are not trivially copy assignable - using int10 = int[10]; - EXPECT_FALSE(absl::is_trivially_copy_assignable<int10>::value); - - // Verify that references are handled correctly - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&&>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value); -} - -TEST(TypeTraitsTest, TestTriviallyCopyable) { - // Verify that arithmetic types and pointers are trivially copyable. - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<bool>::value); - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<char>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<unsigned char>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<signed char>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<wchar_t>::value); - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<unsigned int>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<int16_t>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<uint16_t>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<int64_t>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<uint64_t>::value); - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<float>::value); - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<double>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<long double>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<std::string*>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<Trivial*>::value); - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< - const std::string*>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<const Trivial*>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<std::string**>::value); - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<Trivial**>::value); - - // const qualified types are not assignable but are constructible - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<const int>::value); - - // Trivial copy constructor/assignment and destructor. - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<Trivial>::value); - // Trivial copy assignment, but non-trivial copy constructor/destructor. - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - TrivialCopyAssign>::value); - // Trivial copy constructor, but non-trivial assignment. - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - TrivialCopyCtor>::value); - - // Types with a non-trivial copy constructor/assignment - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - NontrivialCopyCtor>::value); - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - NontrivialCopyAssign>::value); - - // Types without copy constructor/assignment, but with move - // MSVC disagrees with other compilers about this: - // EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< - // MovableNonCopyable>::value); - - // Types without copy/move constructor/assignment - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - NonCopyableOrMovable>::value); - - // No copy assign, but has trivial copy constructor. - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable< - DeletedCopyAssign>::value); - - // types with vtables - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<Base>::value); - - // Verify that simple_pair is trivially copyable if members are - EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable< - simple_pair<int, char*>>::value)); - EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable< - simple_pair<int, Trivial>>::value)); - - // Verify that types not trivially copyable are - // correctly marked as such. - EXPECT_FALSE( - absl::type_traits_internal::is_trivially_copyable<std::string>::value); - EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable< - std::vector<int>>::value); - - // Verify that simple_pairs of types not trivially copyable - // are not marked as trivial. - EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< - simple_pair<int, std::string>>::value)); - EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< - simple_pair<std::string, int>>::value)); - EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable< - simple_pair<int, TrivialCopyAssign>>::value)); - - // Verify that arrays of trivially copyable types are trivially copyable - using int10 = int[10]; - EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int10>::value); - using int10x10 = int[10][10]; - EXPECT_TRUE( - absl::type_traits_internal::is_trivially_copyable<int10x10>::value); - - // Verify that references are handled correctly - EXPECT_FALSE( - absl::type_traits_internal::is_trivially_copyable<Trivial&&>::value); - EXPECT_FALSE( - absl::type_traits_internal::is_trivially_copyable<Trivial&>::value); -} - -#define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \ - EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \ - absl::trait_name##_t<__VA_ARGS__>>::value)) - -TEST(TypeTraitsTest, TestRemoveCVAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const volatile int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const volatile int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const volatile int); -} - -TEST(TypeTraitsTest, TestAddCVAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const volatile int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const volatile int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const volatile int); -} - -TEST(TypeTraitsTest, TestReferenceAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&&); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&&); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&&); -} - -TEST(TypeTraitsTest, TestPointerAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, int*); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, volatile int*); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, volatile int); -} - -TEST(TypeTraitsTest, TestSignednessAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, unsigned); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile unsigned); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, unsigned); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile unsigned); -} - -TEST(TypeTraitsTest, TestExtentAliases) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1][1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[][1]); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1][1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[][1]); -} - -TEST(TypeTraitsTest, TestAlignedStorageAlias) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 1); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 2); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 3); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 4); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 5); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 6); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 7); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 8); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 9); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 10); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 11); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 12); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 13); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 14); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 15); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 16); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 17); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 18); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 19); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 20); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 21); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 22); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 23); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 24); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 25); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 26); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 27); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 28); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 29); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 30); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 31); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 32); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 33); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 1, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 2, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 3, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 4, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 5, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 6, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 7, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 8, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 9, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 10, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 11, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 12, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 13, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 14, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 15, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 16, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 17, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 18, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 19, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 20, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 21, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 22, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 23, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 24, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 25, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 26, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 27, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 28, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 29, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 30, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 31, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 32, 128); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(aligned_storage, 33, 128); -} - -TEST(TypeTraitsTest, TestDecay) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1][1]); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[][1]); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int()); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float)); // NOLINT - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...)); // NOLINT -} - -struct TypeA {}; -struct TypeB {}; -struct TypeC {}; -struct TypeD {}; - -template <typename T> -struct Wrap {}; - -enum class TypeEnum { A, B, C, D }; - -struct GetTypeT { - template <typename T, - absl::enable_if_t<std::is_same<T, TypeA>::value, int> = 0> - TypeEnum operator()(Wrap<T>) const { - return TypeEnum::A; - } - - template <typename T, - absl::enable_if_t<std::is_same<T, TypeB>::value, int> = 0> - TypeEnum operator()(Wrap<T>) const { - return TypeEnum::B; - } - - template <typename T, - absl::enable_if_t<std::is_same<T, TypeC>::value, int> = 0> - TypeEnum operator()(Wrap<T>) const { - return TypeEnum::C; - } - - // NOTE: TypeD is intentionally not handled -} constexpr GetType = {}; - -TEST(TypeTraitsTest, TestEnableIf) { - EXPECT_EQ(TypeEnum::A, GetType(Wrap<TypeA>())); - EXPECT_EQ(TypeEnum::B, GetType(Wrap<TypeB>())); - EXPECT_EQ(TypeEnum::C, GetType(Wrap<TypeC>())); -} - -TEST(TypeTraitsTest, TestConditional) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, true, int, char); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, false, int, char); -} - -// TODO(calabrese) Check with specialized std::common_type -TEST(TypeTraitsTest, TestCommonType) { - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int); - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char&); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int&); -} - -TEST(TypeTraitsTest, TestUnderlyingType) { - enum class enum_char : char {}; - enum class enum_long_long : long long {}; // NOLINT(runtime/int) - - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_char); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_long_long); -} - -struct GetTypeExtT { - template <typename T> - absl::result_of_t<const GetTypeT&(T)> operator()(T&& arg) const { - return GetType(std::forward<T>(arg)); - } - - TypeEnum operator()(Wrap<TypeD>) const { return TypeEnum::D; } -} constexpr GetTypeExt = {}; - -TEST(TypeTraitsTest, TestResultOf) { - EXPECT_EQ(TypeEnum::A, GetTypeExt(Wrap<TypeA>())); - EXPECT_EQ(TypeEnum::B, GetTypeExt(Wrap<TypeB>())); - EXPECT_EQ(TypeEnum::C, GetTypeExt(Wrap<TypeC>())); - EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap<TypeD>())); -} - -template <typename T> -bool TestCopyAssign() { - return absl::is_copy_assignable<T>::value == - std::is_copy_assignable<T>::value; -} - -TEST(TypeTraitsTest, IsCopyAssignable) { - EXPECT_TRUE(TestCopyAssign<int>()); - EXPECT_TRUE(TestCopyAssign<int&>()); - EXPECT_TRUE(TestCopyAssign<int&&>()); - - struct S {}; - EXPECT_TRUE(TestCopyAssign<S>()); - EXPECT_TRUE(TestCopyAssign<S&>()); - EXPECT_TRUE(TestCopyAssign<S&&>()); - - class C { - public: - explicit C(C* c) : c_(c) {} - ~C() { delete c_; } - - private: - C* c_; - }; - EXPECT_TRUE(TestCopyAssign<C>()); - EXPECT_TRUE(TestCopyAssign<C&>()); - EXPECT_TRUE(TestCopyAssign<C&&>()); - - // Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases -#ifndef _LIBCPP_VERSION - EXPECT_TRUE(TestCopyAssign<int()>()); - EXPECT_TRUE(TestCopyAssign<int(int) const>()); - EXPECT_TRUE(TestCopyAssign<int(...) volatile&>()); - EXPECT_TRUE(TestCopyAssign<int(int, ...) const volatile&&>()); -#endif // _LIBCPP_VERSION -} - -template <typename T> -bool TestMoveAssign() { - return absl::is_move_assignable<T>::value == - std::is_move_assignable<T>::value; -} - -TEST(TypeTraitsTest, IsMoveAssignable) { - EXPECT_TRUE(TestMoveAssign<int>()); - EXPECT_TRUE(TestMoveAssign<int&>()); - EXPECT_TRUE(TestMoveAssign<int&&>()); - - struct S {}; - EXPECT_TRUE(TestMoveAssign<S>()); - EXPECT_TRUE(TestMoveAssign<S&>()); - EXPECT_TRUE(TestMoveAssign<S&&>()); - - class C { - public: - explicit C(C* c) : c_(c) {} - ~C() { delete c_; } - void operator=(const C&) = delete; - void operator=(C&&) = delete; - - private: - C* c_; - }; - EXPECT_TRUE(TestMoveAssign<C>()); - EXPECT_TRUE(TestMoveAssign<C&>()); - EXPECT_TRUE(TestMoveAssign<C&&>()); - - // Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases -#ifndef _LIBCPP_VERSION - EXPECT_TRUE(TestMoveAssign<int()>()); - EXPECT_TRUE(TestMoveAssign<int(int) const>()); - EXPECT_TRUE(TestMoveAssign<int(...) volatile&>()); - EXPECT_TRUE(TestMoveAssign<int(int, ...) const volatile&&>()); -#endif // _LIBCPP_VERSION -} - -namespace adl_namespace { - -struct DeletedSwap { -}; - -void swap(DeletedSwap&, DeletedSwap&) = delete; - -struct SpecialNoexceptSwap { - SpecialNoexceptSwap(SpecialNoexceptSwap&&) {} - SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; } - ~SpecialNoexceptSwap() = default; -}; - -void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {} - -} // namespace adl_namespace - -TEST(TypeTraitsTest, IsSwappable) { - using absl::type_traits_internal::IsSwappable; - using absl::type_traits_internal::StdSwapIsUnconstrained; - - EXPECT_TRUE(IsSwappable<int>::value); - - struct S {}; - EXPECT_TRUE(IsSwappable<S>::value); - - struct NoConstruct { - NoConstruct(NoConstruct&&) = delete; - NoConstruct& operator=(NoConstruct&&) { return *this; } - ~NoConstruct() = default; - }; - - EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value); - struct NoAssign { - NoAssign(NoAssign&&) {} - NoAssign& operator=(NoAssign&&) = delete; - ~NoAssign() = default; - }; - - EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value); - - EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value); - - EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value); -} - -TEST(TypeTraitsTest, IsNothrowSwappable) { - using absl::type_traits_internal::IsNothrowSwappable; - using absl::type_traits_internal::StdSwapIsUnconstrained; - - EXPECT_TRUE(IsNothrowSwappable<int>::value); - - struct NonNoexceptMoves { - NonNoexceptMoves(NonNoexceptMoves&&) {} - NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; } - ~NonNoexceptMoves() = default; - }; - - EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value); - - struct NoConstruct { - NoConstruct(NoConstruct&&) = delete; - NoConstruct& operator=(NoConstruct&&) { return *this; } - ~NoConstruct() = default; - }; - - EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value); - - struct NoAssign { - NoAssign(NoAssign&&) {} - NoAssign& operator=(NoAssign&&) = delete; - ~NoAssign() = default; - }; - - EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value); - - EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value); - - EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/numeric/BUILD.bazel b/third_party/abseil_cpp/absl/numeric/BUILD.bazel deleted file mode 100644 index f808f5dab06e..000000000000 --- a/third_party/abseil_cpp/absl/numeric/BUILD.bazel +++ /dev/null @@ -1,74 +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. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "int128", - srcs = [ - "int128.cc", - "int128_have_intrinsic.inc", - "int128_no_intrinsic.inc", - ], - hdrs = ["int128.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:bits", - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -cc_test( - name = "int128_test", - size = "small", - srcs = [ - "int128_stream_test.cc", - "int128_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":int128", - "//absl/base", - "//absl/base:core_headers", - "//absl/hash:hash_testing", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "int128_benchmark", - srcs = ["int128_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":int128", - "//absl/base:config", - "@com_github_google_benchmark//:benchmark_main", - ], -) diff --git a/third_party/abseil_cpp/absl/numeric/CMakeLists.txt b/third_party/abseil_cpp/absl/numeric/CMakeLists.txt deleted file mode 100644 index 1e12d80f7ce9..000000000000 --- a/third_party/abseil_cpp/absl/numeric/CMakeLists.txt +++ /dev/null @@ -1,61 +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. -# - -absl_cc_library( - NAME - int128 - HDRS - "int128.h" - SRCS - "int128.cc" - "int128_have_intrinsic.inc" - "int128_no_intrinsic.inc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bits - absl::config - absl::core_headers - PUBLIC -) - -absl_cc_test( - NAME - int128_test - SRCS - "int128_stream_test.cc" - "int128_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::int128 - absl::base - absl::core_headers - absl::hash_testing - absl::type_traits - gmock_main -) - -# component target -absl_cc_library( - NAME - numeric - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::int128 - PUBLIC -) diff --git a/third_party/abseil_cpp/absl/numeric/int128.cc b/third_party/abseil_cpp/absl/numeric/int128.cc deleted file mode 100644 index e21e5e9a4ad4..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128.cc +++ /dev/null @@ -1,390 +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/numeric/int128.h" - -#include <stddef.h> - -#include <cassert> -#include <iomanip> -#include <ostream> // NOLINT(readability/streams) -#include <sstream> -#include <string> -#include <type_traits> - -#include "absl/base/internal/bits.h" -#include "absl/base/optimization.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -ABSL_DLL const uint128 kuint128max = MakeUint128( - std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max()); - -namespace { - -// Returns the 0-based position of the last set bit (i.e., most significant bit) -// in the given uint128. The argument is not 0. -// -// For example: -// Given: 5 (decimal) == 101 (binary) -// Returns: 2 -inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) { - if (uint64_t hi = Uint128High64(n)) { - ABSL_INTERNAL_ASSUME(hi != 0); - return 127 - base_internal::CountLeadingZeros64(hi); - } - const uint64_t low = Uint128Low64(n); - ABSL_INTERNAL_ASSUME(low != 0); - return 63 - base_internal::CountLeadingZeros64(low); -} - -// 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) { - assert(divisor != 0); - - if (divisor > dividend) { - *quotient_ret = 0; - *remainder_ret = dividend; - return; - } - - if (divisor == dividend) { - *quotient_ret = 1; - *remainder_ret = 0; - return; - } - - uint128 denominator = divisor; - uint128 quotient = 0; - - // Left aligns the MSB of the denominator and the dividend. - const int shift = Fls128(dividend) - Fls128(denominator); - denominator <<= shift; - - // Uses shift-subtract algorithm to divide dividend by denominator. The - // remainder will be left in dividend. - for (int i = 0; i <= shift; ++i) { - quotient <<= 1; - if (dividend >= denominator) { - dividend -= denominator; - quotient |= 1; - } - denominator >>= 1; - } - - *quotient_ret = quotient; - *remainder_ret = dividend; -} - -template <typename T> -uint128 MakeUint128FromFloat(T v) { - static_assert(std::is_floating_point<T>::value, ""); - - // Rounding behavior is towards zero, same as for built-in types. - - // Undefined behavior if v is NaN or cannot fit into uint128. - assert(std::isfinite(v) && v > -1 && - (std::numeric_limits<T>::max_exponent <= 128 || - v < std::ldexp(static_cast<T>(1), 128))); - - if (v >= std::ldexp(static_cast<T>(1), 64)) { - uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64)); - uint64_t lo = static_cast<uint64_t>(v - std::ldexp(static_cast<T>(hi), 64)); - return MakeUint128(hi, lo); - } - - return MakeUint128(0, static_cast<uint64_t>(v)); -} - -#if defined(__clang__) && !defined(__SSE3__) -// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 -// Casting from long double to uint64_t is miscompiled and drops bits. -// It is more work, so only use when we need the workaround. -uint128 MakeUint128FromFloat(long double v) { - // Go 50 bits at a time, that fits in a double - static_assert(std::numeric_limits<double>::digits >= 50, ""); - static_assert(std::numeric_limits<long double>::digits <= 150, ""); - // Undefined behavior if v is not finite or cannot fit into uint128. - assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128)); - - v = std::ldexp(v, -100); - uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v))); - v = std::ldexp(v - static_cast<double>(w0), 50); - uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v))); - v = std::ldexp(v - static_cast<double>(w1), 50); - uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v))); - return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) | - static_cast<uint128>(w2); -} -#endif // __clang__ && !__SSE3__ -} // namespace - -uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} -uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {} -uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {} - -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, "ient, &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, "ient, &remainder); - return remainder; -#endif // ABSL_HAVE_INTRINSIC_INT128 -} - -namespace { - -std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { - // Select a divisor which is the largest power of the base < 2^64. - uint128 div; - int div_base_log; - switch (flags & std::ios::basefield) { - case std::ios::hex: - div = 0x1000000000000000; // 16^15 - div_base_log = 15; - break; - case std::ios::oct: - div = 01000000000000000000000; // 8^21 - div_base_log = 21; - break; - default: // std::ios::dec - div = 10000000000000000000u; // 10^19 - div_base_log = 19; - break; - } - - // Now piece together the uint128 representation from three chunks of the - // original value, each less than "div" and therefore representable as a - // uint64_t. - std::ostringstream os; - std::ios_base::fmtflags copy_mask = - std::ios::basefield | std::ios::showbase | std::ios::uppercase; - os.setf(flags & copy_mask, copy_mask); - uint128 high = v; - uint128 low; - DivModImpl(high, div, &high, &low); - uint128 mid; - DivModImpl(high, div, &high, &mid); - if (Uint128Low64(high) != 0) { - os << Uint128Low64(high); - os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); - os << Uint128Low64(mid); - os << std::setw(div_base_log); - } else if (Uint128Low64(mid) != 0) { - os << Uint128Low64(mid); - os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); - } - os << Uint128Low64(low); - return os.str(); -} - -} // namespace - -std::ostream& operator<<(std::ostream& os, uint128 v) { - std::ios_base::fmtflags flags = os.flags(); - std::string rep = Uint128ToFormattedString(v, flags); - - // Add the requisite padding. - std::streamsize width = os.width(0); - if (static_cast<size_t>(width) > rep.size()) { - std::ios::fmtflags adjustfield = flags & std::ios::adjustfield; - if (adjustfield == std::ios::left) { - rep.append(width - rep.size(), os.fill()); - } else if (adjustfield == std::ios::internal && - (flags & std::ios::showbase) && - (flags & std::ios::basefield) == std::ios::hex && v != 0) { - rep.insert(2, width - rep.size(), os.fill()); - } else { - rep.insert(0, width - rep.size(), os.fill()); - } - } - - return os << rep; -} - -namespace { - -uint128 UnsignedAbsoluteValue(int128 v) { - // Cast to uint128 before possibly negating because -Int128Min() is undefined. - return Int128High64(v) < 0 ? -uint128(v) : uint128(v); -} - -} // namespace - -#if !defined(ABSL_HAVE_INTRINSIC_INT128) -namespace { - -template <typename T> -int128 MakeInt128FromFloat(T v) { - // Conversion when v is NaN or cannot fit into int128 would be undefined - // behavior if using an intrinsic 128-bit integer. - assert(std::isfinite(v) && (std::numeric_limits<T>::max_exponent <= 127 || - (v >= -std::ldexp(static_cast<T>(1), 127) && - v < std::ldexp(static_cast<T>(1), 127)))); - - // We must convert the absolute value and then negate as needed, because - // floating point types are typically sign-magnitude. Otherwise, the - // difference between the high and low 64 bits when interpreted as two's - // complement overwhelms the precision of the mantissa. - uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v); - return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), - Uint128Low64(result)); -} - -} // namespace - -int128::int128(float v) : int128(MakeInt128FromFloat(v)) {} -int128::int128(double v) : int128(MakeInt128FromFloat(v)) {} -int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {} - -int128 operator/(int128 lhs, int128 rhs) { - assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. - - uint128 quotient = 0; - uint128 remainder = 0; - DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), - "ient, &remainder); - if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient; - return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)), - Uint128Low64(quotient)); -} - -int128 operator%(int128 lhs, int128 rhs) { - assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. - - uint128 quotient = 0; - uint128 remainder = 0; - DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), - "ient, &remainder); - if (Int128High64(lhs) < 0) remainder = -remainder; - return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)), - Uint128Low64(remainder)); -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -std::ostream& operator<<(std::ostream& os, int128 v) { - std::ios_base::fmtflags flags = os.flags(); - std::string rep; - - // Add the sign if needed. - bool print_as_decimal = - (flags & std::ios::basefield) == std::ios::dec || - (flags & std::ios::basefield) == std::ios_base::fmtflags(); - if (print_as_decimal) { - if (Int128High64(v) < 0) { - rep = "-"; - } else if (flags & std::ios::showpos) { - rep = "+"; - } - } - - rep.append(Uint128ToFormattedString( - print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags())); - - // Add the requisite padding. - std::streamsize width = os.width(0); - if (static_cast<size_t>(width) > rep.size()) { - switch (flags & std::ios::adjustfield) { - case std::ios::left: - rep.append(width - rep.size(), os.fill()); - break; - case std::ios::internal: - if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) { - rep.insert(1, width - rep.size(), os.fill()); - } else if ((flags & std::ios::basefield) == std::ios::hex && - (flags & std::ios::showbase) && v != 0) { - rep.insert(2, width - rep.size(), os.fill()); - } else { - rep.insert(0, width - rep.size(), os.fill()); - } - break; - default: // std::ios::right - rep.insert(0, width - rep.size(), os.fill()); - break; - } - } - - return os << rep; -} - -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { -constexpr bool numeric_limits<absl::uint128>::is_specialized; -constexpr bool numeric_limits<absl::uint128>::is_signed; -constexpr bool numeric_limits<absl::uint128>::is_integer; -constexpr bool numeric_limits<absl::uint128>::is_exact; -constexpr bool numeric_limits<absl::uint128>::has_infinity; -constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN; -constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN; -constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm; -constexpr bool numeric_limits<absl::uint128>::has_denorm_loss; -constexpr float_round_style numeric_limits<absl::uint128>::round_style; -constexpr bool numeric_limits<absl::uint128>::is_iec559; -constexpr bool numeric_limits<absl::uint128>::is_bounded; -constexpr bool numeric_limits<absl::uint128>::is_modulo; -constexpr int numeric_limits<absl::uint128>::digits; -constexpr int numeric_limits<absl::uint128>::digits10; -constexpr int numeric_limits<absl::uint128>::max_digits10; -constexpr int numeric_limits<absl::uint128>::radix; -constexpr int numeric_limits<absl::uint128>::min_exponent; -constexpr int numeric_limits<absl::uint128>::min_exponent10; -constexpr int numeric_limits<absl::uint128>::max_exponent; -constexpr int numeric_limits<absl::uint128>::max_exponent10; -constexpr bool numeric_limits<absl::uint128>::traps; -constexpr bool numeric_limits<absl::uint128>::tinyness_before; - -constexpr bool numeric_limits<absl::int128>::is_specialized; -constexpr bool numeric_limits<absl::int128>::is_signed; -constexpr bool numeric_limits<absl::int128>::is_integer; -constexpr bool numeric_limits<absl::int128>::is_exact; -constexpr bool numeric_limits<absl::int128>::has_infinity; -constexpr bool numeric_limits<absl::int128>::has_quiet_NaN; -constexpr bool numeric_limits<absl::int128>::has_signaling_NaN; -constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm; -constexpr bool numeric_limits<absl::int128>::has_denorm_loss; -constexpr float_round_style numeric_limits<absl::int128>::round_style; -constexpr bool numeric_limits<absl::int128>::is_iec559; -constexpr bool numeric_limits<absl::int128>::is_bounded; -constexpr bool numeric_limits<absl::int128>::is_modulo; -constexpr int numeric_limits<absl::int128>::digits; -constexpr int numeric_limits<absl::int128>::digits10; -constexpr int numeric_limits<absl::int128>::max_digits10; -constexpr int numeric_limits<absl::int128>::radix; -constexpr int numeric_limits<absl::int128>::min_exponent; -constexpr int numeric_limits<absl::int128>::min_exponent10; -constexpr int numeric_limits<absl::int128>::max_exponent; -constexpr int numeric_limits<absl::int128>::max_exponent10; -constexpr bool numeric_limits<absl::int128>::traps; -constexpr bool numeric_limits<absl::int128>::tinyness_before; -} // namespace std diff --git a/third_party/abseil_cpp/absl/numeric/int128.h b/third_party/abseil_cpp/absl/numeric/int128.h deleted file mode 100644 index 0dd814a890e7..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128.h +++ /dev/null @@ -1,1092 +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. -// -// ----------------------------------------------------------------------------- -// File: int128.h -// ----------------------------------------------------------------------------- -// -// This header file defines 128-bit integer types, `uint128` and `int128`. - -#ifndef ABSL_NUMERIC_INT128_H_ -#define ABSL_NUMERIC_INT128_H_ - -#include <cassert> -#include <cmath> -#include <cstdint> -#include <cstring> -#include <iosfwd> -#include <limits> -#include <utility> - -#include "absl/base/config.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" - -#if defined(_MSC_VER) -// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is -// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t -// builtin type. We need to make sure not to define operator wchar_t() -// alongside operator unsigned short() in these instances. -#define ABSL_INTERNAL_WCHAR_T __wchar_t -#if defined(_M_X64) -#include <intrin.h> -#pragma intrinsic(_umul128) -#endif // defined(_M_X64) -#else // defined(_MSC_VER) -#define ABSL_INTERNAL_WCHAR_T wchar_t -#endif // defined(_MSC_VER) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class int128; - -// uint128 -// -// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type -// as closely as is practical, including exhibiting undefined behavior in -// analogous cases (e.g. division by zero). This type is intended to be a -// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when -// that occurs, existing well-behaved uses of `uint128` will continue to work -// using that new type. -// -// Note: code written with this type will continue to compile once `uint128_t` -// is introduced, provided the replacement helper functions -// `Uint128(Low|High)64()` and `MakeUint128()` are made. -// -// A `uint128` supports the following: -// -// * Implicit construction from integral types -// * Explicit conversion to integral types -// -// Additionally, if your compiler supports `__int128`, `uint128` is -// interoperable with that type. (Abseil checks for this compatibility through -// the `ABSL_HAVE_INTRINSIC_INT128` macro.) -// -// However, a `uint128` differs from intrinsic integral types in the following -// ways: -// -// * Errors on implicit conversions that do not preserve value (such as -// loss of precision when converting to float values). -// * Requires explicit construction from and conversion to floating point -// types. -// * Conversion to integral types requires an explicit static_cast() to -// mimic use of the `-Wnarrowing` compiler flag. -// * The alignment requirement of `uint128` may differ from that of an -// intrinsic 128-bit integer type depending on platform and build -// configuration. -// -// Example: -// -// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly -// // converted to float. -// -// absl::uint128 v; -// uint64_t i = v; // Error -// uint64_t i = static_cast<uint64_t>(v); // OK -// -class -#if defined(ABSL_HAVE_INTRINSIC_INT128) - alignas(unsigned __int128) -#endif // ABSL_HAVE_INTRINSIC_INT128 - uint128 { - public: - uint128() = default; - - // Constructors from arithmetic types - constexpr uint128(int v); // NOLINT(runtime/explicit) - constexpr uint128(unsigned int v); // NOLINT(runtime/explicit) - constexpr uint128(long v); // NOLINT(runtime/int) - constexpr uint128(unsigned long v); // NOLINT(runtime/int) - constexpr uint128(long long v); // NOLINT(runtime/int) - constexpr uint128(unsigned long long v); // NOLINT(runtime/int) -#ifdef ABSL_HAVE_INTRINSIC_INT128 - constexpr uint128(__int128 v); // NOLINT(runtime/explicit) - constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) -#endif // ABSL_HAVE_INTRINSIC_INT128 - constexpr uint128(int128 v); // NOLINT(runtime/explicit) - explicit uint128(float v); - explicit uint128(double v); - explicit uint128(long double v); - - // Assignment operators from arithmetic types - uint128& operator=(int v); - uint128& operator=(unsigned int v); - uint128& operator=(long v); // NOLINT(runtime/int) - uint128& operator=(unsigned long v); // NOLINT(runtime/int) - uint128& operator=(long long v); // NOLINT(runtime/int) - uint128& operator=(unsigned long long v); // NOLINT(runtime/int) -#ifdef ABSL_HAVE_INTRINSIC_INT128 - uint128& operator=(__int128 v); - uint128& operator=(unsigned __int128 v); -#endif // ABSL_HAVE_INTRINSIC_INT128 - uint128& operator=(int128 v); - - // Conversion operators to other arithmetic types - constexpr explicit operator bool() const; - constexpr explicit operator char() const; - constexpr explicit operator signed char() const; - constexpr explicit operator unsigned char() const; - constexpr explicit operator char16_t() const; - constexpr explicit operator char32_t() const; - constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; - constexpr explicit operator short() const; // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned short() const; - constexpr explicit operator int() const; - constexpr explicit operator unsigned int() const; - constexpr explicit operator long() const; // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned long() const; - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator long long() const; - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned long long() const; -#ifdef ABSL_HAVE_INTRINSIC_INT128 - constexpr explicit operator __int128() const; - constexpr explicit operator unsigned __int128() const; -#endif // ABSL_HAVE_INTRINSIC_INT128 - explicit operator float() const; - explicit operator double() const; - explicit operator long double() const; - - // Trivial copy constructor, assignment operator and destructor. - - // Arithmetic operators. - uint128& operator+=(uint128 other); - uint128& operator-=(uint128 other); - uint128& operator*=(uint128 other); - // Long division/modulo for uint128. - uint128& operator/=(uint128 other); - uint128& operator%=(uint128 other); - uint128 operator++(int); - uint128 operator--(int); - uint128& operator<<=(int); - uint128& operator>>=(int); - uint128& operator&=(uint128 other); - uint128& operator|=(uint128 other); - uint128& operator^=(uint128 other); - uint128& operator++(); - uint128& operator--(); - - // Uint128Low64() - // - // Returns the lower 64-bit value of a `uint128` value. - friend constexpr uint64_t Uint128Low64(uint128 v); - - // Uint128High64() - // - // Returns the higher 64-bit value of a `uint128` value. - friend constexpr uint64_t Uint128High64(uint128 v); - - // MakeUInt128() - // - // Constructs a `uint128` numeric value from two 64-bit unsigned integers. - // Note that this factory function is the only way to construct a `uint128` - // from integer values greater than 2^64. - // - // Example: - // - // absl::uint128 big = absl::MakeUint128(1, 0); - friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low); - - // Uint128Max() - // - // Returns the highest value for a 128-bit unsigned integer. - friend constexpr uint128 Uint128Max(); - - // Support for absl::Hash. - template <typename H> - friend H AbslHashValue(H h, uint128 v) { - return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); - } - - private: - constexpr uint128(uint64_t high, uint64_t low); - - // TODO(strel) Update implementation to use __int128 once all users of - // uint128 are fixed to not depend on alignof(uint128) == 8. Also add - // alignas(16) to class definition to keep alignment consistent across - // platforms. -#if defined(ABSL_IS_LITTLE_ENDIAN) - uint64_t lo_; - uint64_t hi_; -#elif defined(ABSL_IS_BIG_ENDIAN) - uint64_t hi_; - uint64_t lo_; -#else // byte order -#error "Unsupported byte order: must be little-endian or big-endian." -#endif // byte order -}; - -// Prefer to use the constexpr `Uint128Max()`. -// -// TODO(absl-team) deprecate kuint128max once migration tool is released. -ABSL_DLL extern const uint128 kuint128max; - -// allow uint128 to be logged -std::ostream& operator<<(std::ostream& os, uint128 v); - -// TODO(strel) add operator>>(std::istream&, uint128) - -constexpr uint128 Uint128Max() { - return uint128((std::numeric_limits<uint64_t>::max)(), - (std::numeric_limits<uint64_t>::max)()); -} - -ABSL_NAMESPACE_END -} // namespace absl - -// Specialized numeric_limits for uint128. -namespace std { -template <> -class numeric_limits<absl::uint128> { - public: - static constexpr bool is_specialized = true; - static constexpr bool is_signed = false; - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; - static constexpr float_round_style round_style = round_toward_zero; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = true; - static constexpr int digits = 128; - static constexpr int digits10 = 38; - static constexpr int max_digits10 = 0; - static constexpr int radix = 2; - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; -#ifdef ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool traps = numeric_limits<unsigned __int128>::traps; -#else // ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool traps = numeric_limits<uint64_t>::traps; -#endif // ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool tinyness_before = false; - - static constexpr absl::uint128 (min)() { return 0; } - static constexpr absl::uint128 lowest() { return 0; } - static constexpr absl::uint128 (max)() { return absl::Uint128Max(); } - static constexpr absl::uint128 epsilon() { return 0; } - static constexpr absl::uint128 round_error() { return 0; } - static constexpr absl::uint128 infinity() { return 0; } - static constexpr absl::uint128 quiet_NaN() { return 0; } - static constexpr absl::uint128 signaling_NaN() { return 0; } - static constexpr absl::uint128 denorm_min() { return 0; } -}; -} // namespace std - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// int128 -// -// A signed 128-bit integer type. The API is meant to mimic an intrinsic -// integral type as closely as is practical, including exhibiting undefined -// behavior in analogous cases (e.g. division by zero). -// -// An `int128` supports the following: -// -// * Implicit construction from integral types -// * Explicit conversion to integral types -// -// However, an `int128` differs from intrinsic integral types in the following -// ways: -// -// * It is not implicitly convertible to other integral types. -// * Requires explicit construction from and conversion to floating point -// types. - -// Additionally, if your compiler supports `__int128`, `int128` is -// interoperable with that type. (Abseil checks for this compatibility through -// the `ABSL_HAVE_INTRINSIC_INT128` macro.) -// -// The design goal for `int128` is that it will be compatible with a future -// `int128_t`, if that type becomes a part of the standard. -// -// Example: -// -// float y = absl::int128(17); // Error. int128 cannot be implicitly -// // converted to float. -// -// absl::int128 v; -// int64_t i = v; // Error -// int64_t i = static_cast<int64_t>(v); // OK -// -class int128 { - public: - int128() = default; - - // Constructors from arithmetic types - constexpr int128(int v); // NOLINT(runtime/explicit) - constexpr int128(unsigned int v); // NOLINT(runtime/explicit) - constexpr int128(long v); // NOLINT(runtime/int) - constexpr int128(unsigned long v); // NOLINT(runtime/int) - constexpr int128(long long v); // NOLINT(runtime/int) - constexpr int128(unsigned long long v); // NOLINT(runtime/int) -#ifdef ABSL_HAVE_INTRINSIC_INT128 - constexpr int128(__int128 v); // NOLINT(runtime/explicit) - constexpr explicit int128(unsigned __int128 v); -#endif // ABSL_HAVE_INTRINSIC_INT128 - constexpr explicit int128(uint128 v); - explicit int128(float v); - explicit int128(double v); - explicit int128(long double v); - - // Assignment operators from arithmetic types - int128& operator=(int v); - int128& operator=(unsigned int v); - int128& operator=(long v); // NOLINT(runtime/int) - int128& operator=(unsigned long v); // NOLINT(runtime/int) - int128& operator=(long long v); // NOLINT(runtime/int) - int128& operator=(unsigned long long v); // NOLINT(runtime/int) -#ifdef ABSL_HAVE_INTRINSIC_INT128 - int128& operator=(__int128 v); -#endif // ABSL_HAVE_INTRINSIC_INT128 - - // Conversion operators to other arithmetic types - constexpr explicit operator bool() const; - constexpr explicit operator char() const; - constexpr explicit operator signed char() const; - constexpr explicit operator unsigned char() const; - constexpr explicit operator char16_t() const; - constexpr explicit operator char32_t() const; - constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; - constexpr explicit operator short() const; // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned short() const; - constexpr explicit operator int() const; - constexpr explicit operator unsigned int() const; - constexpr explicit operator long() const; // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned long() const; - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator long long() const; - // NOLINTNEXTLINE(runtime/int) - constexpr explicit operator unsigned long long() const; -#ifdef ABSL_HAVE_INTRINSIC_INT128 - constexpr explicit operator __int128() const; - constexpr explicit operator unsigned __int128() const; -#endif // ABSL_HAVE_INTRINSIC_INT128 - explicit operator float() const; - explicit operator double() const; - explicit operator long double() const; - - // Trivial copy constructor, assignment operator and destructor. - - // Arithmetic operators - int128& operator+=(int128 other); - int128& operator-=(int128 other); - int128& operator*=(int128 other); - int128& operator/=(int128 other); - int128& operator%=(int128 other); - int128 operator++(int); // postfix increment: i++ - int128 operator--(int); // postfix decrement: i-- - int128& operator++(); // prefix increment: ++i - int128& operator--(); // prefix decrement: --i - int128& operator&=(int128 other); - int128& operator|=(int128 other); - int128& operator^=(int128 other); - int128& operator<<=(int amount); - int128& operator>>=(int amount); - - // Int128Low64() - // - // Returns the lower 64-bit value of a `int128` value. - friend constexpr uint64_t Int128Low64(int128 v); - - // Int128High64() - // - // Returns the higher 64-bit value of a `int128` value. - friend constexpr int64_t Int128High64(int128 v); - - // MakeInt128() - // - // Constructs a `int128` numeric value from two 64-bit integers. Note that - // signedness is conveyed in the upper `high` value. - // - // (absl::int128(1) << 64) * high + low - // - // Note that this factory function is the only way to construct a `int128` - // from integer values greater than 2^64 or less than -2^64. - // - // Example: - // - // absl::int128 big = absl::MakeInt128(1, 0); - // absl::int128 big_n = absl::MakeInt128(-1, 0); - friend constexpr int128 MakeInt128(int64_t high, uint64_t low); - - // Int128Max() - // - // Returns the maximum value for a 128-bit signed integer. - friend constexpr int128 Int128Max(); - - // Int128Min() - // - // Returns the minimum value for a 128-bit signed integer. - friend constexpr int128 Int128Min(); - - // Support for absl::Hash. - template <typename H> - friend H AbslHashValue(H h, int128 v) { - return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); - } - - private: - constexpr int128(int64_t high, uint64_t low); - -#if defined(ABSL_HAVE_INTRINSIC_INT128) - __int128 v_; -#else // ABSL_HAVE_INTRINSIC_INT128 -#if defined(ABSL_IS_LITTLE_ENDIAN) - uint64_t lo_; - int64_t hi_; -#elif defined(ABSL_IS_BIG_ENDIAN) - int64_t hi_; - uint64_t lo_; -#else // byte order -#error "Unsupported byte order: must be little-endian or big-endian." -#endif // byte order -#endif // ABSL_HAVE_INTRINSIC_INT128 -}; - -std::ostream& operator<<(std::ostream& os, int128 v); - -// TODO(absl-team) add operator>>(std::istream&, int128) - -constexpr int128 Int128Max() { - return int128((std::numeric_limits<int64_t>::max)(), - (std::numeric_limits<uint64_t>::max)()); -} - -constexpr int128 Int128Min() { - return int128((std::numeric_limits<int64_t>::min)(), 0); -} - -ABSL_NAMESPACE_END -} // namespace absl - -// Specialized numeric_limits for int128. -namespace std { -template <> -class numeric_limits<absl::int128> { - public: - static constexpr bool is_specialized = true; - static constexpr bool is_signed = true; - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; - static constexpr float_round_style round_style = round_toward_zero; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - static constexpr int digits = 127; - static constexpr int digits10 = 38; - static constexpr int max_digits10 = 0; - static constexpr int radix = 2; - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; -#ifdef ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool traps = numeric_limits<__int128>::traps; -#else // ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool traps = numeric_limits<uint64_t>::traps; -#endif // ABSL_HAVE_INTRINSIC_INT128 - static constexpr bool tinyness_before = false; - - static constexpr absl::int128 (min)() { return absl::Int128Min(); } - static constexpr absl::int128 lowest() { return absl::Int128Min(); } - static constexpr absl::int128 (max)() { return absl::Int128Max(); } - static constexpr absl::int128 epsilon() { return 0; } - static constexpr absl::int128 round_error() { return 0; } - static constexpr absl::int128 infinity() { return 0; } - static constexpr absl::int128 quiet_NaN() { return 0; } - static constexpr absl::int128 signaling_NaN() { return 0; } - static constexpr absl::int128 denorm_min() { return 0; } -}; -} // namespace std - -// -------------------------------------------------------------------------- -// Implementation details follow -// -------------------------------------------------------------------------- -namespace absl { -ABSL_NAMESPACE_BEGIN - -constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { - return uint128(high, low); -} - -// Assignment from integer types. - -inline uint128& uint128::operator=(int v) { return *this = uint128(v); } - -inline uint128& uint128::operator=(unsigned int v) { - return *this = uint128(v); -} - -inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int) - return *this = uint128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline uint128& uint128::operator=(unsigned long v) { - return *this = uint128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline uint128& uint128::operator=(long long v) { - return *this = uint128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline uint128& uint128::operator=(unsigned long long v) { - return *this = uint128(v); -} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -inline uint128& uint128::operator=(__int128 v) { - return *this = uint128(v); -} - -inline uint128& uint128::operator=(unsigned __int128 v) { - return *this = uint128(v); -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -inline uint128& uint128::operator=(int128 v) { - return *this = uint128(v); -} - -// Arithmetic operators. - -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); - -inline uint128& uint128::operator<<=(int amount) { - *this = *this << amount; - return *this; -} - -inline uint128& uint128::operator>>=(int amount) { - *this = *this >> amount; - return *this; -} - -inline uint128& uint128::operator+=(uint128 other) { - *this = *this + other; - return *this; -} - -inline uint128& uint128::operator-=(uint128 other) { - *this = *this - other; - return *this; -} - -inline uint128& uint128::operator*=(uint128 other) { - *this = *this * other; - return *this; -} - -inline uint128& uint128::operator/=(uint128 other) { - *this = *this / other; - return *this; -} - -inline uint128& uint128::operator%=(uint128 other) { - *this = *this % other; - return *this; -} - -constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; } - -constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; } - -// Constructors from integer types. - -#if defined(ABSL_IS_LITTLE_ENDIAN) - -constexpr uint128::uint128(uint64_t high, uint64_t low) - : lo_{low}, hi_{high} {} - -constexpr uint128::uint128(int v) - : lo_{static_cast<uint64_t>(v)}, - hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} -constexpr uint128::uint128(long v) // NOLINT(runtime/int) - : lo_{static_cast<uint64_t>(v)}, - hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} -constexpr uint128::uint128(long long v) // NOLINT(runtime/int) - : lo_{static_cast<uint64_t>(v)}, - hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} - -constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {} -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {} -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -constexpr uint128::uint128(__int128 v) - : lo_{static_cast<uint64_t>(v & ~uint64_t{0})}, - hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {} -constexpr uint128::uint128(unsigned __int128 v) - : lo_{static_cast<uint64_t>(v & ~uint64_t{0})}, - hi_{static_cast<uint64_t>(v >> 64)} {} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -constexpr uint128::uint128(int128 v) - : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {} - -#elif defined(ABSL_IS_BIG_ENDIAN) - -constexpr uint128::uint128(uint64_t high, uint64_t low) - : hi_{high}, lo_{low} {} - -constexpr uint128::uint128(int v) - : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, - lo_{static_cast<uint64_t>(v)} {} -constexpr uint128::uint128(long v) // NOLINT(runtime/int) - : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, - lo_{static_cast<uint64_t>(v)} {} -constexpr uint128::uint128(long long v) // NOLINT(runtime/int) - : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, - lo_{static_cast<uint64_t>(v)} {} - -constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {} -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {} -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -constexpr uint128::uint128(__int128 v) - : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)}, - lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {} -constexpr uint128::uint128(unsigned __int128 v) - : hi_{static_cast<uint64_t>(v >> 64)}, - lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -constexpr uint128::uint128(int128 v) - : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {} - -#else // byte order -#error "Unsupported byte order: must be little-endian or big-endian." -#endif // byte order - -// Conversion operators to integer types. - -constexpr uint128::operator bool() const { return lo_ || hi_; } - -constexpr uint128::operator char() const { return static_cast<char>(lo_); } - -constexpr uint128::operator signed char() const { - return static_cast<signed char>(lo_); -} - -constexpr uint128::operator unsigned char() const { - return static_cast<unsigned char>(lo_); -} - -constexpr uint128::operator char16_t() const { - return static_cast<char16_t>(lo_); -} - -constexpr uint128::operator char32_t() const { - return static_cast<char32_t>(lo_); -} - -constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const { - return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_); -} - -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::operator short() const { return static_cast<short>(lo_); } - -constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int) - return static_cast<unsigned short>(lo_); // NOLINT(runtime/int) -} - -constexpr uint128::operator int() const { return static_cast<int>(lo_); } - -constexpr uint128::operator unsigned int() const { - return static_cast<unsigned int>(lo_); -} - -// NOLINTNEXTLINE(runtime/int) -constexpr uint128::operator long() const { return static_cast<long>(lo_); } - -constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int) - return static_cast<unsigned long>(lo_); // NOLINT(runtime/int) -} - -constexpr uint128::operator long long() const { // NOLINT(runtime/int) - return static_cast<long long>(lo_); // NOLINT(runtime/int) -} - -constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int) - return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int) -} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -constexpr uint128::operator __int128() const { - return (static_cast<__int128>(hi_) << 64) + lo_; -} - -constexpr uint128::operator unsigned __int128() const { - return (static_cast<unsigned __int128>(hi_) << 64) + lo_; -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -// Conversion operators to floating point types. - -inline uint128::operator float() const { - return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64); -} - -inline uint128::operator double() const { - return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64); -} - -inline uint128::operator long double() const { - return static_cast<long double>(lo_) + - std::ldexp(static_cast<long double>(hi_), 64); -} - -// Comparison operators. - -inline bool operator==(uint128 lhs, uint128 rhs) { - return (Uint128Low64(lhs) == Uint128Low64(rhs) && - Uint128High64(lhs) == Uint128High64(rhs)); -} - -inline bool operator!=(uint128 lhs, uint128 rhs) { - return !(lhs == rhs); -} - -inline bool operator<(uint128 lhs, uint128 rhs) { -#ifdef ABSL_HAVE_INTRINSIC_INT128 - return static_cast<unsigned __int128>(lhs) < - static_cast<unsigned __int128>(rhs); -#else - return (Uint128High64(lhs) == Uint128High64(rhs)) - ? (Uint128Low64(lhs) < Uint128Low64(rhs)) - : (Uint128High64(lhs) < Uint128High64(rhs)); -#endif -} - -inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; } - -inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); } - -inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); } - -// 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); -} - -inline bool operator!(uint128 val) { - return !Uint128High64(val) && !Uint128Low64(val); -} - -// Logical operators. - -inline uint128 operator~(uint128 val) { - return MakeUint128(~Uint128High64(val), ~Uint128Low64(val)); -} - -inline uint128 operator|(uint128 lhs, uint128 rhs) { - return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs), - Uint128Low64(lhs) | Uint128Low64(rhs)); -} - -inline uint128 operator&(uint128 lhs, uint128 rhs) { - return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs), - Uint128Low64(lhs) & Uint128Low64(rhs)); -} - -inline uint128 operator^(uint128 lhs, uint128 rhs) { - return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs), - Uint128Low64(lhs) ^ Uint128Low64(rhs)); -} - -inline uint128& uint128::operator|=(uint128 other) { - hi_ |= other.hi_; - lo_ |= other.lo_; - return *this; -} - -inline uint128& uint128::operator&=(uint128 other) { - hi_ &= other.hi_; - lo_ &= other.lo_; - return *this; -} - -inline uint128& uint128::operator^=(uint128 other) { - hi_ ^= other.hi_; - lo_ ^= other.lo_; - return *this; -} - -// Arithmetic operators. - -inline uint128 operator<<(uint128 lhs, int amount) { -#ifdef ABSL_HAVE_INTRINSIC_INT128 - return static_cast<unsigned __int128>(lhs) << amount; -#else - // uint64_t shifts of >= 64 are undefined, so we will need some - // special-casing. - if (amount < 64) { - if (amount != 0) { - return MakeUint128( - (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)), - Uint128Low64(lhs) << amount); - } - return lhs; - } - return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0); -#endif -} - -inline uint128 operator>>(uint128 lhs, int amount) { -#ifdef ABSL_HAVE_INTRINSIC_INT128 - return static_cast<unsigned __int128>(lhs) >> amount; -#else - // uint64_t shifts of >= 64 are undefined, so we will need some - // special-casing. - if (amount < 64) { - if (amount != 0) { - return MakeUint128(Uint128High64(lhs) >> amount, - (Uint128Low64(lhs) >> amount) | - (Uint128High64(lhs) << (64 - amount))); - } - return lhs; - } - return MakeUint128(0, Uint128High64(lhs) >> (amount - 64)); -#endif -} - -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; -} - -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) { -#if defined(ABSL_HAVE_INTRINSIC_INT128) - // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 - // can be used for uint128 storage. - return static_cast<unsigned __int128>(lhs) * - static_cast<unsigned __int128>(rhs); -#elif defined(_MSC_VER) && defined(_M_X64) - uint64_t carry; - uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); - return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + - Uint128High64(lhs) * Uint128Low64(rhs) + carry, - low); -#else // ABSL_HAVE_INTRINSIC128 - uint64_t a32 = Uint128Low64(lhs) >> 32; - uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; - uint64_t b32 = Uint128Low64(rhs) >> 32; - uint64_t b00 = Uint128Low64(rhs) & 0xffffffff; - uint128 result = - MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) + - Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32, - a00 * b00); - result += uint128(a32 * b00) << 32; - result += uint128(a00 * b32) << 32; - return result; -#endif // ABSL_HAVE_INTRINSIC128 -} - -// Increment/decrement operators. - -inline uint128 uint128::operator++(int) { - uint128 tmp(*this); - *this += 1; - return tmp; -} - -inline uint128 uint128::operator--(int) { - uint128 tmp(*this); - *this -= 1; - return tmp; -} - -inline uint128& uint128::operator++() { - *this += 1; - return *this; -} - -inline uint128& uint128::operator--() { - *this -= 1; - return *this; -} - -constexpr int128 MakeInt128(int64_t high, uint64_t low) { - return int128(high, low); -} - -// Assignment from integer types. -inline int128& int128::operator=(int v) { - return *this = int128(v); -} - -inline int128& int128::operator=(unsigned int v) { - return *this = int128(v); -} - -inline int128& int128::operator=(long v) { // NOLINT(runtime/int) - return *this = int128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline int128& int128::operator=(unsigned long v) { - return *this = int128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline int128& int128::operator=(long long v) { - return *this = int128(v); -} - -// NOLINTNEXTLINE(runtime/int) -inline int128& int128::operator=(unsigned long long v) { - return *this = int128(v); -} - -// Arithmetic operators. - -int128 operator+(int128 lhs, int128 rhs); -int128 operator-(int128 lhs, int128 rhs); -int128 operator*(int128 lhs, int128 rhs); -int128 operator/(int128 lhs, int128 rhs); -int128 operator%(int128 lhs, int128 rhs); -int128 operator|(int128 lhs, int128 rhs); -int128 operator&(int128 lhs, int128 rhs); -int128 operator^(int128 lhs, int128 rhs); -int128 operator<<(int128 lhs, int amount); -int128 operator>>(int128 lhs, int amount); - -inline int128& int128::operator+=(int128 other) { - *this = *this + other; - return *this; -} - -inline int128& int128::operator-=(int128 other) { - *this = *this - other; - return *this; -} - -inline int128& int128::operator*=(int128 other) { - *this = *this * other; - return *this; -} - -inline int128& int128::operator/=(int128 other) { - *this = *this / other; - return *this; -} - -inline int128& int128::operator%=(int128 other) { - *this = *this % other; - return *this; -} - -inline int128& int128::operator|=(int128 other) { - *this = *this | other; - return *this; -} - -inline int128& int128::operator&=(int128 other) { - *this = *this & other; - return *this; -} - -inline int128& int128::operator^=(int128 other) { - *this = *this ^ other; - return *this; -} - -inline int128& int128::operator<<=(int amount) { - *this = *this << amount; - return *this; -} - -inline int128& int128::operator>>=(int amount) { - *this = *this >> amount; - return *this; -} - -namespace int128_internal { - -// Casts from unsigned to signed while preserving the underlying binary -// representation. -constexpr int64_t BitCastToSigned(uint64_t v) { - // Casting an unsigned integer to a signed integer of the same - // width is implementation defined behavior if the source value would not fit - // in the destination type. We step around it with a roundtrip bitwise not - // operation to make sure this function remains constexpr. Clang, GCC, and - // MSVC optimize this to a no-op on x86-64. - return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v) - : static_cast<int64_t>(v); -} - -} // namespace int128_internal - -#if defined(ABSL_HAVE_INTRINSIC_INT128) -#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export -#else // ABSL_HAVE_INTRINSIC_INT128 -#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export -#endif // ABSL_HAVE_INTRINSIC_INT128 - -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_WCHAR_T - -#endif // ABSL_NUMERIC_INT128_H_ diff --git a/third_party/abseil_cpp/absl/numeric/int128_benchmark.cc b/third_party/abseil_cpp/absl/numeric/int128_benchmark.cc deleted file mode 100644 index eab1515c0ad8..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128_benchmark.cc +++ /dev/null @@ -1,282 +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 <algorithm> -#include <cstdint> -#include <limits> -#include <random> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/config.h" -#include "absl/numeric/int128.h" - -namespace { - -constexpr size_t kSampleSize = 1000000; - -std::mt19937 MakeRandomEngine() { - std::random_device r; - std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); - 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::mt19937 random = MakeRandomEngine(); - std::uniform_int_distribution<H> uniform_h; - 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))); - } - return values; -} - -template <typename T> -void BM_DivideClass128UniformDivisor(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_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); - -template <typename T, - typename H = typename std::conditional< - std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type> -std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() { - std::vector<std::pair<T, H>> values; - std::mt19937 random = MakeRandomEngine(); - std::uniform_int_distribution<H> uniform_h; - 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); - } - return values; -} - -template <typename T> -void BM_DivideClass128SmallDivisor(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_DivideClass128SmallDivisor, absl::uint128); -BENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::int128); - -template <typename T> -void BM_RemainderClass128SmallDivisor(benchmark::State& state) { - auto values = GetRandomClass128SampleSmallDivisor<T>(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first % pair.second); - } - } -} -BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::uint128); -BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::int128); - -std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() { - std::vector<std::pair<absl::uint128, absl::uint128>> values; - std::mt19937 random = MakeRandomEngine(); - std::uniform_int_distribution<uint64_t> uniform_uint64; - values.reserve(kSampleSize); - for (size_t i = 0; i < kSampleSize; ++i) { - values.emplace_back( - absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)), - absl::MakeUint128(uniform_uint64(random), uniform_uint64(random))); - } - return values; -} - -void BM_MultiplyClass128(benchmark::State& state) { - auto values = GetRandomClass128Sample(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first * pair.second); - } - } -} -BENCHMARK(BM_MultiplyClass128); - -void BM_AddClass128(benchmark::State& state) { - auto values = GetRandomClass128Sample(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first + pair.second); - } - } -} -BENCHMARK(BM_AddClass128); - -#ifdef ABSL_HAVE_INTRINSIC_INT128 - -// 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); - } - - private: - std::uniform_int_distribution<H> 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::mt19937 random = MakeRandomEngine(); - UniformIntDistribution128<T> uniform_128; - 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))); - } - return values; -} - -template <typename T> -void BM_DivideIntrinsic128UniformDivisor(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_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); - -template <typename T, - typename H = typename std::conditional< - std::is_same<T, __int128>::value, int64_t, uint64_t>::type> -std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() { - std::vector<std::pair<T, H>> values; - std::mt19937 random = MakeRandomEngine(); - UniformIntDistribution128<T> uniform_int128; - std::uniform_int_distribution<H> uniform_int64; - 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); - } - return values; -} - -template <typename T> -void BM_DivideIntrinsic128SmallDivisor(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_DivideIntrinsic128SmallDivisor, unsigned __int128); -BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128); - -template <typename T> -void BM_RemainderIntrinsic128SmallDivisor(benchmark::State& state) { - auto values = GetRandomIntrinsic128SampleSmallDivisor<T>(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first % pair.second); - } - } -} -BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, unsigned __int128); -BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128); - -std::vector<std::pair<unsigned __int128, unsigned __int128>> - GetRandomIntrinsic128Sample() { - std::vector<std::pair<unsigned __int128, unsigned __int128>> values; - std::mt19937 random = MakeRandomEngine(); - UniformIntDistribution128<unsigned __int128> uniform_uint128; - values.reserve(kSampleSize); - for (size_t i = 0; i < kSampleSize; ++i) { - values.emplace_back(uniform_uint128(random), uniform_uint128(random)); - } - return values; -} - -void BM_MultiplyIntrinsic128(benchmark::State& state) { - auto values = GetRandomIntrinsic128Sample(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first * pair.second); - } - } -} -BENCHMARK(BM_MultiplyIntrinsic128); - -void BM_AddIntrinsic128(benchmark::State& state) { - auto values = GetRandomIntrinsic128Sample(); - while (state.KeepRunningBatch(values.size())) { - for (const auto& pair : values) { - benchmark::DoNotOptimize(pair.first + pair.second); - } - } -} -BENCHMARK(BM_AddIntrinsic128); - -#endif // ABSL_HAVE_INTRINSIC_INT128 - -} // namespace diff --git a/third_party/abseil_cpp/absl/numeric/int128_have_intrinsic.inc b/third_party/abseil_cpp/absl/numeric/int128_have_intrinsic.inc deleted file mode 100644 index d6c76dd320ce..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128_have_intrinsic.inc +++ /dev/null @@ -1,302 +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 contains :int128 implementation details that depend on internal -// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is -// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. - -namespace int128_internal { - -// Casts from unsigned to signed while preserving the underlying binary -// representation. -constexpr __int128 BitCastToSigned(unsigned __int128 v) { - // Casting an unsigned integer to a signed integer of the same - // width is implementation defined behavior if the source value would not fit - // in the destination type. We step around it with a roundtrip bitwise not - // operation to make sure this function remains constexpr. Clang and GCC - // optimize this to a no-op on x86-64. - return v & (static_cast<unsigned __int128>(1) << 127) - ? ~static_cast<__int128>(~v) - : static_cast<__int128>(v); -} - -} // namespace int128_internal - -inline int128& int128::operator=(__int128 v) { - v_ = v; - return *this; -} - -constexpr uint64_t Int128Low64(int128 v) { - return static_cast<uint64_t>(v.v_ & ~uint64_t{0}); -} - -constexpr int64_t Int128High64(int128 v) { - // Initially cast to unsigned to prevent a right shift on a negative value. - return int128_internal::BitCastToSigned( - static_cast<uint64_t>(static_cast<unsigned __int128>(v.v_) >> 64)); -} - -constexpr int128::int128(int64_t high, uint64_t low) - // Initially cast to unsigned to prevent a left shift that overflows. - : v_(int128_internal::BitCastToSigned(static_cast<unsigned __int128>(high) - << 64) | - low) {} - - -constexpr int128::int128(int v) : v_{v} {} - -constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int) - -constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int) - -constexpr int128::int128(__int128 v) : v_{v} {} - -constexpr int128::int128(unsigned int v) : v_{v} {} - -constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int) - -// NOLINTNEXTLINE(runtime/int) -constexpr int128::int128(unsigned long long v) : v_{v} {} - -constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {} - -inline int128::int128(float v) { - v_ = static_cast<__int128>(v); -} - -inline int128::int128(double v) { - v_ = static_cast<__int128>(v); -} - -inline int128::int128(long double v) { - v_ = static_cast<__int128>(v); -} - -constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {} - -constexpr int128::operator bool() const { return static_cast<bool>(v_); } - -constexpr int128::operator char() const { return static_cast<char>(v_); } - -constexpr int128::operator signed char() const { - return static_cast<signed char>(v_); -} - -constexpr int128::operator unsigned char() const { - return static_cast<unsigned char>(v_); -} - -constexpr int128::operator char16_t() const { - return static_cast<char16_t>(v_); -} - -constexpr int128::operator char32_t() const { - return static_cast<char32_t>(v_); -} - -constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { - return static_cast<ABSL_INTERNAL_WCHAR_T>(v_); -} - -constexpr int128::operator short() const { // NOLINT(runtime/int) - return static_cast<short>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) - return static_cast<unsigned short>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator int() const { - return static_cast<int>(v_); -} - -constexpr int128::operator unsigned int() const { - return static_cast<unsigned int>(v_); -} - -constexpr int128::operator long() const { // NOLINT(runtime/int) - return static_cast<long>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) - return static_cast<unsigned long>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator long long() const { // NOLINT(runtime/int) - return static_cast<long long>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) - return static_cast<unsigned long long>(v_); // NOLINT(runtime/int) -} - -constexpr int128::operator __int128() const { return v_; } - -constexpr int128::operator unsigned __int128() const { - return static_cast<unsigned __int128>(v_); -} - -// Clang on PowerPC sometimes produces incorrect __int128 to floating point -// conversions. In that case, we do the conversion with a similar implementation -// to the conversion operators in int128_no_intrinsic.inc. -#if defined(__clang__) && !defined(__ppc64__) -inline int128::operator float() const { return static_cast<float>(v_); } - -inline int128::operator double () const { return static_cast<double>(v_); } - -inline int128::operator long double() const { - return static_cast<long double>(v_); -} - -#else // Clang on PowerPC -// Forward declaration for conversion operators to floating point types. -int128 operator-(int128 v); -bool operator!=(int128 lhs, int128 rhs); - -inline int128::operator float() const { - // We must convert the absolute value and then negate as needed, because - // floating point types are typically sign-magnitude. Otherwise, the - // difference between the high and low 64 bits when interpreted as two's - // complement overwhelms the precision of the mantissa. - // - // Also check to make sure we don't negate Int128Min() - return v_ < 0 && *this != Int128Min() - ? -static_cast<float>(-*this) - : static_cast<float>(Int128Low64(*this)) + - std::ldexp(static_cast<float>(Int128High64(*this)), 64); -} - -inline int128::operator double() const { - // See comment in int128::operator float() above. - return v_ < 0 && *this != Int128Min() - ? -static_cast<double>(-*this) - : static_cast<double>(Int128Low64(*this)) + - std::ldexp(static_cast<double>(Int128High64(*this)), 64); -} - -inline int128::operator long double() const { - // See comment in int128::operator float() above. - return v_ < 0 && *this != Int128Min() - ? -static_cast<long double>(-*this) - : static_cast<long double>(Int128Low64(*this)) + - std::ldexp(static_cast<long double>(Int128High64(*this)), - 64); -} -#endif // Clang on PowerPC - -// Comparison operators. - -inline bool operator==(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) == static_cast<__int128>(rhs); -} - -inline bool operator!=(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) != static_cast<__int128>(rhs); -} - -inline bool operator<(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) < static_cast<__int128>(rhs); -} - -inline bool operator>(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) > static_cast<__int128>(rhs); -} - -inline bool operator<=(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs); -} - -inline bool operator>=(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs); -} - -// Unary operators. - -inline int128 operator-(int128 v) { - return -static_cast<__int128>(v); -} - -inline bool operator!(int128 v) { - return !static_cast<__int128>(v); -} - -inline int128 operator~(int128 val) { - return ~static_cast<__int128>(val); -} - -// Arithmetic operators. - -inline int128 operator+(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) + static_cast<__int128>(rhs); -} - -inline int128 operator-(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); -} - -inline int128 operator*(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); -} - -inline int128 operator/(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); -} - -inline int128 operator%(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); -} - -inline int128 int128::operator++(int) { - int128 tmp(*this); - ++v_; - return tmp; -} - -inline int128 int128::operator--(int) { - int128 tmp(*this); - --v_; - return tmp; -} - -inline int128& int128::operator++() { - ++v_; - return *this; -} - -inline int128& int128::operator--() { - --v_; - return *this; -} - -inline int128 operator|(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) | static_cast<__int128>(rhs); -} - -inline int128 operator&(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) & static_cast<__int128>(rhs); -} - -inline int128 operator^(int128 lhs, int128 rhs) { - return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs); -} - -inline int128 operator<<(int128 lhs, int amount) { - return static_cast<__int128>(lhs) << amount; -} - -inline int128 operator>>(int128 lhs, int amount) { - return static_cast<__int128>(lhs) >> amount; -} diff --git a/third_party/abseil_cpp/absl/numeric/int128_no_intrinsic.inc b/third_party/abseil_cpp/absl/numeric/int128_no_intrinsic.inc deleted file mode 100644 index c753771ae73a..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128_no_intrinsic.inc +++ /dev/null @@ -1,308 +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 contains :int128 implementation details that depend on internal -// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file -// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. - -constexpr uint64_t Int128Low64(int128 v) { return v.lo_; } - -constexpr int64_t Int128High64(int128 v) { return v.hi_; } - -#if defined(ABSL_IS_LITTLE_ENDIAN) - -constexpr int128::int128(int64_t high, uint64_t low) : - lo_(low), hi_(high) {} - -constexpr int128::int128(int v) - : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} -constexpr int128::int128(long v) // NOLINT(runtime/int) - : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} -constexpr int128::int128(long long v) // NOLINT(runtime/int) - : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} - -constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {} -// NOLINTNEXTLINE(runtime/int) -constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {} -// NOLINTNEXTLINE(runtime/int) -constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {} - -constexpr int128::int128(uint128 v) - : lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {} - -#elif defined(ABSL_IS_BIG_ENDIAN) - -constexpr int128::int128(int64_t high, uint64_t low) : - hi_{high}, lo_{low} {} - -constexpr int128::int128(int v) - : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {} -constexpr int128::int128(long v) // NOLINT(runtime/int) - : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {} -constexpr int128::int128(long long v) // NOLINT(runtime/int) - : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {} - -constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {} -// NOLINTNEXTLINE(runtime/int) -constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {} -// NOLINTNEXTLINE(runtime/int) -constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {} - -constexpr int128::int128(uint128 v) - : hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {} - -#else // byte order -#error "Unsupported byte order: must be little-endian or big-endian." -#endif // byte order - -constexpr int128::operator bool() const { return lo_ || hi_; } - -constexpr int128::operator char() const { - // NOLINTNEXTLINE(runtime/int) - return static_cast<char>(static_cast<long long>(*this)); -} - -constexpr int128::operator signed char() const { - // NOLINTNEXTLINE(runtime/int) - return static_cast<signed char>(static_cast<long long>(*this)); -} - -constexpr int128::operator unsigned char() const { - return static_cast<unsigned char>(lo_); -} - -constexpr int128::operator char16_t() const { - return static_cast<char16_t>(lo_); -} - -constexpr int128::operator char32_t() const { - return static_cast<char32_t>(lo_); -} - -constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { - // NOLINTNEXTLINE(runtime/int) - return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this)); -} - -constexpr int128::operator short() const { // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - return static_cast<short>(static_cast<long long>(*this)); -} - -constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) - return static_cast<unsigned short>(lo_); // NOLINT(runtime/int) -} - -constexpr int128::operator int() const { - // NOLINTNEXTLINE(runtime/int) - return static_cast<int>(static_cast<long long>(*this)); -} - -constexpr int128::operator unsigned int() const { - return static_cast<unsigned int>(lo_); -} - -constexpr int128::operator long() const { // NOLINT(runtime/int) - // NOLINTNEXTLINE(runtime/int) - return static_cast<long>(static_cast<long long>(*this)); -} - -constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) - return static_cast<unsigned long>(lo_); // NOLINT(runtime/int) -} - -constexpr int128::operator long long() const { // NOLINT(runtime/int) - // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit - // must be set in order for the value to fit into a long long. Conversely, if - // lo_'s high bit is set, *this must be < 0 for the value to fit. - return int128_internal::BitCastToSigned(lo_); -} - -constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) - return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int) -} - -// Forward declaration for conversion operators to floating point types. -int128 operator-(int128 v); -bool operator!=(int128 lhs, int128 rhs); - -inline int128::operator float() const { - // We must convert the absolute value and then negate as needed, because - // floating point types are typically sign-magnitude. Otherwise, the - // difference between the high and low 64 bits when interpreted as two's - // complement overwhelms the precision of the mantissa. - // - // Also check to make sure we don't negate Int128Min() - return hi_ < 0 && *this != Int128Min() - ? -static_cast<float>(-*this) - : static_cast<float>(lo_) + - std::ldexp(static_cast<float>(hi_), 64); -} - -inline int128::operator double() const { - // See comment in int128::operator float() above. - return hi_ < 0 && *this != Int128Min() - ? -static_cast<double>(-*this) - : static_cast<double>(lo_) + - std::ldexp(static_cast<double>(hi_), 64); -} - -inline int128::operator long double() const { - // See comment in int128::operator float() above. - return hi_ < 0 && *this != Int128Min() - ? -static_cast<long double>(-*this) - : static_cast<long double>(lo_) + - std::ldexp(static_cast<long double>(hi_), 64); -} - -// Comparison operators. - -inline bool operator==(int128 lhs, int128 rhs) { - return (Int128Low64(lhs) == Int128Low64(rhs) && - Int128High64(lhs) == Int128High64(rhs)); -} - -inline bool operator!=(int128 lhs, int128 rhs) { - return !(lhs == rhs); -} - -inline bool operator<(int128 lhs, int128 rhs) { - return (Int128High64(lhs) == Int128High64(rhs)) - ? (Int128Low64(lhs) < Int128Low64(rhs)) - : (Int128High64(lhs) < Int128High64(rhs)); -} - -inline bool operator>(int128 lhs, int128 rhs) { - return (Int128High64(lhs) == Int128High64(rhs)) - ? (Int128Low64(lhs) > Int128Low64(rhs)) - : (Int128High64(lhs) > Int128High64(rhs)); -} - -inline bool operator<=(int128 lhs, int128 rhs) { - return !(lhs > rhs); -} - -inline bool operator>=(int128 lhs, int128 rhs) { - return !(lhs < rhs); -} - -// Unary operators. - -inline int128 operator-(int128 v) { - int64_t hi = ~Int128High64(v); - uint64_t lo = ~Int128Low64(v) + 1; - if (lo == 0) ++hi; // carry - return MakeInt128(hi, lo); -} - -inline bool operator!(int128 v) { - return !Int128Low64(v) && !Int128High64(v); -} - -inline int128 operator~(int128 val) { - return MakeInt128(~Int128High64(val), ~Int128Low64(val)); -} - -// Arithmetic operators. - -inline int128 operator+(int128 lhs, int128 rhs) { - int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs), - Int128Low64(lhs) + Int128Low64(rhs)); - if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry - return MakeInt128(Int128High64(result) + 1, Int128Low64(result)); - } - return result; -} - -inline int128 operator-(int128 lhs, int128 rhs) { - int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs), - Int128Low64(lhs) - Int128Low64(rhs)); - if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry - return MakeInt128(Int128High64(result) - 1, Int128Low64(result)); - } - return result; -} - -inline int128 operator*(int128 lhs, int128 rhs) { - uint128 result = uint128(lhs) * rhs; - return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), - Uint128Low64(result)); -} - -inline int128 int128::operator++(int) { - int128 tmp(*this); - *this += 1; - return tmp; -} - -inline int128 int128::operator--(int) { - int128 tmp(*this); - *this -= 1; - return tmp; -} - -inline int128& int128::operator++() { - *this += 1; - return *this; -} - -inline int128& int128::operator--() { - *this -= 1; - return *this; -} - -inline int128 operator|(int128 lhs, int128 rhs) { - return MakeInt128(Int128High64(lhs) | Int128High64(rhs), - Int128Low64(lhs) | Int128Low64(rhs)); -} - -inline int128 operator&(int128 lhs, int128 rhs) { - return MakeInt128(Int128High64(lhs) & Int128High64(rhs), - Int128Low64(lhs) & Int128Low64(rhs)); -} - -inline int128 operator^(int128 lhs, int128 rhs) { - return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs), - Int128Low64(lhs) ^ Int128Low64(rhs)); -} - -inline int128 operator<<(int128 lhs, int amount) { - // uint64_t shifts of >= 64 are undefined, so we need some special-casing. - if (amount < 64) { - if (amount != 0) { - return MakeInt128( - (Int128High64(lhs) << amount) | - static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)), - Int128Low64(lhs) << amount); - } - return lhs; - } - return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)), 0); -} - -inline int128 operator>>(int128 lhs, int amount) { - // uint64_t shifts of >= 64 are undefined, so we need some special-casing. - if (amount < 64) { - if (amount != 0) { - return MakeInt128( - Int128High64(lhs) >> amount, - (Int128Low64(lhs) >> amount) | - (static_cast<uint64_t>(Int128High64(lhs)) << (64 - amount))); - } - return lhs; - } - return MakeInt128(0, - static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64))); -} diff --git a/third_party/abseil_cpp/absl/numeric/int128_stream_test.cc b/third_party/abseil_cpp/absl/numeric/int128_stream_test.cc deleted file mode 100644 index 479ad66cf4d5..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128_stream_test.cc +++ /dev/null @@ -1,1395 +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/numeric/int128.h" - -#include <sstream> -#include <string> - -#include "gtest/gtest.h" - -namespace { - -struct Uint128TestCase { - absl::uint128 value; - std::ios_base::fmtflags flags; - std::streamsize width; - const char* expected; -}; - -constexpr char kFill = '_'; - -std::string StreamFormatToString(std::ios_base::fmtflags flags, - std::streamsize width) { - std::vector<const char*> flagstr; - switch (flags & std::ios::basefield) { - case std::ios::dec: - flagstr.push_back("std::ios::dec"); - break; - case std::ios::oct: - flagstr.push_back("std::ios::oct"); - break; - case std::ios::hex: - flagstr.push_back("std::ios::hex"); - break; - default: // basefield not specified - break; - } - switch (flags & std::ios::adjustfield) { - case std::ios::left: - flagstr.push_back("std::ios::left"); - break; - case std::ios::internal: - flagstr.push_back("std::ios::internal"); - break; - case std::ios::right: - flagstr.push_back("std::ios::right"); - break; - default: // adjustfield not specified - break; - } - if (flags & std::ios::uppercase) flagstr.push_back("std::ios::uppercase"); - if (flags & std::ios::showbase) flagstr.push_back("std::ios::showbase"); - if (flags & std::ios::showpos) flagstr.push_back("std::ios::showpos"); - - std::ostringstream msg; - msg << "\n StreamFormatToString(test_case.flags, test_case.width)\n " - "flags: "; - if (!flagstr.empty()) { - for (size_t i = 0; i < flagstr.size() - 1; ++i) msg << flagstr[i] << " | "; - msg << flagstr.back(); - } else { - msg << "(default)"; - } - msg << "\n width: " << width << "\n fill: '" << kFill << "'"; - return msg.str(); -} - -void CheckUint128Case(const Uint128TestCase& test_case) { - std::ostringstream os; - os.flags(test_case.flags); - os.width(test_case.width); - os.fill(kFill); - os << test_case.value; - SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width)); - EXPECT_EQ(test_case.expected, os.str()); -} - -constexpr std::ios::fmtflags kDec = std::ios::dec; -constexpr std::ios::fmtflags kOct = std::ios::oct; -constexpr std::ios::fmtflags kHex = std::ios::hex; -constexpr std::ios::fmtflags kLeft = std::ios::left; -constexpr std::ios::fmtflags kInt = std::ios::internal; -constexpr std::ios::fmtflags kRight = std::ios::right; -constexpr std::ios::fmtflags kUpper = std::ios::uppercase; -constexpr std::ios::fmtflags kBase = std::ios::showbase; -constexpr std::ios::fmtflags kPos = std::ios::showpos; - -TEST(Uint128, OStreamValueTest) { - CheckUint128Case({1, kDec, /*width = */ 0, "1"}); - CheckUint128Case({1, kOct, /*width = */ 0, "1"}); - CheckUint128Case({1, kHex, /*width = */ 0, "1"}); - CheckUint128Case({9, kDec, /*width = */ 0, "9"}); - CheckUint128Case({9, kOct, /*width = */ 0, "11"}); - CheckUint128Case({9, kHex, /*width = */ 0, "9"}); - CheckUint128Case({12345, kDec, /*width = */ 0, "12345"}); - CheckUint128Case({12345, kOct, /*width = */ 0, "30071"}); - CheckUint128Case({12345, kHex, /*width = */ 0, "3039"}); - CheckUint128Case( - {0x8000000000000000, kDec, /*width = */ 0, "9223372036854775808"}); - CheckUint128Case( - {0x8000000000000000, kOct, /*width = */ 0, "1000000000000000000000"}); - CheckUint128Case( - {0x8000000000000000, kHex, /*width = */ 0, "8000000000000000"}); - CheckUint128Case({std::numeric_limits<uint64_t>::max(), kDec, - /*width = */ 0, "18446744073709551615"}); - CheckUint128Case({std::numeric_limits<uint64_t>::max(), kOct, - /*width = */ 0, "1777777777777777777777"}); - CheckUint128Case({std::numeric_limits<uint64_t>::max(), kHex, - /*width = */ 0, "ffffffffffffffff"}); - CheckUint128Case( - {absl::MakeUint128(1, 0), kDec, /*width = */ 0, "18446744073709551616"}); - CheckUint128Case({absl::MakeUint128(1, 0), kOct, /*width = */ 0, - "2000000000000000000000"}); - CheckUint128Case( - {absl::MakeUint128(1, 0), kHex, /*width = */ 0, "10000000000000000"}); - CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kDec, - /*width = */ 0, "170141183460469231731687303715884105728"}); - CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kOct, - /*width = */ 0, - "2000000000000000000000000000000000000000000"}); - CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kHex, - /*width = */ 0, "80000000000000000000000000000000"}); - CheckUint128Case({absl::kuint128max, kDec, /*width = */ 0, - "340282366920938463463374607431768211455"}); - CheckUint128Case({absl::kuint128max, kOct, /*width = */ 0, - "3777777777777777777777777777777777777777777"}); - CheckUint128Case({absl::kuint128max, kHex, /*width = */ 0, - "ffffffffffffffffffffffffffffffff"}); -} - -std::vector<Uint128TestCase> GetUint128FormatCases(); - -TEST(Uint128, OStreamFormatTest) { - for (const Uint128TestCase& test_case : GetUint128FormatCases()) { - CheckUint128Case(test_case); - } -} - -struct Int128TestCase { - absl::int128 value; - std::ios_base::fmtflags flags; - std::streamsize width; - const char* expected; -}; - -void CheckInt128Case(const Int128TestCase& test_case) { - std::ostringstream os; - os.flags(test_case.flags); - os.width(test_case.width); - os.fill(kFill); - os << test_case.value; - SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width)); - EXPECT_EQ(test_case.expected, os.str()); -} - -TEST(Int128, OStreamValueTest) { - CheckInt128Case({1, kDec, /*width = */ 0, "1"}); - CheckInt128Case({1, kOct, /*width = */ 0, "1"}); - CheckInt128Case({1, kHex, /*width = */ 0, "1"}); - CheckInt128Case({9, kDec, /*width = */ 0, "9"}); - CheckInt128Case({9, kOct, /*width = */ 0, "11"}); - CheckInt128Case({9, kHex, /*width = */ 0, "9"}); - CheckInt128Case({12345, kDec, /*width = */ 0, "12345"}); - CheckInt128Case({12345, kOct, /*width = */ 0, "30071"}); - CheckInt128Case({12345, kHex, /*width = */ 0, "3039"}); - CheckInt128Case( - {0x8000000000000000, kDec, /*width = */ 0, "9223372036854775808"}); - CheckInt128Case( - {0x8000000000000000, kOct, /*width = */ 0, "1000000000000000000000"}); - CheckInt128Case( - {0x8000000000000000, kHex, /*width = */ 0, "8000000000000000"}); - CheckInt128Case({std::numeric_limits<uint64_t>::max(), kDec, - /*width = */ 0, "18446744073709551615"}); - CheckInt128Case({std::numeric_limits<uint64_t>::max(), kOct, - /*width = */ 0, "1777777777777777777777"}); - CheckInt128Case({std::numeric_limits<uint64_t>::max(), kHex, - /*width = */ 0, "ffffffffffffffff"}); - CheckInt128Case( - {absl::MakeInt128(1, 0), kDec, /*width = */ 0, "18446744073709551616"}); - CheckInt128Case( - {absl::MakeInt128(1, 0), kOct, /*width = */ 0, "2000000000000000000000"}); - CheckInt128Case( - {absl::MakeInt128(1, 0), kHex, /*width = */ 0, "10000000000000000"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(), - std::numeric_limits<uint64_t>::max()), - std::ios::dec, /*width = */ 0, - "170141183460469231731687303715884105727"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(), - std::numeric_limits<uint64_t>::max()), - std::ios::oct, /*width = */ 0, - "1777777777777777777777777777777777777777777"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(), - std::numeric_limits<uint64_t>::max()), - std::ios::hex, /*width = */ 0, - "7fffffffffffffffffffffffffffffff"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0), - std::ios::dec, /*width = */ 0, - "-170141183460469231731687303715884105728"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0), - std::ios::oct, /*width = */ 0, - "2000000000000000000000000000000000000000000"}); - CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0), - std::ios::hex, /*width = */ 0, - "80000000000000000000000000000000"}); - CheckInt128Case({-1, std::ios::dec, /*width = */ 0, "-1"}); - CheckInt128Case({-1, std::ios::oct, /*width = */ 0, - "3777777777777777777777777777777777777777777"}); - CheckInt128Case( - {-1, std::ios::hex, /*width = */ 0, "ffffffffffffffffffffffffffffffff"}); - CheckInt128Case({-12345, std::ios::dec, /*width = */ 0, "-12345"}); - CheckInt128Case({-12345, std::ios::oct, /*width = */ 0, - "3777777777777777777777777777777777777747707"}); - CheckInt128Case({-12345, std::ios::hex, /*width = */ 0, - "ffffffffffffffffffffffffffffcfc7"}); -} - -std::vector<Int128TestCase> GetInt128FormatCases(); -TEST(Int128, OStreamFormatTest) { - for (const Int128TestCase& test_case : GetInt128FormatCases()) { - CheckInt128Case(test_case); - } -} - -std::vector<Int128TestCase> GetInt128FormatCases() { - return { - {0, std::ios_base::fmtflags(), /*width = */ 0, "0"}, - {0, std::ios_base::fmtflags(), /*width = */ 6, "_____0"}, - {0, kPos, /*width = */ 0, "+0"}, - {0, kPos, /*width = */ 6, "____+0"}, - {0, kBase, /*width = */ 0, "0"}, - {0, kBase, /*width = */ 6, "_____0"}, - {0, kBase | kPos, /*width = */ 0, "+0"}, - {0, kBase | kPos, /*width = */ 6, "____+0"}, - {0, kUpper, /*width = */ 0, "0"}, - {0, kUpper, /*width = */ 6, "_____0"}, - {0, kUpper | kPos, /*width = */ 0, "+0"}, - {0, kUpper | kPos, /*width = */ 6, "____+0"}, - {0, kUpper | kBase, /*width = */ 0, "0"}, - {0, kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kUpper | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kLeft, /*width = */ 0, "0"}, - {0, kLeft, /*width = */ 6, "0_____"}, - {0, kLeft | kPos, /*width = */ 0, "+0"}, - {0, kLeft | kPos, /*width = */ 6, "+0____"}, - {0, kLeft | kBase, /*width = */ 0, "0"}, - {0, kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kLeft | kBase | kPos, /*width = */ 0, "+0"}, - {0, kLeft | kBase | kPos, /*width = */ 6, "+0____"}, - {0, kLeft | kUpper, /*width = */ 0, "0"}, - {0, kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kLeft | kUpper | kPos, /*width = */ 6, "+0____"}, - {0, kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"}, - {0, kInt, /*width = */ 0, "0"}, - {0, kInt, /*width = */ 6, "_____0"}, - {0, kInt | kPos, /*width = */ 0, "+0"}, - {0, kInt | kPos, /*width = */ 6, "+____0"}, - {0, kInt | kBase, /*width = */ 0, "0"}, - {0, kInt | kBase, /*width = */ 6, "_____0"}, - {0, kInt | kBase | kPos, /*width = */ 0, "+0"}, - {0, kInt | kBase | kPos, /*width = */ 6, "+____0"}, - {0, kInt | kUpper, /*width = */ 0, "0"}, - {0, kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kInt | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kInt | kUpper | kPos, /*width = */ 6, "+____0"}, - {0, kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"}, - {0, kRight, /*width = */ 0, "0"}, - {0, kRight, /*width = */ 6, "_____0"}, - {0, kRight | kPos, /*width = */ 0, "+0"}, - {0, kRight | kPos, /*width = */ 6, "____+0"}, - {0, kRight | kBase, /*width = */ 0, "0"}, - {0, kRight | kBase, /*width = */ 6, "_____0"}, - {0, kRight | kBase | kPos, /*width = */ 0, "+0"}, - {0, kRight | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kRight | kUpper, /*width = */ 0, "0"}, - {0, kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kRight | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kRight | kUpper | kPos, /*width = */ 6, "____+0"}, - {0, kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kDec, /*width = */ 0, "0"}, - {0, kDec, /*width = */ 6, "_____0"}, - {0, kDec | kPos, /*width = */ 0, "+0"}, - {0, kDec | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kBase, /*width = */ 0, "0"}, - {0, kDec | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kUpper, /*width = */ 0, "0"}, - {0, kDec | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kDec | kUpper | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kLeft, /*width = */ 0, "0"}, - {0, kDec | kLeft, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kPos, /*width = */ 0, "+0"}, - {0, kDec | kLeft | kPos, /*width = */ 6, "+0____"}, - {0, kDec | kLeft | kBase, /*width = */ 0, "0"}, - {0, kDec | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kLeft | kBase | kPos, /*width = */ 6, "+0____"}, - {0, kDec | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+0____"}, - {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"}, - {0, kDec | kInt, /*width = */ 0, "0"}, - {0, kDec | kInt, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kPos, /*width = */ 0, "+0"}, - {0, kDec | kInt | kPos, /*width = */ 6, "+____0"}, - {0, kDec | kInt | kBase, /*width = */ 0, "0"}, - {0, kDec | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kInt | kBase | kPos, /*width = */ 6, "+____0"}, - {0, kDec | kInt | kUpper, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kDec | kInt | kUpper | kPos, /*width = */ 6, "+____0"}, - {0, kDec | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"}, - {0, kDec | kRight, /*width = */ 0, "0"}, - {0, kDec | kRight, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kPos, /*width = */ 0, "+0"}, - {0, kDec | kRight | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kRight | kBase, /*width = */ 0, "0"}, - {0, kDec | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kRight | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kRight | kUpper, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper | kPos, /*width = */ 0, "+0"}, - {0, kDec | kRight | kUpper | kPos, /*width = */ 6, "____+0"}, - {0, kDec | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"}, - {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, - {0, kOct, /*width = */ 0, "0"}, - {0, kOct, /*width = */ 6, "_____0"}, - {0, kOct | kPos, /*width = */ 0, "0"}, - {0, kOct | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kBase, /*width = */ 0, "0"}, - {0, kOct | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kUpper, /*width = */ 0, "0"}, - {0, kOct | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kLeft, /*width = */ 0, "0"}, - {0, kOct | kLeft, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kBase, /*width = */ 0, "0"}, - {0, kOct | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kInt, /*width = */ 0, "0"}, - {0, kOct | kInt, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kBase, /*width = */ 0, "0"}, - {0, kOct | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight, /*width = */ 0, "0"}, - {0, kOct | kRight, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kBase, /*width = */ 0, "0"}, - {0, kOct | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex, /*width = */ 0, "0"}, - {0, kHex, /*width = */ 6, "_____0"}, - {0, kHex | kPos, /*width = */ 0, "0"}, - {0, kHex | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kBase, /*width = */ 0, "0"}, - {0, kHex | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kUpper, /*width = */ 0, "0"}, - {0, kHex | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kLeft, /*width = */ 0, "0"}, - {0, kHex | kLeft, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kBase, /*width = */ 0, "0"}, - {0, kHex | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kInt, /*width = */ 0, "0"}, - {0, kHex | kInt, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kBase, /*width = */ 0, "0"}, - {0, kHex | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight, /*width = */ 0, "0"}, - {0, kHex | kRight, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kBase, /*width = */ 0, "0"}, - {0, kHex | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {42, std::ios_base::fmtflags(), /*width = */ 0, "42"}, - {42, std::ios_base::fmtflags(), /*width = */ 6, "____42"}, - {42, kPos, /*width = */ 0, "+42"}, - {42, kPos, /*width = */ 6, "___+42"}, - {42, kBase, /*width = */ 0, "42"}, - {42, kBase, /*width = */ 6, "____42"}, - {42, kBase | kPos, /*width = */ 0, "+42"}, - {42, kBase | kPos, /*width = */ 6, "___+42"}, - {42, kUpper, /*width = */ 0, "42"}, - {42, kUpper, /*width = */ 6, "____42"}, - {42, kUpper | kPos, /*width = */ 0, "+42"}, - {42, kUpper | kPos, /*width = */ 6, "___+42"}, - {42, kUpper | kBase, /*width = */ 0, "42"}, - {42, kUpper | kBase, /*width = */ 6, "____42"}, - {42, kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kUpper | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kLeft, /*width = */ 0, "42"}, - {42, kLeft, /*width = */ 6, "42____"}, - {42, kLeft | kPos, /*width = */ 0, "+42"}, - {42, kLeft | kPos, /*width = */ 6, "+42___"}, - {42, kLeft | kBase, /*width = */ 0, "42"}, - {42, kLeft | kBase, /*width = */ 6, "42____"}, - {42, kLeft | kBase | kPos, /*width = */ 0, "+42"}, - {42, kLeft | kBase | kPos, /*width = */ 6, "+42___"}, - {42, kLeft | kUpper, /*width = */ 0, "42"}, - {42, kLeft | kUpper, /*width = */ 6, "42____"}, - {42, kLeft | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kLeft | kUpper | kPos, /*width = */ 6, "+42___"}, - {42, kLeft | kUpper | kBase, /*width = */ 0, "42"}, - {42, kLeft | kUpper | kBase, /*width = */ 6, "42____"}, - {42, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"}, - {42, kInt, /*width = */ 0, "42"}, - {42, kInt, /*width = */ 6, "____42"}, - {42, kInt | kPos, /*width = */ 0, "+42"}, - {42, kInt | kPos, /*width = */ 6, "+___42"}, - {42, kInt | kBase, /*width = */ 0, "42"}, - {42, kInt | kBase, /*width = */ 6, "____42"}, - {42, kInt | kBase | kPos, /*width = */ 0, "+42"}, - {42, kInt | kBase | kPos, /*width = */ 6, "+___42"}, - {42, kInt | kUpper, /*width = */ 0, "42"}, - {42, kInt | kUpper, /*width = */ 6, "____42"}, - {42, kInt | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kInt | kUpper | kPos, /*width = */ 6, "+___42"}, - {42, kInt | kUpper | kBase, /*width = */ 0, "42"}, - {42, kInt | kUpper | kBase, /*width = */ 6, "____42"}, - {42, kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"}, - {42, kRight, /*width = */ 0, "42"}, - {42, kRight, /*width = */ 6, "____42"}, - {42, kRight | kPos, /*width = */ 0, "+42"}, - {42, kRight | kPos, /*width = */ 6, "___+42"}, - {42, kRight | kBase, /*width = */ 0, "42"}, - {42, kRight | kBase, /*width = */ 6, "____42"}, - {42, kRight | kBase | kPos, /*width = */ 0, "+42"}, - {42, kRight | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kRight | kUpper, /*width = */ 0, "42"}, - {42, kRight | kUpper, /*width = */ 6, "____42"}, - {42, kRight | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kRight | kUpper | kPos, /*width = */ 6, "___+42"}, - {42, kRight | kUpper | kBase, /*width = */ 0, "42"}, - {42, kRight | kUpper | kBase, /*width = */ 6, "____42"}, - {42, kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kDec, /*width = */ 0, "42"}, - {42, kDec, /*width = */ 6, "____42"}, - {42, kDec | kPos, /*width = */ 0, "+42"}, - {42, kDec | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kBase, /*width = */ 0, "42"}, - {42, kDec | kBase, /*width = */ 6, "____42"}, - {42, kDec | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kUpper, /*width = */ 0, "42"}, - {42, kDec | kUpper, /*width = */ 6, "____42"}, - {42, kDec | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kDec | kUpper | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kUpper | kBase, /*width = */ 0, "42"}, - {42, kDec | kUpper | kBase, /*width = */ 6, "____42"}, - {42, kDec | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kLeft, /*width = */ 0, "42"}, - {42, kDec | kLeft, /*width = */ 6, "42____"}, - {42, kDec | kLeft | kPos, /*width = */ 0, "+42"}, - {42, kDec | kLeft | kPos, /*width = */ 6, "+42___"}, - {42, kDec | kLeft | kBase, /*width = */ 0, "42"}, - {42, kDec | kLeft | kBase, /*width = */ 6, "42____"}, - {42, kDec | kLeft | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kLeft | kBase | kPos, /*width = */ 6, "+42___"}, - {42, kDec | kLeft | kUpper, /*width = */ 0, "42"}, - {42, kDec | kLeft | kUpper, /*width = */ 6, "42____"}, - {42, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+42___"}, - {42, kDec | kLeft | kUpper | kBase, /*width = */ 0, "42"}, - {42, kDec | kLeft | kUpper | kBase, /*width = */ 6, "42____"}, - {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"}, - {42, kDec | kInt, /*width = */ 0, "42"}, - {42, kDec | kInt, /*width = */ 6, "____42"}, - {42, kDec | kInt | kPos, /*width = */ 0, "+42"}, - {42, kDec | kInt | kPos, /*width = */ 6, "+___42"}, - {42, kDec | kInt | kBase, /*width = */ 0, "42"}, - {42, kDec | kInt | kBase, /*width = */ 6, "____42"}, - {42, kDec | kInt | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kInt | kBase | kPos, /*width = */ 6, "+___42"}, - {42, kDec | kInt | kUpper, /*width = */ 0, "42"}, - {42, kDec | kInt | kUpper, /*width = */ 6, "____42"}, - {42, kDec | kInt | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kDec | kInt | kUpper | kPos, /*width = */ 6, "+___42"}, - {42, kDec | kInt | kUpper | kBase, /*width = */ 0, "42"}, - {42, kDec | kInt | kUpper | kBase, /*width = */ 6, "____42"}, - {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"}, - {42, kDec | kRight, /*width = */ 0, "42"}, - {42, kDec | kRight, /*width = */ 6, "____42"}, - {42, kDec | kRight | kPos, /*width = */ 0, "+42"}, - {42, kDec | kRight | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kRight | kBase, /*width = */ 0, "42"}, - {42, kDec | kRight | kBase, /*width = */ 6, "____42"}, - {42, kDec | kRight | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kRight | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kRight | kUpper, /*width = */ 0, "42"}, - {42, kDec | kRight | kUpper, /*width = */ 6, "____42"}, - {42, kDec | kRight | kUpper | kPos, /*width = */ 0, "+42"}, - {42, kDec | kRight | kUpper | kPos, /*width = */ 6, "___+42"}, - {42, kDec | kRight | kUpper | kBase, /*width = */ 0, "42"}, - {42, kDec | kRight | kUpper | kBase, /*width = */ 6, "____42"}, - {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"}, - {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, - {42, kOct, /*width = */ 0, "52"}, - {42, kOct, /*width = */ 6, "____52"}, - {42, kOct | kPos, /*width = */ 0, "52"}, - {42, kOct | kPos, /*width = */ 6, "____52"}, - {42, kOct | kBase, /*width = */ 0, "052"}, - {42, kOct | kBase, /*width = */ 6, "___052"}, - {42, kOct | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kBase | kPos, /*width = */ 6, "___052"}, - {42, kOct | kUpper, /*width = */ 0, "52"}, - {42, kOct | kUpper, /*width = */ 6, "____52"}, - {42, kOct | kUpper | kPos, /*width = */ 0, "52"}, - {42, kOct | kUpper | kPos, /*width = */ 6, "____52"}, - {42, kOct | kUpper | kBase, /*width = */ 0, "052"}, - {42, kOct | kUpper | kBase, /*width = */ 6, "___052"}, - {42, kOct | kUpper | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kUpper | kBase | kPos, /*width = */ 6, "___052"}, - {42, kOct | kLeft, /*width = */ 0, "52"}, - {42, kOct | kLeft, /*width = */ 6, "52____"}, - {42, kOct | kLeft | kPos, /*width = */ 0, "52"}, - {42, kOct | kLeft | kPos, /*width = */ 6, "52____"}, - {42, kOct | kLeft | kBase, /*width = */ 0, "052"}, - {42, kOct | kLeft | kBase, /*width = */ 6, "052___"}, - {42, kOct | kLeft | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kLeft | kBase | kPos, /*width = */ 6, "052___"}, - {42, kOct | kLeft | kUpper, /*width = */ 0, "52"}, - {42, kOct | kLeft | kUpper, /*width = */ 6, "52____"}, - {42, kOct | kLeft | kUpper | kPos, /*width = */ 0, "52"}, - {42, kOct | kLeft | kUpper | kPos, /*width = */ 6, "52____"}, - {42, kOct | kLeft | kUpper | kBase, /*width = */ 0, "052"}, - {42, kOct | kLeft | kUpper | kBase, /*width = */ 6, "052___"}, - {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "052___"}, - {42, kOct | kInt, /*width = */ 0, "52"}, - {42, kOct | kInt, /*width = */ 6, "____52"}, - {42, kOct | kInt | kPos, /*width = */ 0, "52"}, - {42, kOct | kInt | kPos, /*width = */ 6, "____52"}, - {42, kOct | kInt | kBase, /*width = */ 0, "052"}, - {42, kOct | kInt | kBase, /*width = */ 6, "___052"}, - {42, kOct | kInt | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kInt | kBase | kPos, /*width = */ 6, "___052"}, - {42, kOct | kInt | kUpper, /*width = */ 0, "52"}, - {42, kOct | kInt | kUpper, /*width = */ 6, "____52"}, - {42, kOct | kInt | kUpper | kPos, /*width = */ 0, "52"}, - {42, kOct | kInt | kUpper | kPos, /*width = */ 6, "____52"}, - {42, kOct | kInt | kUpper | kBase, /*width = */ 0, "052"}, - {42, kOct | kInt | kUpper | kBase, /*width = */ 6, "___052"}, - {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "___052"}, - {42, kOct | kRight, /*width = */ 0, "52"}, - {42, kOct | kRight, /*width = */ 6, "____52"}, - {42, kOct | kRight | kPos, /*width = */ 0, "52"}, - {42, kOct | kRight | kPos, /*width = */ 6, "____52"}, - {42, kOct | kRight | kBase, /*width = */ 0, "052"}, - {42, kOct | kRight | kBase, /*width = */ 6, "___052"}, - {42, kOct | kRight | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kRight | kBase | kPos, /*width = */ 6, "___052"}, - {42, kOct | kRight | kUpper, /*width = */ 0, "52"}, - {42, kOct | kRight | kUpper, /*width = */ 6, "____52"}, - {42, kOct | kRight | kUpper | kPos, /*width = */ 0, "52"}, - {42, kOct | kRight | kUpper | kPos, /*width = */ 6, "____52"}, - {42, kOct | kRight | kUpper | kBase, /*width = */ 0, "052"}, - {42, kOct | kRight | kUpper | kBase, /*width = */ 6, "___052"}, - {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "052"}, - {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "___052"}, - {42, kHex, /*width = */ 0, "2a"}, - {42, kHex, /*width = */ 6, "____2a"}, - {42, kHex | kPos, /*width = */ 0, "2a"}, - {42, kHex | kPos, /*width = */ 6, "____2a"}, - {42, kHex | kBase, /*width = */ 0, "0x2a"}, - {42, kHex | kBase, /*width = */ 6, "__0x2a"}, - {42, kHex | kBase | kPos, /*width = */ 0, "0x2a"}, - {42, kHex | kBase | kPos, /*width = */ 6, "__0x2a"}, - {42, kHex | kUpper, /*width = */ 0, "2A"}, - {42, kHex | kUpper, /*width = */ 6, "____2A"}, - {42, kHex | kUpper | kPos, /*width = */ 0, "2A"}, - {42, kHex | kUpper | kPos, /*width = */ 6, "____2A"}, - {42, kHex | kUpper | kBase, /*width = */ 0, "0X2A"}, - {42, kHex | kUpper | kBase, /*width = */ 6, "__0X2A"}, - {42, kHex | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, - {42, kHex | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"}, - {42, kHex | kLeft, /*width = */ 0, "2a"}, - {42, kHex | kLeft, /*width = */ 6, "2a____"}, - {42, kHex | kLeft | kPos, /*width = */ 0, "2a"}, - {42, kHex | kLeft | kPos, /*width = */ 6, "2a____"}, - {42, kHex | kLeft | kBase, /*width = */ 0, "0x2a"}, - {42, kHex | kLeft | kBase, /*width = */ 6, "0x2a__"}, - {42, kHex | kLeft | kBase | kPos, /*width = */ 0, "0x2a"}, - {42, kHex | kLeft | kBase | kPos, /*width = */ 6, "0x2a__"}, - {42, kHex | kLeft | kUpper, /*width = */ 0, "2A"}, - {42, kHex | kLeft | kUpper, /*width = */ 6, "2A____"}, - {42, kHex | kLeft | kUpper | kPos, /*width = */ 0, "2A"}, - {42, kHex | kLeft | kUpper | kPos, /*width = */ 6, "2A____"}, - {42, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0X2A"}, - {42, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0X2A__"}, - {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, - {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0X2A__"}, - {42, kHex | kInt, /*width = */ 0, "2a"}, - {42, kHex | kInt, /*width = */ 6, "____2a"}, - {42, kHex | kInt | kPos, /*width = */ 0, "2a"}, - {42, kHex | kInt | kPos, /*width = */ 6, "____2a"}, - {42, kHex | kInt | kBase, /*width = */ 0, "0x2a"}, - {42, kHex | kInt | kBase, /*width = */ 6, "0x__2a"}, - {42, kHex | kInt | kBase | kPos, /*width = */ 0, "0x2a"}, - {42, kHex | kInt | kBase | kPos, /*width = */ 6, "0x__2a"}, - {42, kHex | kInt | kUpper, /*width = */ 0, "2A"}, - {42, kHex | kInt | kUpper, /*width = */ 6, "____2A"}, - {42, kHex | kInt | kUpper | kPos, /*width = */ 0, "2A"}, - {42, kHex | kInt | kUpper | kPos, /*width = */ 6, "____2A"}, - {42, kHex | kInt | kUpper | kBase, /*width = */ 0, "0X2A"}, - {42, kHex | kInt | kUpper | kBase, /*width = */ 6, "0X__2A"}, - {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, - {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "0X__2A"}, - {42, kHex | kRight, /*width = */ 0, "2a"}, - {42, kHex | kRight, /*width = */ 6, "____2a"}, - {42, kHex | kRight | kPos, /*width = */ 0, "2a"}, - {42, kHex | kRight | kPos, /*width = */ 6, "____2a"}, - {42, kHex | kRight | kBase, /*width = */ 0, "0x2a"}, - {42, kHex | kRight | kBase, /*width = */ 6, "__0x2a"}, - {42, kHex | kRight | kBase | kPos, /*width = */ 0, "0x2a"}, - {42, kHex | kRight | kBase | kPos, /*width = */ 6, "__0x2a"}, - {42, kHex | kRight | kUpper, /*width = */ 0, "2A"}, - {42, kHex | kRight | kUpper, /*width = */ 6, "____2A"}, - {42, kHex | kRight | kUpper | kPos, /*width = */ 0, "2A"}, - {42, kHex | kRight | kUpper | kPos, /*width = */ 6, "____2A"}, - {42, kHex | kRight | kUpper | kBase, /*width = */ 0, "0X2A"}, - {42, kHex | kRight | kUpper | kBase, /*width = */ 6, "__0X2A"}, - {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, - {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"}, - {-321, std::ios_base::fmtflags(), /*width = */ 0, "-321"}, - {-321, std::ios_base::fmtflags(), /*width = */ 6, "__-321"}, - {-321, kPos, /*width = */ 0, "-321"}, - {-321, kPos, /*width = */ 6, "__-321"}, - {-321, kBase, /*width = */ 0, "-321"}, - {-321, kBase, /*width = */ 6, "__-321"}, - {-321, kBase | kPos, /*width = */ 0, "-321"}, - {-321, kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kUpper, /*width = */ 0, "-321"}, - {-321, kUpper, /*width = */ 6, "__-321"}, - {-321, kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kUpper | kPos, /*width = */ 6, "__-321"}, - {-321, kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kUpper | kBase, /*width = */ 6, "__-321"}, - {-321, kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kUpper | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kLeft, /*width = */ 0, "-321"}, - {-321, kLeft, /*width = */ 6, "-321__"}, - {-321, kLeft | kPos, /*width = */ 0, "-321"}, - {-321, kLeft | kPos, /*width = */ 6, "-321__"}, - {-321, kLeft | kBase, /*width = */ 0, "-321"}, - {-321, kLeft | kBase, /*width = */ 6, "-321__"}, - {-321, kLeft | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kLeft | kBase | kPos, /*width = */ 6, "-321__"}, - {-321, kLeft | kUpper, /*width = */ 0, "-321"}, - {-321, kLeft | kUpper, /*width = */ 6, "-321__"}, - {-321, kLeft | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kLeft | kUpper | kPos, /*width = */ 6, "-321__"}, - {-321, kLeft | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kLeft | kUpper | kBase, /*width = */ 6, "-321__"}, - {-321, kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"}, - {-321, kInt, /*width = */ 0, "-321"}, - {-321, kInt, /*width = */ 6, "-__321"}, - {-321, kInt | kPos, /*width = */ 0, "-321"}, - {-321, kInt | kPos, /*width = */ 6, "-__321"}, - {-321, kInt | kBase, /*width = */ 0, "-321"}, - {-321, kInt | kBase, /*width = */ 6, "-__321"}, - {-321, kInt | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kInt | kBase | kPos, /*width = */ 6, "-__321"}, - {-321, kInt | kUpper, /*width = */ 0, "-321"}, - {-321, kInt | kUpper, /*width = */ 6, "-__321"}, - {-321, kInt | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kInt | kUpper | kPos, /*width = */ 6, "-__321"}, - {-321, kInt | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kInt | kUpper | kBase, /*width = */ 6, "-__321"}, - {-321, kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"}, - {-321, kRight, /*width = */ 0, "-321"}, - {-321, kRight, /*width = */ 6, "__-321"}, - {-321, kRight | kPos, /*width = */ 0, "-321"}, - {-321, kRight | kPos, /*width = */ 6, "__-321"}, - {-321, kRight | kBase, /*width = */ 0, "-321"}, - {-321, kRight | kBase, /*width = */ 6, "__-321"}, - {-321, kRight | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kRight | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kRight | kUpper, /*width = */ 0, "-321"}, - {-321, kRight | kUpper, /*width = */ 6, "__-321"}, - {-321, kRight | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kRight | kUpper | kPos, /*width = */ 6, "__-321"}, - {-321, kRight | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kRight | kUpper | kBase, /*width = */ 6, "__-321"}, - {-321, kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kDec, /*width = */ 0, "-321"}, - {-321, kDec, /*width = */ 6, "__-321"}, - {-321, kDec | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kBase, /*width = */ 6, "__-321"}, - {-321, kDec | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kUpper, /*width = */ 0, "-321"}, - {-321, kDec | kUpper, /*width = */ 6, "__-321"}, - {-321, kDec | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kUpper | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kUpper | kBase, /*width = */ 6, "__-321"}, - {-321, kDec | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kUpper | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kLeft, /*width = */ 0, "-321"}, - {-321, kDec | kLeft, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kPos, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kBase, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kBase | kPos, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kUpper, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kUpper, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kUpper | kPos, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kUpper | kBase, /*width = */ 6, "-321__"}, - {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"}, - {-321, kDec | kInt, /*width = */ 0, "-321"}, - {-321, kDec | kInt, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kPos, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kBase, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kBase | kPos, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kUpper, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kUpper, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kUpper | kPos, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kUpper | kBase, /*width = */ 6, "-__321"}, - {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"}, - {-321, kDec | kRight, /*width = */ 0, "-321"}, - {-321, kDec | kRight, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kBase, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kBase | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kUpper, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kUpper, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kUpper | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kUpper | kPos, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kUpper | kBase, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kUpper | kBase, /*width = */ 6, "__-321"}, - {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"}, - {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}}; -} - -std::vector<Uint128TestCase> GetUint128FormatCases() { - return { - {0, std::ios_base::fmtflags(), /*width = */ 0, "0"}, - {0, std::ios_base::fmtflags(), /*width = */ 6, "_____0"}, - {0, kPos, /*width = */ 0, "0"}, - {0, kPos, /*width = */ 6, "_____0"}, - {0, kBase, /*width = */ 0, "0"}, - {0, kBase, /*width = */ 6, "_____0"}, - {0, kBase | kPos, /*width = */ 0, "0"}, - {0, kBase | kPos, /*width = */ 6, "_____0"}, - {0, kUpper, /*width = */ 0, "0"}, - {0, kUpper, /*width = */ 6, "_____0"}, - {0, kUpper | kPos, /*width = */ 0, "0"}, - {0, kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kUpper | kBase, /*width = */ 0, "0"}, - {0, kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kLeft, /*width = */ 0, "0"}, - {0, kLeft, /*width = */ 6, "0_____"}, - {0, kLeft | kPos, /*width = */ 0, "0"}, - {0, kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kLeft | kBase, /*width = */ 0, "0"}, - {0, kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper, /*width = */ 0, "0"}, - {0, kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kInt, /*width = */ 0, "0"}, - {0, kInt, /*width = */ 6, "_____0"}, - {0, kInt | kPos, /*width = */ 0, "0"}, - {0, kInt | kPos, /*width = */ 6, "_____0"}, - {0, kInt | kBase, /*width = */ 0, "0"}, - {0, kInt | kBase, /*width = */ 6, "_____0"}, - {0, kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kInt | kUpper, /*width = */ 0, "0"}, - {0, kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kRight, /*width = */ 0, "0"}, - {0, kRight, /*width = */ 6, "_____0"}, - {0, kRight | kPos, /*width = */ 0, "0"}, - {0, kRight | kPos, /*width = */ 6, "_____0"}, - {0, kRight | kBase, /*width = */ 0, "0"}, - {0, kRight | kBase, /*width = */ 6, "_____0"}, - {0, kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kRight | kUpper, /*width = */ 0, "0"}, - {0, kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec, /*width = */ 0, "0"}, - {0, kDec, /*width = */ 6, "_____0"}, - {0, kDec | kPos, /*width = */ 0, "0"}, - {0, kDec | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kBase, /*width = */ 0, "0"}, - {0, kDec | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kUpper, /*width = */ 0, "0"}, - {0, kDec | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kUpper | kPos, /*width = */ 0, "0"}, - {0, kDec | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kLeft, /*width = */ 0, "0"}, - {0, kDec | kLeft, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kPos, /*width = */ 0, "0"}, - {0, kDec | kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kBase, /*width = */ 0, "0"}, - {0, kDec | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kDec | kInt, /*width = */ 0, "0"}, - {0, kDec | kInt, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kPos, /*width = */ 0, "0"}, - {0, kDec | kInt | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kBase, /*width = */ 0, "0"}, - {0, kDec | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kRight, /*width = */ 0, "0"}, - {0, kDec | kRight, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kPos, /*width = */ 0, "0"}, - {0, kDec | kRight | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kBase, /*width = */ 0, "0"}, - {0, kDec | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct, /*width = */ 0, "0"}, - {0, kOct, /*width = */ 6, "_____0"}, - {0, kOct | kPos, /*width = */ 0, "0"}, - {0, kOct | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kBase, /*width = */ 0, "0"}, - {0, kOct | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kUpper, /*width = */ 0, "0"}, - {0, kOct | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kLeft, /*width = */ 0, "0"}, - {0, kOct | kLeft, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kBase, /*width = */ 0, "0"}, - {0, kOct | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kOct | kInt, /*width = */ 0, "0"}, - {0, kOct | kInt, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kBase, /*width = */ 0, "0"}, - {0, kOct | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight, /*width = */ 0, "0"}, - {0, kOct | kRight, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kBase, /*width = */ 0, "0"}, - {0, kOct | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex, /*width = */ 0, "0"}, - {0, kHex, /*width = */ 6, "_____0"}, - {0, kHex | kPos, /*width = */ 0, "0"}, - {0, kHex | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kBase, /*width = */ 0, "0"}, - {0, kHex | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kUpper, /*width = */ 0, "0"}, - {0, kHex | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kLeft, /*width = */ 0, "0"}, - {0, kHex | kLeft, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kBase, /*width = */ 0, "0"}, - {0, kHex | kLeft | kBase, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, - {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, - {0, kHex | kInt, /*width = */ 0, "0"}, - {0, kHex | kInt, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kBase, /*width = */ 0, "0"}, - {0, kHex | kInt | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight, /*width = */ 0, "0"}, - {0, kHex | kRight, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kBase, /*width = */ 0, "0"}, - {0, kHex | kRight | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kBase | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kBase, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, - {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, - {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, - {37, std::ios_base::fmtflags(), /*width = */ 0, "37"}, - {37, std::ios_base::fmtflags(), /*width = */ 6, "____37"}, - {37, kPos, /*width = */ 0, "37"}, - {37, kPos, /*width = */ 6, "____37"}, - {37, kBase, /*width = */ 0, "37"}, - {37, kBase, /*width = */ 6, "____37"}, - {37, kBase | kPos, /*width = */ 0, "37"}, - {37, kBase | kPos, /*width = */ 6, "____37"}, - {37, kUpper, /*width = */ 0, "37"}, - {37, kUpper, /*width = */ 6, "____37"}, - {37, kUpper | kPos, /*width = */ 0, "37"}, - {37, kUpper | kPos, /*width = */ 6, "____37"}, - {37, kUpper | kBase, /*width = */ 0, "37"}, - {37, kUpper | kBase, /*width = */ 6, "____37"}, - {37, kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kLeft, /*width = */ 0, "37"}, - {37, kLeft, /*width = */ 6, "37____"}, - {37, kLeft | kPos, /*width = */ 0, "37"}, - {37, kLeft | kPos, /*width = */ 6, "37____"}, - {37, kLeft | kBase, /*width = */ 0, "37"}, - {37, kLeft | kBase, /*width = */ 6, "37____"}, - {37, kLeft | kBase | kPos, /*width = */ 0, "37"}, - {37, kLeft | kBase | kPos, /*width = */ 6, "37____"}, - {37, kLeft | kUpper, /*width = */ 0, "37"}, - {37, kLeft | kUpper, /*width = */ 6, "37____"}, - {37, kLeft | kUpper | kPos, /*width = */ 0, "37"}, - {37, kLeft | kUpper | kPos, /*width = */ 6, "37____"}, - {37, kLeft | kUpper | kBase, /*width = */ 0, "37"}, - {37, kLeft | kUpper | kBase, /*width = */ 6, "37____"}, - {37, kLeft | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kLeft | kUpper | kBase | kPos, /*width = */ 6, "37____"}, - {37, kInt, /*width = */ 0, "37"}, - {37, kInt, /*width = */ 6, "____37"}, - {37, kInt | kPos, /*width = */ 0, "37"}, - {37, kInt | kPos, /*width = */ 6, "____37"}, - {37, kInt | kBase, /*width = */ 0, "37"}, - {37, kInt | kBase, /*width = */ 6, "____37"}, - {37, kInt | kBase | kPos, /*width = */ 0, "37"}, - {37, kInt | kBase | kPos, /*width = */ 6, "____37"}, - {37, kInt | kUpper, /*width = */ 0, "37"}, - {37, kInt | kUpper, /*width = */ 6, "____37"}, - {37, kInt | kUpper | kPos, /*width = */ 0, "37"}, - {37, kInt | kUpper | kPos, /*width = */ 6, "____37"}, - {37, kInt | kUpper | kBase, /*width = */ 0, "37"}, - {37, kInt | kUpper | kBase, /*width = */ 6, "____37"}, - {37, kInt | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kInt | kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kRight, /*width = */ 0, "37"}, - {37, kRight, /*width = */ 6, "____37"}, - {37, kRight | kPos, /*width = */ 0, "37"}, - {37, kRight | kPos, /*width = */ 6, "____37"}, - {37, kRight | kBase, /*width = */ 0, "37"}, - {37, kRight | kBase, /*width = */ 6, "____37"}, - {37, kRight | kBase | kPos, /*width = */ 0, "37"}, - {37, kRight | kBase | kPos, /*width = */ 6, "____37"}, - {37, kRight | kUpper, /*width = */ 0, "37"}, - {37, kRight | kUpper, /*width = */ 6, "____37"}, - {37, kRight | kUpper | kPos, /*width = */ 0, "37"}, - {37, kRight | kUpper | kPos, /*width = */ 6, "____37"}, - {37, kRight | kUpper | kBase, /*width = */ 0, "37"}, - {37, kRight | kUpper | kBase, /*width = */ 6, "____37"}, - {37, kRight | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kRight | kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec, /*width = */ 0, "37"}, - {37, kDec, /*width = */ 6, "____37"}, - {37, kDec | kPos, /*width = */ 0, "37"}, - {37, kDec | kPos, /*width = */ 6, "____37"}, - {37, kDec | kBase, /*width = */ 0, "37"}, - {37, kDec | kBase, /*width = */ 6, "____37"}, - {37, kDec | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec | kUpper, /*width = */ 0, "37"}, - {37, kDec | kUpper, /*width = */ 6, "____37"}, - {37, kDec | kUpper | kPos, /*width = */ 0, "37"}, - {37, kDec | kUpper | kPos, /*width = */ 6, "____37"}, - {37, kDec | kUpper | kBase, /*width = */ 0, "37"}, - {37, kDec | kUpper | kBase, /*width = */ 6, "____37"}, - {37, kDec | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec | kLeft, /*width = */ 0, "37"}, - {37, kDec | kLeft, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kPos, /*width = */ 0, "37"}, - {37, kDec | kLeft | kPos, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kBase, /*width = */ 0, "37"}, - {37, kDec | kLeft | kBase, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kLeft | kBase | kPos, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kUpper, /*width = */ 0, "37"}, - {37, kDec | kLeft | kUpper, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kUpper | kPos, /*width = */ 0, "37"}, - {37, kDec | kLeft | kUpper | kPos, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kUpper | kBase, /*width = */ 0, "37"}, - {37, kDec | kLeft | kUpper | kBase, /*width = */ 6, "37____"}, - {37, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "37____"}, - {37, kDec | kInt, /*width = */ 0, "37"}, - {37, kDec | kInt, /*width = */ 6, "____37"}, - {37, kDec | kInt | kPos, /*width = */ 0, "37"}, - {37, kDec | kInt | kPos, /*width = */ 6, "____37"}, - {37, kDec | kInt | kBase, /*width = */ 0, "37"}, - {37, kDec | kInt | kBase, /*width = */ 6, "____37"}, - {37, kDec | kInt | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kInt | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec | kInt | kUpper, /*width = */ 0, "37"}, - {37, kDec | kInt | kUpper, /*width = */ 6, "____37"}, - {37, kDec | kInt | kUpper | kPos, /*width = */ 0, "37"}, - {37, kDec | kInt | kUpper | kPos, /*width = */ 6, "____37"}, - {37, kDec | kInt | kUpper | kBase, /*width = */ 0, "37"}, - {37, kDec | kInt | kUpper | kBase, /*width = */ 6, "____37"}, - {37, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec | kRight, /*width = */ 0, "37"}, - {37, kDec | kRight, /*width = */ 6, "____37"}, - {37, kDec | kRight | kPos, /*width = */ 0, "37"}, - {37, kDec | kRight | kPos, /*width = */ 6, "____37"}, - {37, kDec | kRight | kBase, /*width = */ 0, "37"}, - {37, kDec | kRight | kBase, /*width = */ 6, "____37"}, - {37, kDec | kRight | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kRight | kBase | kPos, /*width = */ 6, "____37"}, - {37, kDec | kRight | kUpper, /*width = */ 0, "37"}, - {37, kDec | kRight | kUpper, /*width = */ 6, "____37"}, - {37, kDec | kRight | kUpper | kPos, /*width = */ 0, "37"}, - {37, kDec | kRight | kUpper | kPos, /*width = */ 6, "____37"}, - {37, kDec | kRight | kUpper | kBase, /*width = */ 0, "37"}, - {37, kDec | kRight | kUpper | kBase, /*width = */ 6, "____37"}, - {37, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "37"}, - {37, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "____37"}, - {37, kOct, /*width = */ 0, "45"}, - {37, kOct, /*width = */ 6, "____45"}, - {37, kOct | kPos, /*width = */ 0, "45"}, - {37, kOct | kPos, /*width = */ 6, "____45"}, - {37, kOct | kBase, /*width = */ 0, "045"}, - {37, kOct | kBase, /*width = */ 6, "___045"}, - {37, kOct | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kBase | kPos, /*width = */ 6, "___045"}, - {37, kOct | kUpper, /*width = */ 0, "45"}, - {37, kOct | kUpper, /*width = */ 6, "____45"}, - {37, kOct | kUpper | kPos, /*width = */ 0, "45"}, - {37, kOct | kUpper | kPos, /*width = */ 6, "____45"}, - {37, kOct | kUpper | kBase, /*width = */ 0, "045"}, - {37, kOct | kUpper | kBase, /*width = */ 6, "___045"}, - {37, kOct | kUpper | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kUpper | kBase | kPos, /*width = */ 6, "___045"}, - {37, kOct | kLeft, /*width = */ 0, "45"}, - {37, kOct | kLeft, /*width = */ 6, "45____"}, - {37, kOct | kLeft | kPos, /*width = */ 0, "45"}, - {37, kOct | kLeft | kPos, /*width = */ 6, "45____"}, - {37, kOct | kLeft | kBase, /*width = */ 0, "045"}, - {37, kOct | kLeft | kBase, /*width = */ 6, "045___"}, - {37, kOct | kLeft | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kLeft | kBase | kPos, /*width = */ 6, "045___"}, - {37, kOct | kLeft | kUpper, /*width = */ 0, "45"}, - {37, kOct | kLeft | kUpper, /*width = */ 6, "45____"}, - {37, kOct | kLeft | kUpper | kPos, /*width = */ 0, "45"}, - {37, kOct | kLeft | kUpper | kPos, /*width = */ 6, "45____"}, - {37, kOct | kLeft | kUpper | kBase, /*width = */ 0, "045"}, - {37, kOct | kLeft | kUpper | kBase, /*width = */ 6, "045___"}, - {37, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "045___"}, - {37, kOct | kInt, /*width = */ 0, "45"}, - {37, kOct | kInt, /*width = */ 6, "____45"}, - {37, kOct | kInt | kPos, /*width = */ 0, "45"}, - {37, kOct | kInt | kPos, /*width = */ 6, "____45"}, - {37, kOct | kInt | kBase, /*width = */ 0, "045"}, - {37, kOct | kInt | kBase, /*width = */ 6, "___045"}, - {37, kOct | kInt | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kInt | kBase | kPos, /*width = */ 6, "___045"}, - {37, kOct | kInt | kUpper, /*width = */ 0, "45"}, - {37, kOct | kInt | kUpper, /*width = */ 6, "____45"}, - {37, kOct | kInt | kUpper | kPos, /*width = */ 0, "45"}, - {37, kOct | kInt | kUpper | kPos, /*width = */ 6, "____45"}, - {37, kOct | kInt | kUpper | kBase, /*width = */ 0, "045"}, - {37, kOct | kInt | kUpper | kBase, /*width = */ 6, "___045"}, - {37, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "___045"}, - {37, kOct | kRight, /*width = */ 0, "45"}, - {37, kOct | kRight, /*width = */ 6, "____45"}, - {37, kOct | kRight | kPos, /*width = */ 0, "45"}, - {37, kOct | kRight | kPos, /*width = */ 6, "____45"}, - {37, kOct | kRight | kBase, /*width = */ 0, "045"}, - {37, kOct | kRight | kBase, /*width = */ 6, "___045"}, - {37, kOct | kRight | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kRight | kBase | kPos, /*width = */ 6, "___045"}, - {37, kOct | kRight | kUpper, /*width = */ 0, "45"}, - {37, kOct | kRight | kUpper, /*width = */ 6, "____45"}, - {37, kOct | kRight | kUpper | kPos, /*width = */ 0, "45"}, - {37, kOct | kRight | kUpper | kPos, /*width = */ 6, "____45"}, - {37, kOct | kRight | kUpper | kBase, /*width = */ 0, "045"}, - {37, kOct | kRight | kUpper | kBase, /*width = */ 6, "___045"}, - {37, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "045"}, - {37, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "___045"}, - {37, kHex, /*width = */ 0, "25"}, - {37, kHex, /*width = */ 6, "____25"}, - {37, kHex | kPos, /*width = */ 0, "25"}, - {37, kHex | kPos, /*width = */ 6, "____25"}, - {37, kHex | kBase, /*width = */ 0, "0x25"}, - {37, kHex | kBase, /*width = */ 6, "__0x25"}, - {37, kHex | kBase | kPos, /*width = */ 0, "0x25"}, - {37, kHex | kBase | kPos, /*width = */ 6, "__0x25"}, - {37, kHex | kUpper, /*width = */ 0, "25"}, - {37, kHex | kUpper, /*width = */ 6, "____25"}, - {37, kHex | kUpper | kPos, /*width = */ 0, "25"}, - {37, kHex | kUpper | kPos, /*width = */ 6, "____25"}, - {37, kHex | kUpper | kBase, /*width = */ 0, "0X25"}, - {37, kHex | kUpper | kBase, /*width = */ 6, "__0X25"}, - {37, kHex | kUpper | kBase | kPos, /*width = */ 0, "0X25"}, - {37, kHex | kUpper | kBase | kPos, /*width = */ 6, "__0X25"}, - {37, kHex | kLeft, /*width = */ 0, "25"}, - {37, kHex | kLeft, /*width = */ 6, "25____"}, - {37, kHex | kLeft | kPos, /*width = */ 0, "25"}, - {37, kHex | kLeft | kPos, /*width = */ 6, "25____"}, - {37, kHex | kLeft | kBase, /*width = */ 0, "0x25"}, - {37, kHex | kLeft | kBase, /*width = */ 6, "0x25__"}, - {37, kHex | kLeft | kBase | kPos, /*width = */ 0, "0x25"}, - {37, kHex | kLeft | kBase | kPos, /*width = */ 6, "0x25__"}, - {37, kHex | kLeft | kUpper, /*width = */ 0, "25"}, - {37, kHex | kLeft | kUpper, /*width = */ 6, "25____"}, - {37, kHex | kLeft | kUpper | kPos, /*width = */ 0, "25"}, - {37, kHex | kLeft | kUpper | kPos, /*width = */ 6, "25____"}, - {37, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0X25"}, - {37, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0X25__"}, - {37, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0X25"}, - {37, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0X25__"}, - {37, kHex | kInt, /*width = */ 0, "25"}, - {37, kHex | kInt, /*width = */ 6, "____25"}, - {37, kHex | kInt | kPos, /*width = */ 0, "25"}, - {37, kHex | kInt | kPos, /*width = */ 6, "____25"}, - {37, kHex | kInt | kBase, /*width = */ 0, "0x25"}, - {37, kHex | kInt | kBase, /*width = */ 6, "0x__25"}, - {37, kHex | kInt | kBase | kPos, /*width = */ 0, "0x25"}, - {37, kHex | kInt | kBase | kPos, /*width = */ 6, "0x__25"}, - {37, kHex | kInt | kUpper, /*width = */ 0, "25"}, - {37, kHex | kInt | kUpper, /*width = */ 6, "____25"}, - {37, kHex | kInt | kUpper | kPos, /*width = */ 0, "25"}, - {37, kHex | kInt | kUpper | kPos, /*width = */ 6, "____25"}, - {37, kHex | kInt | kUpper | kBase, /*width = */ 0, "0X25"}, - {37, kHex | kInt | kUpper | kBase, /*width = */ 6, "0X__25"}, - {37, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0X25"}, - {37, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "0X__25"}, - {37, kHex | kRight, /*width = */ 0, "25"}, - {37, kHex | kRight, /*width = */ 6, "____25"}, - {37, kHex | kRight | kPos, /*width = */ 0, "25"}, - {37, kHex | kRight | kPos, /*width = */ 6, "____25"}, - {37, kHex | kRight | kBase, /*width = */ 0, "0x25"}, - {37, kHex | kRight | kBase, /*width = */ 6, "__0x25"}, - {37, kHex | kRight | kBase | kPos, /*width = */ 0, "0x25"}, - {37, kHex | kRight | kBase | kPos, /*width = */ 6, "__0x25"}, - {37, kHex | kRight | kUpper, /*width = */ 0, "25"}, - {37, kHex | kRight | kUpper, /*width = */ 6, "____25"}, - {37, kHex | kRight | kUpper | kPos, /*width = */ 0, "25"}, - {37, kHex | kRight | kUpper | kPos, /*width = */ 6, "____25"}, - {37, kHex | kRight | kUpper | kBase, /*width = */ 0, "0X25"}, - {37, kHex | kRight | kUpper | kBase, /*width = */ 6, "__0X25"}, - {37, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0X25"}, - {37, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "__0X25"}}; -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/numeric/int128_test.cc b/third_party/abseil_cpp/absl/numeric/int128_test.cc deleted file mode 100644 index bc86c714acce..000000000000 --- a/third_party/abseil_cpp/absl/numeric/int128_test.cc +++ /dev/null @@ -1,1225 +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/numeric/int128.h" - -#include <algorithm> -#include <limits> -#include <random> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/internal/cycleclock.h" -#include "absl/hash/hash_testing.h" -#include "absl/meta/type_traits.h" - -#if defined(_MSC_VER) && _MSC_VER == 1900 -// Disable "unary minus operator applied to unsigned type" warnings in Microsoft -// Visual C++ 14 (2015). -#pragma warning(disable:4146) -#endif - -namespace { - -template <typename T> -class Uint128IntegerTraitsTest : public ::testing::Test {}; -typedef ::testing::Types<bool, char, signed char, unsigned char, char16_t, - char32_t, wchar_t, - short, // NOLINT(runtime/int) - unsigned short, // NOLINT(runtime/int) - int, unsigned int, - long, // NOLINT(runtime/int) - unsigned long, // NOLINT(runtime/int) - long long, // NOLINT(runtime/int) - unsigned long long> // NOLINT(runtime/int) - IntegerTypes; - -template <typename T> -class Uint128FloatTraitsTest : public ::testing::Test {}; -typedef ::testing::Types<float, double, long double> FloatingPointTypes; - -TYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes); - -TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) { - static_assert(std::is_constructible<absl::uint128, TypeParam>::value, - "absl::uint128 must be constructible from TypeParam"); - static_assert(std::is_assignable<absl::uint128&, TypeParam>::value, - "absl::uint128 must be assignable from TypeParam"); - static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value, - "TypeParam must not be assignable from absl::uint128"); -} - -TYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes); - -TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) { - static_assert(std::is_constructible<absl::uint128, TypeParam>::value, - "absl::uint128 must be constructible from TypeParam"); - static_assert(!std::is_assignable<absl::uint128&, TypeParam>::value, - "absl::uint128 must not be assignable from TypeParam"); - static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value, - "TypeParam must not be assignable from absl::uint128"); -} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -// These type traits done separately as TYPED_TEST requires typeinfo, and not -// all platforms have this for __int128 even though they define the type. -TEST(Uint128, IntrinsicTypeTraitsTest) { - static_assert(std::is_constructible<absl::uint128, __int128>::value, - "absl::uint128 must be constructible from __int128"); - static_assert(std::is_assignable<absl::uint128&, __int128>::value, - "absl::uint128 must be assignable from __int128"); - static_assert(!std::is_assignable<__int128&, absl::uint128>::value, - "__int128 must not be assignable from absl::uint128"); - - static_assert(std::is_constructible<absl::uint128, unsigned __int128>::value, - "absl::uint128 must be constructible from unsigned __int128"); - static_assert(std::is_assignable<absl::uint128&, unsigned __int128>::value, - "absl::uint128 must be assignable from unsigned __int128"); - static_assert(!std::is_assignable<unsigned __int128&, absl::uint128>::value, - "unsigned __int128 must not be assignable from absl::uint128"); -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -TEST(Uint128, TrivialTraitsTest) { - static_assert(absl::is_trivially_default_constructible<absl::uint128>::value, - ""); - static_assert(absl::is_trivially_copy_constructible<absl::uint128>::value, - ""); - static_assert(absl::is_trivially_copy_assignable<absl::uint128>::value, ""); - static_assert(std::is_trivially_destructible<absl::uint128>::value, ""); -} - -TEST(Uint128, AllTests) { - absl::uint128 zero = 0; - absl::uint128 one = 1; - absl::uint128 one_2arg = absl::MakeUint128(0, 1); - absl::uint128 two = 2; - absl::uint128 three = 3; - absl::uint128 big = absl::MakeUint128(2000, 2); - absl::uint128 big_minus_one = absl::MakeUint128(2000, 1); - absl::uint128 bigger = absl::MakeUint128(2001, 1); - absl::uint128 biggest = absl::Uint128Max(); - absl::uint128 high_low = absl::MakeUint128(1, 0); - absl::uint128 low_high = - absl::MakeUint128(0, std::numeric_limits<uint64_t>::max()); - EXPECT_LT(one, two); - EXPECT_GT(two, one); - EXPECT_LT(one, big); - EXPECT_LT(one, big); - EXPECT_EQ(one, one_2arg); - EXPECT_NE(one, two); - EXPECT_GT(big, one); - EXPECT_GE(big, two); - EXPECT_GE(big, big_minus_one); - EXPECT_GT(big, big_minus_one); - EXPECT_LT(big_minus_one, big); - EXPECT_LE(big_minus_one, big); - EXPECT_NE(big_minus_one, big); - EXPECT_LT(big, biggest); - EXPECT_LE(big, biggest); - EXPECT_GT(biggest, big); - EXPECT_GE(biggest, big); - EXPECT_EQ(big, ~~big); - EXPECT_EQ(one, one | one); - EXPECT_EQ(big, big | big); - EXPECT_EQ(one, one | zero); - EXPECT_EQ(one, one & one); - EXPECT_EQ(big, big & big); - EXPECT_EQ(zero, one & zero); - EXPECT_EQ(zero, big & ~big); - EXPECT_EQ(zero, one ^ one); - EXPECT_EQ(zero, big ^ big); - EXPECT_EQ(one, one ^ zero); - - // Shift operators. - EXPECT_EQ(big, big << 0); - EXPECT_EQ(big, big >> 0); - EXPECT_GT(big << 1, big); - EXPECT_LT(big >> 1, big); - EXPECT_EQ(big, (big << 10) >> 10); - EXPECT_EQ(big, (big >> 1) << 1); - EXPECT_EQ(one, (one << 80) >> 80); - EXPECT_EQ(zero, (one >> 80) << 80); - - // Shift assignments. - absl::uint128 big_copy = big; - EXPECT_EQ(big << 0, big_copy <<= 0); - big_copy = big; - EXPECT_EQ(big >> 0, big_copy >>= 0); - big_copy = big; - EXPECT_EQ(big << 1, big_copy <<= 1); - big_copy = big; - EXPECT_EQ(big >> 1, big_copy >>= 1); - big_copy = big; - EXPECT_EQ(big << 10, big_copy <<= 10); - big_copy = big; - EXPECT_EQ(big >> 10, big_copy >>= 10); - big_copy = big; - EXPECT_EQ(big << 64, big_copy <<= 64); - big_copy = big; - EXPECT_EQ(big >> 64, big_copy >>= 64); - big_copy = big; - EXPECT_EQ(big << 73, big_copy <<= 73); - big_copy = big; - EXPECT_EQ(big >> 73, big_copy >>= 73); - - EXPECT_EQ(absl::Uint128High64(biggest), std::numeric_limits<uint64_t>::max()); - EXPECT_EQ(absl::Uint128Low64(biggest), std::numeric_limits<uint64_t>::max()); - EXPECT_EQ(zero + one, one); - EXPECT_EQ(one + one, two); - EXPECT_EQ(big_minus_one + one, big); - EXPECT_EQ(one - one, zero); - EXPECT_EQ(one - zero, one); - EXPECT_EQ(zero - one, biggest); - EXPECT_EQ(big - big, zero); - EXPECT_EQ(big - one, big_minus_one); - EXPECT_EQ(big + std::numeric_limits<uint64_t>::max(), bigger); - EXPECT_EQ(biggest + 1, zero); - EXPECT_EQ(zero - 1, biggest); - EXPECT_EQ(high_low - one, low_high); - EXPECT_EQ(low_high + one, high_low); - EXPECT_EQ(absl::Uint128High64((absl::uint128(1) << 64) - 1), 0); - EXPECT_EQ(absl::Uint128Low64((absl::uint128(1) << 64) - 1), - std::numeric_limits<uint64_t>::max()); - EXPECT_TRUE(!!one); - EXPECT_TRUE(!!high_low); - EXPECT_FALSE(!!zero); - EXPECT_FALSE(!one); - EXPECT_FALSE(!high_low); - EXPECT_TRUE(!zero); - EXPECT_TRUE(zero == 0); // NOLINT(readability/check) - EXPECT_FALSE(zero != 0); // NOLINT(readability/check) - EXPECT_FALSE(one == 0); // NOLINT(readability/check) - EXPECT_TRUE(one != 0); // NOLINT(readability/check) - EXPECT_FALSE(high_low == 0); // NOLINT(readability/check) - EXPECT_TRUE(high_low != 0); // NOLINT(readability/check) - - absl::uint128 test = zero; - EXPECT_EQ(++test, one); - EXPECT_EQ(test, one); - EXPECT_EQ(test++, one); - EXPECT_EQ(test, two); - EXPECT_EQ(test -= 2, zero); - EXPECT_EQ(test, zero); - EXPECT_EQ(test += 2, two); - EXPECT_EQ(test, two); - EXPECT_EQ(--test, one); - EXPECT_EQ(test, one); - EXPECT_EQ(test--, one); - EXPECT_EQ(test, zero); - EXPECT_EQ(test |= three, three); - EXPECT_EQ(test &= one, one); - EXPECT_EQ(test ^= three, two); - EXPECT_EQ(test >>= 1, one); - EXPECT_EQ(test <<= 1, two); - - EXPECT_EQ(big, -(-big)); - EXPECT_EQ(two, -((-one) - 1)); - EXPECT_EQ(absl::Uint128Max(), -one); - EXPECT_EQ(zero, -zero); - - EXPECT_EQ(absl::Uint128Max(), absl::kuint128max); -} - -TEST(Uint128, ConversionTests) { - EXPECT_TRUE(absl::MakeUint128(1, 0)); - -#ifdef ABSL_HAVE_INTRINSIC_INT128 - unsigned __int128 intrinsic = - (static_cast<unsigned __int128>(0x3a5b76c209de76f6) << 64) + - 0x1f25e1d63a2b46c5; - absl::uint128 custom = - absl::MakeUint128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5); - - EXPECT_EQ(custom, absl::uint128(intrinsic)); - EXPECT_EQ(custom, absl::uint128(static_cast<__int128>(intrinsic))); - EXPECT_EQ(intrinsic, static_cast<unsigned __int128>(custom)); - EXPECT_EQ(intrinsic, static_cast<__int128>(custom)); -#endif // ABSL_HAVE_INTRINSIC_INT128 - - // verify that an integer greater than 2**64 that can be stored precisely - // inside a double is converted to a absl::uint128 without loss of - // information. - double precise_double = 0x530e * std::pow(2.0, 64.0) + 0xda74000000000000; - absl::uint128 from_precise_double(precise_double); - absl::uint128 from_precise_ints = - absl::MakeUint128(0x530e, 0xda74000000000000); - EXPECT_EQ(from_precise_double, from_precise_ints); - EXPECT_DOUBLE_EQ(static_cast<double>(from_precise_ints), precise_double); - - double approx_double = 0xffffeeeeddddcccc * std::pow(2.0, 64.0) + - 0xbbbbaaaa99998888; - absl::uint128 from_approx_double(approx_double); - EXPECT_DOUBLE_EQ(static_cast<double>(from_approx_double), approx_double); - - double round_to_zero = 0.7; - double round_to_five = 5.8; - double round_to_nine = 9.3; - EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0); - EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5); - EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9); - - absl::uint128 highest_precision_in_long_double = - ~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits); - EXPECT_EQ(highest_precision_in_long_double, - static_cast<absl::uint128>( - static_cast<long double>(highest_precision_in_long_double))); - // Apply a mask just to make sure all the bits are the right place. - const absl::uint128 arbitrary_mask = - absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468); - EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask, - static_cast<absl::uint128>(static_cast<long double>( - highest_precision_in_long_double & arbitrary_mask))); - - EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0); -} - -TEST(Uint128, OperatorAssignReturnRef) { - absl::uint128 v(1); - (v += 4) -= 3; - EXPECT_EQ(2, v); -} - -TEST(Uint128, Multiply) { - absl::uint128 a, b, c; - - // Zero test. - a = 0; - b = 0; - c = a * b; - EXPECT_EQ(0, c); - - // Max carries. - a = absl::uint128(0) - 1; - b = absl::uint128(0) - 1; - c = a * b; - EXPECT_EQ(1, c); - - // Self-operation with max carries. - c = absl::uint128(0) - 1; - c *= c; - EXPECT_EQ(1, c); - - // 1-bit x 1-bit. - for (int i = 0; i < 64; ++i) { - for (int j = 0; j < 64; ++j) { - a = absl::uint128(1) << i; - b = absl::uint128(1) << j; - c = a * b; - EXPECT_EQ(absl::uint128(1) << (i + j), c); - } - } - - // Verified with dc. - a = absl::MakeUint128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888); - b = absl::MakeUint128(0x7777666655554444, 0x3333222211110000); - c = a * b; - EXPECT_EQ(absl::MakeUint128(0x530EDA741C71D4C3, 0xBF25975319080000), c); - EXPECT_EQ(0, c - b * a); - EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); - - // Verified with dc. - a = absl::MakeUint128(0x0123456789abcdef, 0xfedcba9876543210); - b = absl::MakeUint128(0x02468ace13579bdf, 0xfdb97531eca86420); - c = a * b; - EXPECT_EQ(absl::MakeUint128(0x97a87f4f261ba3f2, 0x342d0bbf48948200), c); - EXPECT_EQ(0, c - b * a); - EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); -} - -TEST(Uint128, AliasTests) { - absl::uint128 x1 = absl::MakeUint128(1, 2); - absl::uint128 x2 = absl::MakeUint128(2, 4); - x1 += x1; - EXPECT_EQ(x2, x1); - - absl::uint128 x3 = absl::MakeUint128(1, static_cast<uint64_t>(1) << 63); - absl::uint128 x4 = absl::MakeUint128(3, 0); - x3 += x3; - EXPECT_EQ(x4, x3); -} - -TEST(Uint128, DivideAndMod) { - using std::swap; - - // a := q * b + r - absl::uint128 a, b, q, r; - - // Zero test. - a = 0; - b = 123; - q = a / b; - r = a % b; - EXPECT_EQ(0, q); - EXPECT_EQ(0, r); - - a = absl::MakeUint128(0x530eda741c71d4c3, 0xbf25975319080000); - q = absl::MakeUint128(0x4de2cab081, 0x14c34ab4676e4bab); - b = absl::uint128(0x1110001); - r = absl::uint128(0x3eb455); - ASSERT_EQ(a, q * b + r); // Sanity-check. - - absl::uint128 result_q, result_r; - result_q = a / b; - result_r = a % b; - EXPECT_EQ(q, result_q); - EXPECT_EQ(r, result_r); - - // Try the other way around. - swap(q, b); - result_q = a / b; - result_r = a % b; - EXPECT_EQ(q, result_q); - EXPECT_EQ(r, result_r); - // Restore. - swap(b, q); - - // Dividend < divisor; result should be q:0 r:<dividend>. - swap(a, b); - result_q = a / b; - result_r = a % b; - EXPECT_EQ(0, result_q); - EXPECT_EQ(a, result_r); - // Try the other way around. - swap(a, q); - result_q = a / b; - result_r = a % b; - EXPECT_EQ(0, result_q); - EXPECT_EQ(a, result_r); - // Restore. - swap(q, a); - swap(b, a); - - // Try a large remainder. - b = a / 2 + 1; - absl::uint128 expected_r = - absl::MakeUint128(0x29876d3a0e38ea61, 0xdf92cba98c83ffff); - // Sanity checks. - ASSERT_EQ(a / 2 - 1, expected_r); - ASSERT_EQ(a, b + expected_r); - result_q = a / b; - result_r = a % b; - EXPECT_EQ(1, result_q); - EXPECT_EQ(expected_r, result_r); -} - -TEST(Uint128, DivideAndModRandomInputs) { - const int kNumIters = 1 << 18; - std::minstd_rand random(testing::UnitTest::GetInstance()->random_seed()); - std::uniform_int_distribution<uint64_t> uniform_uint64; - for (int i = 0; i < kNumIters; ++i) { - const absl::uint128 a = - absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)); - const absl::uint128 b = - absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)); - if (b == 0) { - continue; // Avoid a div-by-zero. - } - const absl::uint128 q = a / b; - const absl::uint128 r = a % b; - ASSERT_EQ(a, b * q + r); - } -} - -TEST(Uint128, ConstexprTest) { - constexpr absl::uint128 zero = absl::uint128(); - constexpr absl::uint128 one = 1; - constexpr absl::uint128 minus_two = -2; - EXPECT_EQ(zero, absl::uint128(0)); - EXPECT_EQ(one, absl::uint128(1)); - EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2)); -} - -TEST(Uint128, NumericLimitsTest) { - static_assert(std::numeric_limits<absl::uint128>::is_specialized, ""); - static_assert(!std::numeric_limits<absl::uint128>::is_signed, ""); - static_assert(std::numeric_limits<absl::uint128>::is_integer, ""); - EXPECT_EQ(static_cast<int>(128 * std::log10(2)), - std::numeric_limits<absl::uint128>::digits10); - EXPECT_EQ(0, std::numeric_limits<absl::uint128>::min()); - EXPECT_EQ(0, std::numeric_limits<absl::uint128>::lowest()); - EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max()); -} - -TEST(Uint128, Hash) { - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ - // Some simple values - absl::uint128{0}, - absl::uint128{1}, - ~absl::uint128{}, - // 64 bit limits - absl::uint128{std::numeric_limits<int64_t>::max()}, - absl::uint128{std::numeric_limits<uint64_t>::max()} + 0, - absl::uint128{std::numeric_limits<uint64_t>::max()} + 1, - absl::uint128{std::numeric_limits<uint64_t>::max()} + 2, - // Keeping high same - absl::uint128{1} << 62, - absl::uint128{1} << 63, - // Keeping low same - absl::uint128{1} << 64, - absl::uint128{1} << 65, - // 128 bit limits - std::numeric_limits<absl::uint128>::max(), - std::numeric_limits<absl::uint128>::max() - 1, - std::numeric_limits<absl::uint128>::min() + 1, - std::numeric_limits<absl::uint128>::min(), - })); -} - - -TEST(Int128Uint128, ConversionTest) { - absl::int128 nonnegative_signed_values[] = { - 0, - 1, - 0xffeeddccbbaa9988, - absl::MakeInt128(0x7766554433221100, 0), - absl::MakeInt128(0x1234567890abcdef, 0xfedcba0987654321), - absl::Int128Max()}; - for (absl::int128 value : nonnegative_signed_values) { - EXPECT_EQ(value, absl::int128(absl::uint128(value))); - - absl::uint128 assigned_value; - assigned_value = value; - EXPECT_EQ(value, absl::int128(assigned_value)); - } - - absl::int128 negative_values[] = { - -1, -0x1234567890abcdef, - absl::MakeInt128(-0x5544332211ffeedd, 0), - -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)}; - for (absl::int128 value : negative_values) { - EXPECT_EQ(absl::uint128(-value), -absl::uint128(value)); - - absl::uint128 assigned_value; - assigned_value = value; - EXPECT_EQ(absl::uint128(-value), -assigned_value); - } -} - -template <typename T> -class Int128IntegerTraitsTest : public ::testing::Test {}; - -TYPED_TEST_SUITE(Int128IntegerTraitsTest, IntegerTypes); - -TYPED_TEST(Int128IntegerTraitsTest, ConstructAssignTest) { - static_assert(std::is_constructible<absl::int128, TypeParam>::value, - "absl::int128 must be constructible from TypeParam"); - static_assert(std::is_assignable<absl::int128&, TypeParam>::value, - "absl::int128 must be assignable from TypeParam"); - static_assert(!std::is_assignable<TypeParam&, absl::int128>::value, - "TypeParam must not be assignable from absl::int128"); -} - -template <typename T> -class Int128FloatTraitsTest : public ::testing::Test {}; - -TYPED_TEST_SUITE(Int128FloatTraitsTest, FloatingPointTypes); - -TYPED_TEST(Int128FloatTraitsTest, ConstructAssignTest) { - static_assert(std::is_constructible<absl::int128, TypeParam>::value, - "absl::int128 must be constructible from TypeParam"); - static_assert(!std::is_assignable<absl::int128&, TypeParam>::value, - "absl::int128 must not be assignable from TypeParam"); - static_assert(!std::is_assignable<TypeParam&, absl::int128>::value, - "TypeParam must not be assignable from absl::int128"); -} - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -// These type traits done separately as TYPED_TEST requires typeinfo, and not -// all platforms have this for __int128 even though they define the type. -TEST(Int128, IntrinsicTypeTraitsTest) { - static_assert(std::is_constructible<absl::int128, __int128>::value, - "absl::int128 must be constructible from __int128"); - static_assert(std::is_assignable<absl::int128&, __int128>::value, - "absl::int128 must be assignable from __int128"); - static_assert(!std::is_assignable<__int128&, absl::int128>::value, - "__int128 must not be assignable from absl::int128"); - - static_assert(std::is_constructible<absl::int128, unsigned __int128>::value, - "absl::int128 must be constructible from unsigned __int128"); - static_assert(!std::is_assignable<absl::int128&, unsigned __int128>::value, - "absl::int128 must be assignable from unsigned __int128"); - static_assert(!std::is_assignable<unsigned __int128&, absl::int128>::value, - "unsigned __int128 must not be assignable from absl::int128"); -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -TEST(Int128, TrivialTraitsTest) { - static_assert(absl::is_trivially_default_constructible<absl::int128>::value, - ""); - static_assert(absl::is_trivially_copy_constructible<absl::int128>::value, ""); - static_assert(absl::is_trivially_copy_assignable<absl::int128>::value, ""); - static_assert(std::is_trivially_destructible<absl::int128>::value, ""); -} - -TEST(Int128, BoolConversionTest) { - EXPECT_FALSE(absl::int128(0)); - for (int i = 0; i < 64; ++i) { - EXPECT_TRUE(absl::MakeInt128(0, uint64_t{1} << i)); - } - for (int i = 0; i < 63; ++i) { - EXPECT_TRUE(absl::MakeInt128(int64_t{1} << i, 0)); - } - EXPECT_TRUE(absl::Int128Min()); - - EXPECT_EQ(absl::int128(1), absl::int128(true)); - EXPECT_EQ(absl::int128(0), absl::int128(false)); -} - -template <typename T> -class Int128IntegerConversionTest : public ::testing::Test {}; - -TYPED_TEST_SUITE(Int128IntegerConversionTest, IntegerTypes); - -TYPED_TEST(Int128IntegerConversionTest, RoundTripTest) { - EXPECT_EQ(TypeParam{0}, static_cast<TypeParam>(absl::int128(0))); - EXPECT_EQ(std::numeric_limits<TypeParam>::min(), - static_cast<TypeParam>( - absl::int128(std::numeric_limits<TypeParam>::min()))); - EXPECT_EQ(std::numeric_limits<TypeParam>::max(), - static_cast<TypeParam>( - absl::int128(std::numeric_limits<TypeParam>::max()))); -} - -template <typename T> -class Int128FloatConversionTest : public ::testing::Test {}; - -TYPED_TEST_SUITE(Int128FloatConversionTest, FloatingPointTypes); - -TYPED_TEST(Int128FloatConversionTest, ConstructAndCastTest) { - // Conversions where the floating point values should be exactly the same. - // 0x9f5b is a randomly chosen small value. - for (int i = 0; i < 110; ++i) { // 110 = 126 - #bits in 0x9f5b - SCOPED_TRACE(::testing::Message() << "i = " << i); - - TypeParam float_value = std::ldexp(static_cast<TypeParam>(0x9f5b), i); - absl::int128 int_value = absl::int128(0x9f5b) << i; - - EXPECT_EQ(float_value, static_cast<TypeParam>(int_value)); - EXPECT_EQ(-float_value, static_cast<TypeParam>(-int_value)); - EXPECT_EQ(int_value, absl::int128(float_value)); - EXPECT_EQ(-int_value, absl::int128(-float_value)); - } - - // Round trip conversions with a small sample of randomly generated uint64_t - // values (less than int64_t max so that value * 2^64 fits into int128). - uint64_t values[] = {0x6d4492c24fb86199, 0x26ead65e4cb359b5, - 0x2c43407433ba3fd1, 0x3b574ec668df6b55, - 0x1c750e55a29f4f0f}; - for (uint64_t value : values) { - for (int i = 0; i <= 64; ++i) { - SCOPED_TRACE(::testing::Message() - << "value = " << value << "; i = " << i); - - TypeParam fvalue = std::ldexp(static_cast<TypeParam>(value), i); - EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(absl::int128(fvalue))); - EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(-absl::int128(fvalue))); - EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(absl::int128(-fvalue))); - EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(-absl::int128(-fvalue))); - } - } - - // Round trip conversions with a small sample of random large positive values. - absl::int128 large_values[] = { - absl::MakeInt128(0x5b0640d96c7b3d9f, 0xb7a7189e51d18622), - absl::MakeInt128(0x34bed042c6f65270, 0x73b236570669a089), - absl::MakeInt128(0x43deba9e6da12724, 0xf7f0f83da686797d), - absl::MakeInt128(0x71e8d383be4e5589, 0x75c3f96fb00752b6)}; - for (absl::int128 value : large_values) { - // Make value have as many significant bits as can be represented by - // the mantissa, also making sure the highest and lowest bit in the range - // are set. - value >>= (127 - std::numeric_limits<TypeParam>::digits); - value |= absl::int128(1) << (std::numeric_limits<TypeParam>::digits - 1); - value |= 1; - for (int i = 0; i < 127 - std::numeric_limits<TypeParam>::digits; ++i) { - absl::int128 int_value = value << i; - EXPECT_EQ(int_value, - static_cast<absl::int128>(static_cast<TypeParam>(int_value))); - EXPECT_EQ(-int_value, - static_cast<absl::int128>(static_cast<TypeParam>(-int_value))); - } - } - - // Small sample of checks that rounding is toward zero - EXPECT_EQ(0, absl::int128(TypeParam(0.1))); - EXPECT_EQ(17, absl::int128(TypeParam(17.8))); - EXPECT_EQ(0, absl::int128(TypeParam(-0.8))); - EXPECT_EQ(-53, absl::int128(TypeParam(-53.1))); - EXPECT_EQ(0, absl::int128(TypeParam(0.5))); - EXPECT_EQ(0, absl::int128(TypeParam(-0.5))); - TypeParam just_lt_one = std::nexttoward(TypeParam(1), TypeParam(0)); - EXPECT_EQ(0, absl::int128(just_lt_one)); - TypeParam just_gt_minus_one = std::nexttoward(TypeParam(-1), TypeParam(0)); - EXPECT_EQ(0, absl::int128(just_gt_minus_one)); - - // Check limits - EXPECT_DOUBLE_EQ(std::ldexp(static_cast<TypeParam>(1), 127), - static_cast<TypeParam>(absl::Int128Max())); - EXPECT_DOUBLE_EQ(-std::ldexp(static_cast<TypeParam>(1), 127), - static_cast<TypeParam>(absl::Int128Min())); -} - -TEST(Int128, FactoryTest) { - EXPECT_EQ(absl::int128(-1), absl::MakeInt128(-1, -1)); - EXPECT_EQ(absl::int128(-31), absl::MakeInt128(-1, -31)); - EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::min()), - absl::MakeInt128(-1, std::numeric_limits<int64_t>::min())); - EXPECT_EQ(absl::int128(0), absl::MakeInt128(0, 0)); - EXPECT_EQ(absl::int128(1), absl::MakeInt128(0, 1)); - EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::max()), - absl::MakeInt128(0, std::numeric_limits<int64_t>::max())); -} - -TEST(Int128, HighLowTest) { - struct HighLowPair { - int64_t high; - uint64_t low; - }; - HighLowPair values[]{{0, 0}, {0, 1}, {1, 0}, {123, 456}, {-654, 321}}; - for (const HighLowPair& pair : values) { - absl::int128 value = absl::MakeInt128(pair.high, pair.low); - EXPECT_EQ(pair.low, absl::Int128Low64(value)); - EXPECT_EQ(pair.high, absl::Int128High64(value)); - } -} - -TEST(Int128, LimitsTest) { - EXPECT_EQ(absl::MakeInt128(0x7fffffffffffffff, 0xffffffffffffffff), - absl::Int128Max()); - EXPECT_EQ(absl::Int128Max(), ~absl::Int128Min()); -} - -#if defined(ABSL_HAVE_INTRINSIC_INT128) -TEST(Int128, IntrinsicConversionTest) { - __int128 intrinsic = - (static_cast<__int128>(0x3a5b76c209de76f6) << 64) + 0x1f25e1d63a2b46c5; - absl::int128 custom = - absl::MakeInt128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5); - - EXPECT_EQ(custom, absl::int128(intrinsic)); - EXPECT_EQ(intrinsic, static_cast<__int128>(custom)); -} -#endif // ABSL_HAVE_INTRINSIC_INT128 - -TEST(Int128, ConstexprTest) { - constexpr absl::int128 zero = absl::int128(); - constexpr absl::int128 one = 1; - constexpr absl::int128 minus_two = -2; - constexpr absl::int128 min = absl::Int128Min(); - constexpr absl::int128 max = absl::Int128Max(); - EXPECT_EQ(zero, absl::int128(0)); - EXPECT_EQ(one, absl::int128(1)); - EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2)); - EXPECT_GT(max, one); - EXPECT_LT(min, minus_two); -} - -TEST(Int128, ComparisonTest) { - struct TestCase { - absl::int128 smaller; - absl::int128 larger; - }; - TestCase cases[] = { - {absl::int128(0), absl::int128(123)}, - {absl::MakeInt128(-12, 34), absl::MakeInt128(12, 34)}, - {absl::MakeInt128(1, 1000), absl::MakeInt128(1000, 1)}, - {absl::MakeInt128(-1000, 1000), absl::MakeInt128(-1, 1)}, - }; - for (const TestCase& pair : cases) { - SCOPED_TRACE(::testing::Message() << "pair.smaller = " << pair.smaller - << "; pair.larger = " << pair.larger); - - EXPECT_TRUE(pair.smaller == pair.smaller); // NOLINT(readability/check) - EXPECT_TRUE(pair.larger == pair.larger); // NOLINT(readability/check) - EXPECT_FALSE(pair.smaller == pair.larger); // NOLINT(readability/check) - - EXPECT_TRUE(pair.smaller != pair.larger); // NOLINT(readability/check) - EXPECT_FALSE(pair.smaller != pair.smaller); // NOLINT(readability/check) - EXPECT_FALSE(pair.larger != pair.larger); // NOLINT(readability/check) - - EXPECT_TRUE(pair.smaller < pair.larger); // NOLINT(readability/check) - EXPECT_FALSE(pair.larger < pair.smaller); // NOLINT(readability/check) - - EXPECT_TRUE(pair.larger > pair.smaller); // NOLINT(readability/check) - EXPECT_FALSE(pair.smaller > pair.larger); // NOLINT(readability/check) - - EXPECT_TRUE(pair.smaller <= pair.larger); // NOLINT(readability/check) - EXPECT_FALSE(pair.larger <= pair.smaller); // NOLINT(readability/check) - EXPECT_TRUE(pair.smaller <= pair.smaller); // NOLINT(readability/check) - EXPECT_TRUE(pair.larger <= pair.larger); // NOLINT(readability/check) - - EXPECT_TRUE(pair.larger >= pair.smaller); // NOLINT(readability/check) - EXPECT_FALSE(pair.smaller >= pair.larger); // NOLINT(readability/check) - EXPECT_TRUE(pair.smaller >= pair.smaller); // NOLINT(readability/check) - EXPECT_TRUE(pair.larger >= pair.larger); // NOLINT(readability/check) - } -} - -TEST(Int128, UnaryNegationTest) { - int64_t values64[] = {0, 1, 12345, 0x4000000000000000, - std::numeric_limits<int64_t>::max()}; - for (int64_t value : values64) { - SCOPED_TRACE(::testing::Message() << "value = " << value); - - EXPECT_EQ(absl::int128(-value), -absl::int128(value)); - EXPECT_EQ(absl::int128(value), -absl::int128(-value)); - EXPECT_EQ(absl::MakeInt128(-value, 0), -absl::MakeInt128(value, 0)); - EXPECT_EQ(absl::MakeInt128(value, 0), -absl::MakeInt128(-value, 0)); - } -} - -TEST(Int128, LogicalNotTest) { - EXPECT_TRUE(!absl::int128(0)); - for (int i = 0; i < 64; ++i) { - EXPECT_FALSE(!absl::MakeInt128(0, uint64_t{1} << i)); - } - for (int i = 0; i < 63; ++i) { - EXPECT_FALSE(!absl::MakeInt128(int64_t{1} << i, 0)); - } -} - -TEST(Int128, AdditionSubtractionTest) { - // 64 bit pairs that will not cause overflow / underflow. These test negative - // carry; positive carry must be checked separately. - std::pair<int64_t, int64_t> cases[]{ - {0, 0}, // 0, 0 - {0, 2945781290834}, // 0, + - {1908357619234, 0}, // +, 0 - {0, -1204895918245}, // 0, - - {-2957928523560, 0}, // -, 0 - {89023982312461, 98346012567134}, // +, + - {-63454234568239, -23456235230773}, // -, - - {98263457263502, -21428561935925}, // +, - - {-88235237438467, 15923659234573}, // -, + - }; - for (const auto& pair : cases) { - SCOPED_TRACE(::testing::Message() - << "pair = {" << pair.first << ", " << pair.second << '}'); - - EXPECT_EQ(absl::int128(pair.first + pair.second), - absl::int128(pair.first) + absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.second + pair.first), - absl::int128(pair.second) += absl::int128(pair.first)); - - EXPECT_EQ(absl::int128(pair.first - pair.second), - absl::int128(pair.first) - absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.second - pair.first), - absl::int128(pair.second) -= absl::int128(pair.first)); - - EXPECT_EQ( - absl::MakeInt128(pair.second + pair.first, 0), - absl::MakeInt128(pair.second, 0) + absl::MakeInt128(pair.first, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first + pair.second, 0), - absl::MakeInt128(pair.first, 0) += absl::MakeInt128(pair.second, 0)); - - EXPECT_EQ( - absl::MakeInt128(pair.second - pair.first, 0), - absl::MakeInt128(pair.second, 0) - absl::MakeInt128(pair.first, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first - pair.second, 0), - absl::MakeInt128(pair.first, 0) -= absl::MakeInt128(pair.second, 0)); - } - - // check positive carry - EXPECT_EQ(absl::MakeInt128(31, 0), - absl::MakeInt128(20, 1) + - absl::MakeInt128(10, std::numeric_limits<uint64_t>::max())); -} - -TEST(Int128, IncrementDecrementTest) { - absl::int128 value = 0; - EXPECT_EQ(0, value++); - EXPECT_EQ(1, value); - EXPECT_EQ(1, value--); - EXPECT_EQ(0, value); - EXPECT_EQ(-1, --value); - EXPECT_EQ(-1, value); - EXPECT_EQ(0, ++value); - EXPECT_EQ(0, value); -} - -TEST(Int128, MultiplicationTest) { - // 1 bit x 1 bit, and negative combinations - for (int i = 0; i < 64; ++i) { - for (int j = 0; j < 127 - i; ++j) { - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - absl::int128 a = absl::int128(1) << i; - absl::int128 b = absl::int128(1) << j; - absl::int128 c = absl::int128(1) << (i + j); - - EXPECT_EQ(c, a * b); - EXPECT_EQ(-c, -a * b); - EXPECT_EQ(-c, a * -b); - EXPECT_EQ(c, -a * -b); - - EXPECT_EQ(c, absl::int128(a) *= b); - EXPECT_EQ(-c, absl::int128(-a) *= b); - EXPECT_EQ(-c, absl::int128(a) *= -b); - EXPECT_EQ(c, absl::int128(-a) *= -b); - } - } - - // Pairs of random values that will not overflow signed 64-bit multiplication - std::pair<int64_t, int64_t> small_values[] = { - {0x5e61, 0xf29f79ca14b4}, // +, + - {0x3e033b, -0x612c0ee549}, // +, - - {-0x052ce7e8, 0x7c728f0f}, // -, + - {-0x3af7054626, -0xfb1e1d}, // -, - - }; - for (const std::pair<int64_t, int64_t>& pair : small_values) { - SCOPED_TRACE(::testing::Message() - << "pair = {" << pair.first << ", " << pair.second << '}'); - - EXPECT_EQ(absl::int128(pair.first * pair.second), - absl::int128(pair.first) * absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.first * pair.second), - absl::int128(pair.first) *= absl::int128(pair.second)); - - EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0), - absl::MakeInt128(pair.first, 0) * absl::int128(pair.second)); - EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0), - absl::MakeInt128(pair.first, 0) *= absl::int128(pair.second)); - } - - // Pairs of positive random values that will not overflow 64-bit - // multiplication and can be left shifted by 32 without overflow - std::pair<int64_t, int64_t> small_values2[] = { - {0x1bb0a110, 0x31487671}, - {0x4792784e, 0x28add7d7}, - {0x7b66553a, 0x11dff8ef}, - }; - for (const std::pair<int64_t, int64_t>& pair : small_values2) { - SCOPED_TRACE(::testing::Message() - << "pair = {" << pair.first << ", " << pair.second << '}'); - - absl::int128 a = absl::int128(pair.first << 32); - absl::int128 b = absl::int128(pair.second << 32); - absl::int128 c = absl::MakeInt128(pair.first * pair.second, 0); - - EXPECT_EQ(c, a * b); - EXPECT_EQ(-c, -a * b); - EXPECT_EQ(-c, a * -b); - EXPECT_EQ(c, -a * -b); - - EXPECT_EQ(c, absl::int128(a) *= b); - EXPECT_EQ(-c, absl::int128(-a) *= b); - EXPECT_EQ(-c, absl::int128(a) *= -b); - EXPECT_EQ(c, absl::int128(-a) *= -b); - } - - // check 0, 1, and -1 behavior with large values - absl::int128 large_values[] = { - {absl::MakeInt128(0xd66f061af02d0408, 0x727d2846cb475b53)}, - {absl::MakeInt128(0x27b8d5ed6104452d, 0x03f8a33b0ee1df4f)}, - {-absl::MakeInt128(0x621b6626b9e8d042, 0x27311ac99df00938)}, - {-absl::MakeInt128(0x34e0656f1e95fb60, 0x4281cfd731257a47)}, - }; - for (absl::int128 value : large_values) { - EXPECT_EQ(0, 0 * value); - EXPECT_EQ(0, value * 0); - EXPECT_EQ(0, absl::int128(0) *= value); - EXPECT_EQ(0, value *= 0); - - EXPECT_EQ(value, 1 * value); - EXPECT_EQ(value, value * 1); - EXPECT_EQ(value, absl::int128(1) *= value); - EXPECT_EQ(value, value *= 1); - - EXPECT_EQ(-value, -1 * value); - EXPECT_EQ(-value, value * -1); - EXPECT_EQ(-value, absl::int128(-1) *= value); - EXPECT_EQ(-value, value *= -1); - } - - // Manually calculated random large value cases - EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1), - absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) * 0x1a6037537b); - EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e), - -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) * 0xe5a434cd14866e); - EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4), - 0xa9b98a8ddf66bc * -absl::MakeInt128(0x81, 0x672e58231e2469d7)); - EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4), - -0x3e39341147 * -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c)); - - EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1), - absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) *= 0x1a6037537b); - EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e), - -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) *= 0xe5a434cd14866e); - EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4), - absl::int128(0xa9b98a8ddf66bc) *= - -absl::MakeInt128(0x81, 0x672e58231e2469d7)); - EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4), - absl::int128(-0x3e39341147) *= - -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c)); -} - -TEST(Int128, DivisionAndModuloTest) { - // Check against 64 bit division and modulo operators with a sample of - // randomly generated pairs. - std::pair<int64_t, int64_t> small_pairs[] = { - {0x15f2a64138, 0x67da05}, {0x5e56d194af43045f, 0xcf1543fb99}, - {0x15e61ed052036a, -0xc8e6}, {0x88125a341e85, -0xd23fb77683}, - {-0xc06e20, 0x5a}, {-0x4f100219aea3e85d, 0xdcc56cb4efe993}, - {-0x168d629105, -0xa7}, {-0x7b44e92f03ab2375, -0x6516}, - }; - for (const std::pair<int64_t, int64_t>& pair : small_pairs) { - SCOPED_TRACE(::testing::Message() - << "pair = {" << pair.first << ", " << pair.second << '}'); - - absl::int128 dividend = pair.first; - absl::int128 divisor = pair.second; - int64_t quotient = pair.first / pair.second; - int64_t remainder = pair.first % pair.second; - - EXPECT_EQ(quotient, dividend / divisor); - EXPECT_EQ(quotient, absl::int128(dividend) /= divisor); - EXPECT_EQ(remainder, dividend % divisor); - EXPECT_EQ(remainder, absl::int128(dividend) %= divisor); - } - - // Test behavior with 0, 1, and -1 with a sample of randomly generated large - // values. - absl::int128 values[] = { - absl::MakeInt128(0x63d26ee688a962b2, 0x9e1411abda5c1d70), - absl::MakeInt128(0x152f385159d6f986, 0xbf8d48ef63da395d), - -absl::MakeInt128(0x3098d7567030038c, 0x14e7a8a098dc2164), - -absl::MakeInt128(0x49a037aca35c809f, 0xa6a87525480ef330), - }; - for (absl::int128 value : values) { - SCOPED_TRACE(::testing::Message() << "value = " << value); - - EXPECT_EQ(0, 0 / value); - EXPECT_EQ(0, absl::int128(0) /= value); - EXPECT_EQ(0, 0 % value); - EXPECT_EQ(0, absl::int128(0) %= value); - - EXPECT_EQ(value, value / 1); - EXPECT_EQ(value, absl::int128(value) /= 1); - EXPECT_EQ(0, value % 1); - EXPECT_EQ(0, absl::int128(value) %= 1); - - EXPECT_EQ(-value, value / -1); - EXPECT_EQ(-value, absl::int128(value) /= -1); - EXPECT_EQ(0, value % -1); - EXPECT_EQ(0, absl::int128(value) %= -1); - } - - // Min and max values - EXPECT_EQ(0, absl::Int128Max() / absl::Int128Min()); - EXPECT_EQ(absl::Int128Max(), absl::Int128Max() % absl::Int128Min()); - EXPECT_EQ(-1, absl::Int128Min() / absl::Int128Max()); - EXPECT_EQ(-1, absl::Int128Min() % absl::Int128Max()); - - // Power of two division and modulo of random large dividends - absl::int128 positive_values[] = { - absl::MakeInt128(0x21e1a1cc69574620, 0xe7ac447fab2fc869), - absl::MakeInt128(0x32c2ff3ab89e66e8, 0x03379a613fd1ce74), - absl::MakeInt128(0x6f32ca786184dcaf, 0x046f9c9ecb3a9ce1), - absl::MakeInt128(0x1aeb469dd990e0ee, 0xda2740f243cd37eb), - }; - for (absl::int128 value : positive_values) { - for (int i = 0; i < 127; ++i) { - SCOPED_TRACE(::testing::Message() - << "value = " << value << "; i = " << i); - absl::int128 power_of_two = absl::int128(1) << i; - - EXPECT_EQ(value >> i, value / power_of_two); - EXPECT_EQ(value >> i, absl::int128(value) /= power_of_two); - EXPECT_EQ(value & (power_of_two - 1), value % power_of_two); - EXPECT_EQ(value & (power_of_two - 1), - absl::int128(value) %= power_of_two); - } - } - - // Manually calculated cases with random large dividends - struct DivisionModCase { - absl::int128 dividend; - absl::int128 divisor; - absl::int128 quotient; - absl::int128 remainder; - }; - DivisionModCase manual_cases[] = { - {absl::MakeInt128(0x6ada48d489007966, 0x3c9c5c98150d5d69), - absl::MakeInt128(0x8bc308fb, 0x8cb9cc9a3b803344), 0xc3b87e08, - absl::MakeInt128(0x1b7db5e1, 0xd9eca34b7af04b49)}, - {absl::MakeInt128(0xd6946511b5b, 0x4886c5c96546bf5f), - -absl::MakeInt128(0x263b, 0xfd516279efcfe2dc), -0x59cbabf0, - absl::MakeInt128(0x622, 0xf462909155651d1f)}, - {-absl::MakeInt128(0x33db734f9e8d1399, 0x8447ac92482bca4d), 0x37495078240, - -absl::MakeInt128(0xf01f1, 0xbc0368bf9a77eae8), -0x21a508f404d}, - {-absl::MakeInt128(0x13f837b409a07e7d, 0x7fc8e248a7d73560), -0x1b9f, - absl::MakeInt128(0xb9157556d724, 0xb14f635714d7563e), -0x1ade}, - }; - for (const DivisionModCase test_case : manual_cases) { - EXPECT_EQ(test_case.quotient, test_case.dividend / test_case.divisor); - EXPECT_EQ(test_case.quotient, - absl::int128(test_case.dividend) /= test_case.divisor); - EXPECT_EQ(test_case.remainder, test_case.dividend % test_case.divisor); - EXPECT_EQ(test_case.remainder, - absl::int128(test_case.dividend) %= test_case.divisor); - } -} - -TEST(Int128, BitwiseLogicTest) { - EXPECT_EQ(absl::int128(-1), ~absl::int128(0)); - - absl::int128 values[]{ - 0, -1, 0xde400bee05c3ff6b, absl::MakeInt128(0x7f32178dd81d634a, 0), - absl::MakeInt128(0xaf539057055613a9, 0x7d104d7d946c2e4d)}; - for (absl::int128 value : values) { - EXPECT_EQ(value, ~~value); - - EXPECT_EQ(value, value | value); - EXPECT_EQ(value, value & value); - EXPECT_EQ(0, value ^ value); - - EXPECT_EQ(value, absl::int128(value) |= value); - EXPECT_EQ(value, absl::int128(value) &= value); - EXPECT_EQ(0, absl::int128(value) ^= value); - - EXPECT_EQ(value, value | 0); - EXPECT_EQ(0, value & 0); - EXPECT_EQ(value, value ^ 0); - - EXPECT_EQ(absl::int128(-1), value | absl::int128(-1)); - EXPECT_EQ(value, value & absl::int128(-1)); - EXPECT_EQ(~value, value ^ absl::int128(-1)); - } - - // small sample of randomly generated int64_t's - std::pair<int64_t, int64_t> pairs64[]{ - {0x7f86797f5e991af4, 0x1ee30494fb007c97}, - {0x0b278282bacf01af, 0x58780e0a57a49e86}, - {0x059f266ccb93a666, 0x3d5b731bae9286f5}, - {0x63c0c4820f12108c, 0x58166713c12e1c3a}, - {0x381488bb2ed2a66e, 0x2220a3eb76a3698c}, - {0x2a0a0dfb81e06f21, 0x4b60585927f5523c}, - {0x555b1c3a03698537, 0x25478cd19d8e53cb}, - {0x4750f6f27d779225, 0x16397553c6ff05fc}, - }; - for (const std::pair<int64_t, int64_t>& pair : pairs64) { - SCOPED_TRACE(::testing::Message() - << "pair = {" << pair.first << ", " << pair.second << '}'); - - EXPECT_EQ(absl::MakeInt128(~pair.first, ~pair.second), - ~absl::MakeInt128(pair.first, pair.second)); - - EXPECT_EQ(absl::int128(pair.first & pair.second), - absl::int128(pair.first) & absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.first | pair.second), - absl::int128(pair.first) | absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.first ^ pair.second), - absl::int128(pair.first) ^ absl::int128(pair.second)); - - EXPECT_EQ(absl::int128(pair.first & pair.second), - absl::int128(pair.first) &= absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.first | pair.second), - absl::int128(pair.first) |= absl::int128(pair.second)); - EXPECT_EQ(absl::int128(pair.first ^ pair.second), - absl::int128(pair.first) ^= absl::int128(pair.second)); - - EXPECT_EQ( - absl::MakeInt128(pair.first & pair.second, 0), - absl::MakeInt128(pair.first, 0) & absl::MakeInt128(pair.second, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first | pair.second, 0), - absl::MakeInt128(pair.first, 0) | absl::MakeInt128(pair.second, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first ^ pair.second, 0), - absl::MakeInt128(pair.first, 0) ^ absl::MakeInt128(pair.second, 0)); - - EXPECT_EQ( - absl::MakeInt128(pair.first & pair.second, 0), - absl::MakeInt128(pair.first, 0) &= absl::MakeInt128(pair.second, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first | pair.second, 0), - absl::MakeInt128(pair.first, 0) |= absl::MakeInt128(pair.second, 0)); - EXPECT_EQ( - absl::MakeInt128(pair.first ^ pair.second, 0), - absl::MakeInt128(pair.first, 0) ^= absl::MakeInt128(pair.second, 0)); - } -} - -TEST(Int128, BitwiseShiftTest) { - for (int i = 0; i < 64; ++i) { - for (int j = 0; j <= i; ++j) { - // Left shift from j-th bit to i-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) << (i - j)); - EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) <<= (i - j)); - } - } - for (int i = 0; i < 63; ++i) { - for (int j = 0; j < 64; ++j) { - // Left shift from j-th bit to (i + 64)-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::int128(uint64_t{1} << j) << (i + 64 - j)); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::int128(uint64_t{1} << j) <<= (i + 64 - j)); - } - for (int j = 0; j <= i; ++j) { - // Left shift from (j + 64)-th bit to (i + 64)-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::MakeInt128(uint64_t{1} << j, 0) << (i - j)); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::MakeInt128(uint64_t{1} << j, 0) <<= (i - j)); - } - } - - for (int i = 0; i < 64; ++i) { - for (int j = i; j < 64; ++j) { - // Right shift from j-th bit to i-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >> (j - i)); - EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >>= (j - i)); - } - for (int j = 0; j < 63; ++j) { - // Right shift from (j + 64)-th bit to i-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(uint64_t{1} << i, - absl::MakeInt128(uint64_t{1} << j, 0) >> (j + 64 - i)); - EXPECT_EQ(uint64_t{1} << i, - absl::MakeInt128(uint64_t{1} << j, 0) >>= (j + 64 - i)); - } - } - for (int i = 0; i < 63; ++i) { - for (int j = i; j < 63; ++j) { - // Right shift from (j + 64)-th bit to (i + 64)-th bit. - SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::MakeInt128(uint64_t{1} << j, 0) >> (j - i)); - EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), - absl::MakeInt128(uint64_t{1} << j, 0) >>= (j - i)); - } - } -} - -TEST(Int128, NumericLimitsTest) { - static_assert(std::numeric_limits<absl::int128>::is_specialized, ""); - static_assert(std::numeric_limits<absl::int128>::is_signed, ""); - static_assert(std::numeric_limits<absl::int128>::is_integer, ""); - EXPECT_EQ(static_cast<int>(127 * std::log10(2)), - std::numeric_limits<absl::int128>::digits10); - EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::min()); - EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::lowest()); - EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max()); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/BUILD.bazel b/third_party/abseil_cpp/absl/random/BUILD.bazel deleted file mode 100644 index 81e150e62e78..000000000000 --- a/third_party/abseil_cpp/absl/random/BUILD.bazel +++ /dev/null @@ -1,509 +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. -# - -# ABSL random-number generation libraries. - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "random", - hdrs = ["random.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":seed_sequences", - "//absl/random/internal:nonsecure_base", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:pool_urbg", - "//absl/random/internal:randen_engine", - ], -) - -cc_library( - name = "distributions", - srcs = [ - "discrete_distribution.cc", - "gaussian_distribution.cc", - ], - hdrs = [ - "bernoulli_distribution.h", - "beta_distribution.h", - "discrete_distribution.h", - "distributions.h", - "exponential_distribution.h", - "gaussian_distribution.h", - "log_uniform_int_distribution.h", - "poisson_distribution.h", - "uniform_int_distribution.h", - "uniform_real_distribution.h", - "zipf_distribution.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/random/internal:distribution_caller", - "//absl/random/internal:fast_uniform_bits", - "//absl/random/internal:fastmath", - "//absl/random/internal:generate_real", - "//absl/random/internal:iostream_state_saver", - "//absl/random/internal:traits", - "//absl/random/internal:uniform_helper", - "//absl/random/internal:wide_multiply", - "//absl/strings", - ], -) - -cc_library( - name = "seed_gen_exception", - srcs = ["seed_gen_exception.cc"], - hdrs = ["seed_gen_exception.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], -) - -cc_library( - name = "seed_sequences", - srcs = ["seed_sequences.cc"], - hdrs = [ - "seed_sequences.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":seed_gen_exception", - "//absl/container:inlined_vector", - "//absl/random/internal:nonsecure_base", - "//absl/random/internal:pool_urbg", - "//absl/random/internal:salted_seed_seq", - "//absl/random/internal:seed_material", - "//absl/types:span", - ], -) - -cc_library( - name = "bit_gen_ref", - hdrs = ["bit_gen_ref.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":random", - "//absl/base:core_headers", - "//absl/base:fast_type_id", - "//absl/meta:type_traits", - "//absl/random/internal:distribution_caller", - "//absl/random/internal:fast_uniform_bits", - ], -) - -cc_library( - name = "mock_distributions", - testonly = 1, - hdrs = ["mock_distributions.h"], - deps = [ - ":distributions", - ":mocking_bit_gen", - "//absl/meta:type_traits", - "//absl/random/internal:mock_overload_set", - "@com_google_googletest//:gtest", - ], -) - -cc_library( - name = "mocking_bit_gen", - testonly = 1, - hdrs = [ - "mocking_bit_gen.h", - ], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:fast_type_id", - "//absl/container:flat_hash_map", - "//absl/meta:type_traits", - "//absl/random/internal:distribution_caller", - "//absl/strings", - "//absl/types:span", - "//absl/types:variant", - "//absl/utility", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "bernoulli_distribution_test", - size = "small", - timeout = "eternal", # Android can take a very long time - srcs = ["bernoulli_distribution_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "beta_distribution_test", - size = "small", - timeout = "eternal", # Android can take a very long time - srcs = ["beta_distribution_test.cc"], - copts = ABSL_TEST_COPTS, - flaky = 1, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "//absl/strings:str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "distributions_test", - size = "small", - timeout = "moderate", - srcs = [ - "distributions_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/random/internal:distribution_test_util", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "generators_test", - size = "small", - srcs = ["generators_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "log_uniform_int_distribution_test", - size = "medium", - srcs = [ - "log_uniform_int_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "//absl/strings:str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "discrete_distribution_test", - size = "medium", - srcs = [ - "discrete_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "poisson_distribution_test", - size = "small", - timeout = "eternal", # Android can take a very long time - srcs = [ - "poisson_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = [ - # Too Slow. - "no_test_android_arm", - "no_test_loonix", - ], - deps = [ - ":distributions", - ":random", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/container:flat_hash_map", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "//absl/strings:str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "exponential_distribution_test", - size = "small", - srcs = ["exponential_distribution_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "//absl/strings:str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "gaussian_distribution_test", - size = "small", - timeout = "eternal", # Android can take a very long time - srcs = [ - "gaussian_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "//absl/strings:str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "uniform_int_distribution_test", - size = "medium", - timeout = "long", - srcs = [ - "uniform_int_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "uniform_real_distribution_test", - size = "medium", - srcs = [ - "uniform_real_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = [ - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - ], - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "zipf_distribution_test", - size = "medium", - srcs = [ - "zipf_distribution_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distributions", - ":random", - "//absl/base:raw_logging_internal", - "//absl/random/internal:distribution_test_util", - "//absl/random/internal:pcg_engine", - "//absl/random/internal:sequence_urbg", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "bit_gen_ref_test", - size = "small", - srcs = ["bit_gen_ref_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bit_gen_ref", - ":random", - "//absl/base:fast_type_id", - "//absl/random/internal:sequence_urbg", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "mocking_bit_gen_test", - size = "small", - srcs = ["mocking_bit_gen_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bit_gen_ref", - ":mock_distributions", - ":mocking_bit_gen", - ":random", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "mock_distributions_test", - size = "small", - srcs = ["mock_distributions_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":mock_distributions", - ":mocking_bit_gen", - ":random", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "examples_test", - size = "small", - srcs = ["examples_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":random", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "seed_sequences_test", - size = "small", - srcs = ["seed_sequences_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":random", - ":seed_sequences", - "//absl/random/internal:nonsecure_base", - "@com_google_googletest//:gtest_main", - ], -) - -BENCHMARK_TAGS = [ - "benchmark", - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - "no_test_darwin_x86_64", - "no_test_ios_x86_64", - "no_test_loonix", - "no_test_msvc_x64", - "no_test_wasm", -] - -# Benchmarks for various methods / test utilities -cc_binary( - name = "benchmarks", - testonly = 1, - srcs = [ - "benchmarks.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = BENCHMARK_TAGS, - deps = [ - ":distributions", - ":random", - ":seed_sequences", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/random/internal:fast_uniform_bits", - "//absl/random/internal:randen_engine", - "@com_github_google_benchmark//:benchmark_main", - ], -) diff --git a/third_party/abseil_cpp/absl/random/CMakeLists.txt b/third_party/abseil_cpp/absl/random/CMakeLists.txt deleted file mode 100644 index 7d7bec83d994..000000000000 --- a/third_party/abseil_cpp/absl/random/CMakeLists.txt +++ /dev/null @@ -1,1207 +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. -# - -absl_cc_library( - NAME - random_random - HDRS - "random.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_distributions - absl::random_internal_nonsecure_base - absl::random_internal_pcg_engine - absl::random_internal_pool_urbg - absl::random_internal_randen_engine - absl::random_seed_sequences -) - -absl_cc_library( - NAME - random_bit_gen_ref - HDRS - "bit_gen_ref.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::core_headers - absl::random_internal_distribution_caller - absl::random_internal_fast_uniform_bits - absl::type_traits -) - -absl_cc_test( - NAME - random_bit_gen_ref_test - SRCS - "bit_gen_ref_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_bit_gen_ref - absl::random_random - absl::random_internal_sequence_urbg - absl::fast_type_id - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_mock_helpers - HDRS - "internal/mock_helpers.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::fast_type_id - absl::optional -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_mock_overload_set - HDRS - "internal/mock_overload_set.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_mocking_bit_gen - absl::random_internal_mock_helpers - TESTONLY -) - -absl_cc_library( - NAME - random_mocking_bit_gen - HDRS - "mock_distributions.h" - "mocking_bit_gen.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::flat_hash_map - absl::raw_logging_internal - absl::random_distributions - absl::random_internal_distribution_caller - absl::random_internal_mock_overload_set - absl::random_random - absl::strings - absl::span - absl::type_traits - absl::utility - absl::variant - gmock - gtest - TESTONLY -) - -absl_cc_test( - NAME - random_mock_distributions_test - SRCS - "mock_distributions_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_mocking_bit_gen - absl::random_random - gmock - gtest_main -) - -absl_cc_test( - NAME - random_mocking_bit_gen_test - SRCS - "mocking_bit_gen_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_bit_gen_ref - absl::random_mocking_bit_gen - absl::random_random - gmock - gtest_main -) - -absl_cc_library( - NAME - random_distributions - SRCS - "discrete_distribution.cc" - "gaussian_distribution.cc" - HDRS - "bernoulli_distribution.h" - "beta_distribution.h" - "discrete_distribution.h" - "distributions.h" - "exponential_distribution.h" - "gaussian_distribution.h" - "log_uniform_int_distribution.h" - "poisson_distribution.h" - "uniform_int_distribution.h" - "uniform_real_distribution.h" - "zipf_distribution.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::base_internal - absl::config - absl::core_headers - absl::random_internal_generate_real - absl::random_internal_distribution_caller - absl::random_internal_fast_uniform_bits - absl::random_internal_fastmath - absl::random_internal_iostream_state_saver - absl::random_internal_traits - absl::random_internal_uniform_helper - absl::random_internal_wide_multiply - absl::strings - absl::type_traits -) - -absl_cc_library( - NAME - random_seed_gen_exception - SRCS - "seed_gen_exception.cc" - HDRS - "seed_gen_exception.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config -) - -absl_cc_library( - NAME - random_seed_sequences - SRCS - "seed_sequences.cc" - HDRS - "seed_sequences.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::inlined_vector - absl::random_internal_nonsecure_base - absl::random_internal_pool_urbg - absl::random_internal_salted_seed_seq - absl::random_internal_seed_material - absl::random_seed_gen_exception - absl::span -) - -absl_cc_test( - NAME - random_bernoulli_distribution_test - SRCS - "bernoulli_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_distributions - absl::random_random - absl::random_internal_sequence_urbg - absl::random_internal_pcg_engine - gmock - gtest_main -) - -absl_cc_test( - NAME - random_beta_distribution_test - SRCS - "beta_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_distributions_test - SRCS - "distributions_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_distributions - absl::random_random - absl::random_internal_distribution_test_util - gmock - gtest_main -) - -absl_cc_test( - NAME - random_generators_test - SRCS - "generators_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - absl::random_distributions - absl::random_random - absl::raw_logging_internal - gmock - gtest_main -) - -absl_cc_test( - NAME - random_log_uniform_int_distribution_test - SRCS - "log_uniform_int_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_discrete_distribution_test - SRCS - "discrete_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_poisson_distribution_test - SRCS - "poisson_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_distributions - absl::random_random - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_exponential_distribution_test - SRCS - "exponential_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_gaussian_distribution_test - SRCS - "gaussian_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::core_headers - absl::random_distributions - absl::random_internal_distribution_test_util - absl::random_internal_sequence_urbg - absl::random_random - absl::raw_logging_internal - absl::strings - absl::str_format - gmock - gtest_main -) - -absl_cc_test( - NAME - random_uniform_int_distribution_test - SRCS - "uniform_int_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_uniform_real_distribution_test - SRCS - "uniform_real_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_distributions - absl::random_internal_distribution_test_util - absl::random_internal_pcg_engine - absl::random_internal_sequence_urbg - absl::random_random - absl::strings - gmock - gtest_main -) - -absl_cc_test( - NAME - random_zipf_distribution_test - SRCS - "zipf_distribution_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - 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 - gmock - gtest_main -) - -absl_cc_test( - NAME - random_examples_test - SRCS - "examples_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_random - gtest_main -) - -absl_cc_test( - NAME - random_seed_sequences_test - SRCS - "seed_sequences_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_seed_sequences - absl::random_internal_nonsecure_base - absl::random_random - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_traits - HDRS - "internal/traits.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_distribution_caller - HDRS - "internal/distribution_caller.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${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_fast_uniform_bits - HDRS - "internal/fast_uniform_bits.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_seed_material - SRCS - "internal/seed_material.cc" - HDRS - "internal/seed_material.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - $<$<BOOL:${MINGW}>:"bcrypt"> - DEPS - absl::core_headers - absl::optional - absl::random_internal_fast_uniform_bits - absl::raw_logging_internal - absl::span - absl::strings -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_pool_urbg - SRCS - "internal/pool_urbg.cc" - HDRS - "internal/pool_urbg.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::base - absl::config - absl::core_headers - absl::endian - absl::random_internal_randen - absl::random_internal_seed_material - absl::random_internal_traits - absl::random_seed_gen_exception - absl::raw_logging_internal - absl::span -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_explicit_seed_seq - HDRS - "internal/random_internal_explicit_seed_seq.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - TESTONLY -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_sequence_urbg - HDRS - "internal/sequence_urbg.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - TESTONLY -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_salted_seed_seq - HDRS - "internal/salted_seed_seq.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::inlined_vector - absl::optional - absl::span - absl::random_internal_seed_material - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_iostream_state_saver - HDRS - "internal/iostream_state_saver.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::int128 - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_generate_real - HDRS - "internal/generate_real.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::bits - absl::random_internal_fastmath - absl::random_internal_traits - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_wide_multiply - HDRS - "internal/wide_multiply.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::bits - absl::config - absl::int128 -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_fastmath - HDRS - "internal/fastmath.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::bits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_nonsecure_base - HDRS - "internal/nonsecure_base.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::core_headers - absl::optional - absl::random_internal_pool_urbg - absl::random_internal_salted_seed_seq - absl::random_internal_seed_material - absl::span - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_pcg_engine - HDRS - "internal/pcg_engine.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::int128 - absl::random_internal_fastmath - absl::random_internal_iostream_state_saver - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_randen_engine - HDRS - "internal/randen_engine.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_iostream_state_saver - absl::random_internal_randen - absl::raw_logging_internal - absl::type_traits -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_platform - HDRS - "internal/randen_traits.h" - "internal/platform.h" - SRCS - "internal/randen_round_keys.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_randen - SRCS - "internal/randen.cc" - HDRS - "internal/randen.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_platform - absl::random_internal_randen_hwaes - absl::random_internal_randen_slow -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_randen_slow - SRCS - "internal/randen_slow.cc" - HDRS - "internal/randen_slow.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_platform - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_randen_hwaes - SRCS - "internal/randen_detect.cc" - HDRS - "internal/randen_detect.h" - "internal/randen_hwaes.h" - COPTS - ${ABSL_DEFAULT_COPTS} - ${ABSL_RANDOM_RANDEN_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_platform - absl::random_internal_randen_hwaes_impl - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_randen_hwaes_impl - SRCS - "internal/randen_hwaes.cc" - "internal/randen_hwaes.h" - COPTS - ${ABSL_DEFAULT_COPTS} - ${ABSL_RANDOM_RANDEN_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_platform - absl::config -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_distribution_test_util - SRCS - "internal/chi_square.cc" - "internal/distribution_test_util.cc" - HDRS - "internal/chi_square.h" - "internal/distribution_test_util.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::core_headers - absl::raw_logging_internal - absl::strings - absl::str_format - absl::span -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_traits_test - SRCS - "internal/traits_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_traits - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_generate_real_test - SRCS - "internal/generate_real_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::bits - absl::flags - absl::random_internal_generate_real - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_distribution_test_util_test - SRCS - "internal/distribution_test_util_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_distribution_test_util - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_fastmath_test - SRCS - "internal/fastmath_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_fastmath - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_explicit_seed_seq_test - SRCS - "internal/explicit_seed_seq_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_explicit_seed_seq - absl::random_seed_sequences - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_salted_seed_seq_test - SRCS - "internal/salted_seed_seq_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_salted_seed_seq - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_chi_square_test - SRCS - "internal/chi_square_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::core_headers - absl::random_internal_distribution_test_util - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_fast_uniform_bits_test - SRCS - "internal/fast_uniform_bits_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_fast_uniform_bits - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_nonsecure_base_test - SRCS - "internal/nonsecure_base_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_nonsecure_base - absl::random_random - absl::random_distributions - absl::random_seed_sequences - absl::strings - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_seed_material_test - SRCS - "internal/seed_material_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_seed_material - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_pool_urbg_test - SRCS - "internal/pool_urbg_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_pool_urbg - absl::span - absl::type_traits - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_pcg_engine_test - SRCS - "internal/pcg_engine_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_explicit_seed_seq - absl::random_internal_pcg_engine - absl::time - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_randen_engine_test - SRCS - "internal/randen_engine_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_explicit_seed_seq - absl::random_internal_randen_engine - absl::raw_logging_internal - absl::strings - absl::time - gmock - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_randen_test - SRCS - "internal/randen_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_randen - absl::type_traits - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_randen_slow_test - SRCS - "internal/randen_slow_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_randen_slow - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_randen_hwaes_test - SRCS - "internal/randen_hwaes_test.cc" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_platform - absl::random_internal_randen_hwaes - absl::random_internal_randen_hwaes_impl - absl::raw_logging_internal - absl::str_format - gmock - gtest -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - random_internal_uniform_helper - HDRS - "internal/uniform_helper.h" - COPTS - ${ABSL_DEFAULT_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::config - absl::random_internal_traits - absl::type_traits -) - -# 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_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" - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_iostream_state_saver - gtest_main -) - -# Internal-only target, do not depend on directly. -absl_cc_test( - NAME - random_internal_wide_multiply_test - SRCS - internal/wide_multiply_test.cc - COPTS - ${ABSL_TEST_COPTS} - LINKOPTS - ${ABSL_DEFAULT_LINKOPTS} - DEPS - absl::random_internal_wide_multiply - absl::bits - absl::int128 - gtest_main -) diff --git a/third_party/abseil_cpp/absl/random/benchmarks.cc b/third_party/abseil_cpp/absl/random/benchmarks.cc deleted file mode 100644 index 87bbb9810a77..000000000000 --- a/third_party/abseil_cpp/absl/random/benchmarks.cc +++ /dev/null @@ -1,383 +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. - -// Benchmarks for absl random distributions as well as a selection of the -// C++ standard library random distributions. - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <initializer_list> -#include <iterator> -#include <limits> -#include <random> -#include <type_traits> -#include <vector> - -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" -#include "absl/random/bernoulli_distribution.h" -#include "absl/random/beta_distribution.h" -#include "absl/random/exponential_distribution.h" -#include "absl/random/gaussian_distribution.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/randen_engine.h" -#include "absl/random/log_uniform_int_distribution.h" -#include "absl/random/poisson_distribution.h" -#include "absl/random/random.h" -#include "absl/random/uniform_int_distribution.h" -#include "absl/random/uniform_real_distribution.h" -#include "absl/random/zipf_distribution.h" -#include "benchmark/benchmark.h" - -namespace { - -// Seed data to avoid reading random_device() for benchmarks. -uint32_t kSeedData[] = { - 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, - 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, - 0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A, - 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, - 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A18FF, 0x5664526C, 0xC2B19EE1, - 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, - 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, - 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, - 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0x13198A2E, 0x03707344, -}; - -// PrecompiledSeedSeq provides kSeedData to a conforming -// random engine to speed initialization in the benchmarks. -class PrecompiledSeedSeq { - public: - using result_type = uint32_t; - - PrecompiledSeedSeq() {} - - template <typename Iterator> - PrecompiledSeedSeq(Iterator begin, Iterator end) {} - - template <typename T> - PrecompiledSeedSeq(std::initializer_list<T> il) {} - - template <typename OutIterator> - void generate(OutIterator begin, OutIterator end) { - static size_t idx = 0; - for (; begin != end; begin++) { - *begin = kSeedData[idx++]; - if (idx >= ABSL_ARRAYSIZE(kSeedData)) { - idx = 0; - } - } - } - - size_t size() const { return ABSL_ARRAYSIZE(kSeedData); } - - template <typename OutIterator> - void param(OutIterator out) const { - std::copy(std::begin(kSeedData), std::end(kSeedData), out); - } -}; - -// use_default_initialization<T> indicates whether the random engine -// T must be default initialized, or whether we may initialize it using -// a seed sequence. This is used because some engines do not accept seed -// sequence-based initialization. -template <typename E> -using use_default_initialization = std::false_type; - -// make_engine<T, SSeq> returns a random_engine which is initialized, -// either via the default constructor, when use_default_initialization<T> -// is true, or via the indicated seed sequence, SSeq. -template <typename Engine, typename SSeq = PrecompiledSeedSeq> -typename absl::enable_if_t<!use_default_initialization<Engine>::value, Engine> -make_engine() { - // Initialize the random engine using the seed sequence SSeq, which - // is constructed from the precompiled seed data. - SSeq seq(std::begin(kSeedData), std::end(kSeedData)); - return Engine(seq); -} - -template <typename Engine, typename SSeq = PrecompiledSeedSeq> -typename absl::enable_if_t<use_default_initialization<Engine>::value, Engine> -make_engine() { - // Initialize the random engine using the default constructor. - return Engine(); -} - -template <typename Engine, typename SSeq> -void BM_Construct(benchmark::State& state) { - for (auto _ : state) { - auto rng = make_engine<Engine, SSeq>(); - benchmark::DoNotOptimize(rng()); - } -} - -template <typename Engine> -void BM_Direct(benchmark::State& state) { - using value_type = typename Engine::result_type; - // Direct use of the URBG. - auto rng = make_engine<Engine>(); - for (auto _ : state) { - benchmark::DoNotOptimize(rng()); - } - state.SetBytesProcessed(sizeof(value_type) * state.iterations()); -} - -template <typename Engine> -void BM_Generate(benchmark::State& state) { - // std::generate makes a copy of the RNG; thus this tests the - // copy-constructor efficiency. - using value_type = typename Engine::result_type; - std::vector<value_type> v(64); - auto rng = make_engine<Engine>(); - while (state.KeepRunningBatch(64)) { - std::generate(std::begin(v), std::end(v), rng); - } -} - -template <typename Engine, size_t elems> -void BM_Shuffle(benchmark::State& state) { - // Direct use of the Engine. - std::vector<uint32_t> v(elems); - while (state.KeepRunningBatch(elems)) { - auto rng = make_engine<Engine>(); - std::shuffle(std::begin(v), std::end(v), rng); - } -} - -template <typename Engine, size_t elems> -void BM_ShuffleReuse(benchmark::State& state) { - // Direct use of the Engine. - std::vector<uint32_t> v(elems); - auto rng = make_engine<Engine>(); - while (state.KeepRunningBatch(elems)) { - std::shuffle(std::begin(v), std::end(v), rng); - } -} - -template <typename Engine, typename Dist, typename... Args> -void BM_Dist(benchmark::State& state, Args&&... args) { - using value_type = typename Dist::result_type; - auto rng = make_engine<Engine>(); - Dist dis{std::forward<Args>(args)...}; - // Compare the following loop performance: - for (auto _ : state) { - benchmark::DoNotOptimize(dis(rng)); - } - state.SetBytesProcessed(sizeof(value_type) * state.iterations()); -} - -template <typename Engine, typename Dist> -void BM_Large(benchmark::State& state) { - using value_type = typename Dist::result_type; - volatile value_type kMin = 0; - volatile value_type kMax = std::numeric_limits<value_type>::max() / 2 + 1; - BM_Dist<Engine, Dist>(state, kMin, kMax); -} - -template <typename Engine, typename Dist> -void BM_Small(benchmark::State& state) { - using value_type = typename Dist::result_type; - volatile value_type kMin = 0; - volatile value_type kMax = std::numeric_limits<value_type>::max() / 64 + 1; - BM_Dist<Engine, Dist>(state, kMin, kMax); -} - -template <typename Engine, typename Dist, int A> -void BM_Bernoulli(benchmark::State& state) { - volatile double a = static_cast<double>(A) / 1000000; - BM_Dist<Engine, Dist>(state, a); -} - -template <typename Engine, typename Dist, int A, int B> -void BM_Beta(benchmark::State& state) { - using value_type = typename Dist::result_type; - volatile value_type a = static_cast<value_type>(A) / 100; - volatile value_type b = static_cast<value_type>(B) / 100; - BM_Dist<Engine, Dist>(state, a, b); -} - -template <typename Engine, typename Dist, int A> -void BM_Gamma(benchmark::State& state) { - using value_type = typename Dist::result_type; - volatile value_type a = static_cast<value_type>(A) / 100; - BM_Dist<Engine, Dist>(state, a); -} - -template <typename Engine, typename Dist, int A = 100> -void BM_Poisson(benchmark::State& state) { - volatile double a = static_cast<double>(A) / 100; - BM_Dist<Engine, Dist>(state, a); -} - -template <typename Engine, typename Dist, int Q = 2, int V = 1> -void BM_Zipf(benchmark::State& state) { - using value_type = typename Dist::result_type; - volatile double q = Q; - volatile double v = V; - BM_Dist<Engine, Dist>(state, std::numeric_limits<value_type>::max(), q, v); -} - -template <typename Engine, typename Dist> -void BM_Thread(benchmark::State& state) { - using value_type = typename Dist::result_type; - auto rng = make_engine<Engine>(); - Dist dis{}; - for (auto _ : state) { - benchmark::DoNotOptimize(dis(rng)); - } - state.SetBytesProcessed(sizeof(value_type) * state.iterations()); -} - -// NOTES: -// -// std::geometric_distribution is similar to the zipf distributions. -// The algorithm for the geometric_distribution is, basically, -// floor(log(1-X) / log(1-p)) - -// Normal benchmark suite -#define BM_BASIC(Engine) \ - BENCHMARK_TEMPLATE(BM_Construct, Engine, PrecompiledSeedSeq); \ - BENCHMARK_TEMPLATE(BM_Construct, Engine, std::seed_seq); \ - BENCHMARK_TEMPLATE(BM_Direct, Engine); \ - BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 10); \ - BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100); \ - BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000); \ - BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100); \ - BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::random_internal::FastUniformBits<uint32_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::random_internal::FastUniformBits<uint64_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Large, Engine, \ - std::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Large, Engine, \ - std::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Large, Engine, \ - absl::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Large, Engine, \ - absl::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<float>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<float>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<double>) - -#define BM_COPY(Engine) BENCHMARK_TEMPLATE(BM_Generate, Engine) - -#define BM_THREAD(Engine) \ - BENCHMARK_TEMPLATE(BM_Thread, Engine, \ - absl::uniform_int_distribution<int64_t>) \ - ->ThreadPerCpu(); \ - BENCHMARK_TEMPLATE(BM_Thread, Engine, \ - absl::uniform_real_distribution<double>) \ - ->ThreadPerCpu(); \ - BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100)->ThreadPerCpu(); \ - BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000)->ThreadPerCpu(); \ - BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100)->ThreadPerCpu(); \ - BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000)->ThreadPerCpu(); - -#define BM_EXTENDED(Engine) \ - /* -------------- Extended Uniform -----------------------*/ \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - std::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - std::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - absl::uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - absl::uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, std::uniform_real_distribution<float>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - std::uniform_real_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - absl::uniform_real_distribution<float>); \ - BENCHMARK_TEMPLATE(BM_Small, Engine, \ - absl::uniform_real_distribution<double>); \ - /* -------------- Other -----------------------*/ \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::normal_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::gaussian_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::exponential_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::exponential_distribution<double>); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \ - 100); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \ - 100); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \ - 10 * 100); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \ - 10 * 100); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \ - 13 * 100); \ - BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \ - 13 * 100); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::log_uniform_int_distribution<int32_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, \ - absl::log_uniform_int_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Dist, Engine, std::geometric_distribution<int64_t>); \ - BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>); \ - BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>, 2, \ - 3); \ - BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, std::bernoulli_distribution, \ - 257305); \ - BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, absl::bernoulli_distribution, \ - 257305); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 65, \ - 41); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 99, \ - 330); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 150, \ - 150); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 410, \ - 580); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 65, 41); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 99, \ - 330); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 150, \ - 150); \ - BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 410, \ - 580); \ - BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<float>, 199); \ - BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<double>, 199); - -// ABSL Recommended interfaces. -BM_BASIC(absl::InsecureBitGen); // === pcg64_2018_engine -BM_BASIC(absl::BitGen); // === randen_engine<uint64_t>. -BM_THREAD(absl::BitGen); -BM_EXTENDED(absl::BitGen); - -// Instantiate benchmarks for multiple engines. -using randen_engine_64 = absl::random_internal::randen_engine<uint64_t>; -using randen_engine_32 = absl::random_internal::randen_engine<uint32_t>; - -// Comparison interfaces. -BM_BASIC(std::mt19937_64); -BM_COPY(std::mt19937_64); -BM_EXTENDED(std::mt19937_64); -BM_BASIC(randen_engine_64); -BM_COPY(randen_engine_64); -BM_EXTENDED(randen_engine_64); - -BM_BASIC(std::mt19937); -BM_COPY(std::mt19937); -BM_BASIC(randen_engine_32); -BM_COPY(randen_engine_32); - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/bernoulli_distribution.h b/third_party/abseil_cpp/absl/random/bernoulli_distribution.h deleted file mode 100644 index 25bd0d5ca420..000000000000 --- a/third_party/abseil_cpp/absl/random/bernoulli_distribution.h +++ /dev/null @@ -1,200 +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. - -#ifndef ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ -#define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ - -#include <cstdint> -#include <istream> -#include <limits> - -#include "absl/base/optimization.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::bernoulli_distribution is a drop in replacement for -// std::bernoulli_distribution. It guarantees that (given a perfect -// UniformRandomBitGenerator) the acceptance probability is *exactly* equal to -// the given double. -// -// The implementation assumes that double is IEEE754 -class bernoulli_distribution { - public: - using result_type = bool; - - class param_type { - public: - using distribution_type = bernoulli_distribution; - - explicit param_type(double p = 0.5) : prob_(p) { - assert(p >= 0.0 && p <= 1.0); - } - - double p() const { return prob_; } - - friend bool operator==(const param_type& p1, const param_type& p2) { - return p1.p() == p2.p(); - } - friend bool operator!=(const param_type& p1, const param_type& p2) { - return p1.p() != p2.p(); - } - - private: - double prob_; - }; - - bernoulli_distribution() : bernoulli_distribution(0.5) {} - - explicit bernoulli_distribution(double p) : param_(p) {} - - explicit bernoulli_distribution(param_type p) : param_(p) {} - - // no-op - void reset() {} - - template <typename URBG> - bool operator()(URBG& g) { // NOLINT(runtime/references) - return Generate(param_.p(), g); - } - - template <typename URBG> - bool operator()(URBG& g, // NOLINT(runtime/references) - const param_type& param) { - return Generate(param.p(), g); - } - - param_type param() const { return param_; } - void param(const param_type& param) { param_ = param; } - - double p() const { return param_.p(); } - - result_type(min)() const { return false; } - result_type(max)() const { return true; } - - friend bool operator==(const bernoulli_distribution& d1, - const bernoulli_distribution& d2) { - return d1.param_ == d2.param_; - } - - friend bool operator!=(const bernoulli_distribution& d1, - const bernoulli_distribution& d2) { - return d1.param_ != d2.param_; - } - - private: - static constexpr uint64_t kP32 = static_cast<uint64_t>(1) << 32; - - template <typename URBG> - static bool Generate(double p, URBG& g); // NOLINT(runtime/references) - - param_type param_; -}; - -template <typename CharT, typename Traits> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const bernoulli_distribution& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<double>::kPrecision); - os << x.p(); - return os; -} - -template <typename CharT, typename Traits> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - bernoulli_distribution& x) { // NOLINT(runtime/references) - auto saver = random_internal::make_istream_state_saver(is); - auto p = random_internal::read_floating_point<double>(is); - if (!is.fail()) { - x.param(bernoulli_distribution::param_type(p)); - } - return is; -} - -template <typename URBG> -bool bernoulli_distribution::Generate(double p, - URBG& g) { // NOLINT(runtime/references) - random_internal::FastUniformBits<uint32_t> fast_u32; - - while (true) { - // There are two aspects of the definition of `c` below that are worth - // commenting on. First, because `p` is in the range [0, 1], `c` is in the - // range [0, 2^32] which does not fit in a uint32_t and therefore requires - // 64 bits. - // - // Second, `c` is constructed by first casting explicitly to a signed - // integer and then converting implicitly to an unsigned integer of the same - // size. This is done because the hardware conversion instructions produce - // signed integers from double; if taken as a uint64_t the conversion would - // be wrong for doubles greater than 2^63 (not relevant in this use-case). - // If converted directly to an unsigned integer, the compiler would end up - // emitting code to handle such large values that are not relevant due to - // the known bounds on `c`. To avoid these extra instructions this - // implementation converts first to the signed type and then use the - // implicit conversion to unsigned (which is a no-op). - const uint64_t c = static_cast<int64_t>(p * kP32); - const uint32_t v = fast_u32(g); - // FAST PATH: this path fails with probability 1/2^32. Note that simply - // returning v <= c would approximate P very well (up to an absolute error - // of 1/2^32); the slow path (taken in that range of possible error, in the - // case of equality) eliminates the remaining error. - if (ABSL_PREDICT_TRUE(v != c)) return v < c; - - // It is guaranteed that `q` is strictly less than 1, because if `q` were - // greater than or equal to 1, the same would be true for `p`. Certainly `p` - // cannot be greater than 1, and if `p == 1`, then the fast path would - // necessary have been taken already. - const double q = static_cast<double>(c) / kP32; - - // The probability of acceptance on the fast path is `q` and so the - // probability of acceptance here should be `p - q`. - // - // Note that `q` is obtained from `p` via some shifts and conversions, the - // upshot of which is that `q` is simply `p` with some of the - // least-significant bits of its mantissa set to zero. This means that the - // difference `p - q` will not have any rounding errors. To see why, pretend - // that double has 10 bits of resolution and q is obtained from `p` in such - // a way that the 4 least-significant bits of its mantissa are set to zero. - // For example: - // p = 1.1100111011 * 2^-1 - // q = 1.1100110000 * 2^-1 - // p - q = 1.011 * 2^-8 - // The difference `p - q` has exactly the nonzero mantissa bits that were - // "lost" in `q` producing a number which is certainly representable in a - // double. - const double left = p - q; - - // By construction, the probability of being on this slow path is 1/2^32, so - // P(accept in slow path) = P(accept| in slow path) * P(slow path), - // which means the probability of acceptance here is `1 / (left * kP32)`: - const double here = left * kP32; - - // The simplest way to compute the result of this trial is to repeat the - // whole algorithm with the new probability. This terminates because even - // given arbitrarily unfriendly "random" bits, each iteration either - // multiplies a tiny probability by 2^32 (if c == 0) or strips off some - // number of nonzero mantissa bits. That process is bounded. - if (here == 0) return false; - p = here; - } -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/bernoulli_distribution_test.cc b/third_party/abseil_cpp/absl/random/bernoulli_distribution_test.cc deleted file mode 100644 index b250f8787c6e..000000000000 --- a/third_party/abseil_cpp/absl/random/bernoulli_distribution_test.cc +++ /dev/null @@ -1,217 +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/bernoulli_distribution.h" - -#include <cmath> -#include <cstddef> -#include <random> -#include <sstream> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" - -namespace { - -class BernoulliTest : public testing::TestWithParam<std::pair<double, size_t>> { -}; - -TEST_P(BernoulliTest, Serialize) { - const double d = GetParam().first; - absl::bernoulli_distribution before(d); - - { - absl::bernoulli_distribution via_param{ - absl::bernoulli_distribution::param_type(d)}; - EXPECT_EQ(via_param, before); - } - - std::stringstream ss; - ss << before; - absl::bernoulli_distribution after(0.6789); - - EXPECT_NE(before.p(), after.p()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.p(), after.p()); - EXPECT_EQ(before.param(), after.param()); - EXPECT_EQ(before, after); -} - -TEST_P(BernoulliTest, Accuracy) { - // Sadly, the claim to fame for this implementation is precise accuracy, which - // is very, very hard to measure, the improvements come as trials approach the - // limit of double accuracy; thus the outcome differs from the - // std::bernoulli_distribution with a probability of approximately 1 in 2^-53. - const std::pair<double, size_t> para = GetParam(); - size_t trials = para.second; - double p = para.first; - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6); - - size_t yes = 0; - absl::bernoulli_distribution dist(p); - for (size_t i = 0; i < trials; ++i) { - if (dist(rng)) yes++; - } - - // Compute the distribution parameters for a binomial test, using a normal - // approximation for the confidence interval, as there are a sufficiently - // large number of trials that the central limit theorem applies. - const double stddev_p = std::sqrt((p * (1.0 - p)) / trials); - const double expected = trials * p; - const double stddev = trials * stddev_p; - - // 5 sigma, approved by Richard Feynman - EXPECT_NEAR(yes, expected, 5 * stddev) - << "@" << p << ", " - << std::abs(static_cast<double>(yes) - expected) / stddev << " stddev"; -} - -// There must be many more trials to make the mean approximately normal for `p` -// closes to 0 or 1. -INSTANTIATE_TEST_SUITE_P( - All, BernoulliTest, - ::testing::Values( - // Typical values. - std::make_pair(0, 30000), std::make_pair(1e-3, 30000000), - std::make_pair(0.1, 3000000), std::make_pair(0.5, 3000000), - std::make_pair(0.9, 30000000), std::make_pair(0.999, 30000000), - std::make_pair(1, 30000), - // Boundary cases. - std::make_pair(std::nextafter(1.0, 0.0), 1), // ~1 - epsilon - std::make_pair(std::numeric_limits<double>::epsilon(), 1), - std::make_pair(std::nextafter(std::numeric_limits<double>::min(), - 1.0), // min + epsilon - 1), - std::make_pair(std::numeric_limits<double>::min(), // smallest normal - 1), - std::make_pair( - std::numeric_limits<double>::denorm_min(), // smallest denorm - 1), - std::make_pair(std::numeric_limits<double>::min() / 2, 1), // denorm - std::make_pair(std::nextafter(std::numeric_limits<double>::min(), - 0.0), // denorm_max - 1))); - -// NOTE: absl::bernoulli_distribution is not guaranteed to be stable. -TEST(BernoulliTest, StabilityTest) { - // absl::bernoulli_distribution stability relies on FastUniformBits and - // integer arithmetic. - absl::random_internal::sequence_urbg urbg({ - 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull, - 0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull, - 0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull, - 0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull, - 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full, - 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull, - 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull, - 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull, - 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull, - 0xe3fd722dc65ad09eull, 0x5a14fd21ea2a5705ull, 0x14e6ea4d6edb0c73ull, - 0x275b0dc7e0a18acfull, 0x36cebe0d2653682eull, 0x0361e9b23861596bull, - }); - - // Generate a string of '0' and '1' for the distribution output. - auto generate = [&urbg](absl::bernoulli_distribution& dist) { - std::string output; - output.reserve(36); - urbg.reset(); - for (int i = 0; i < 35; i++) { - output.append(dist(urbg) ? "1" : "0"); - } - return output; - }; - - const double kP = 0.0331289862362; - { - absl::bernoulli_distribution dist(kP); - auto v = generate(dist); - EXPECT_EQ(35, urbg.invocations()); - EXPECT_EQ(v, "00000000000010000000000010000000000") << dist; - } - { - absl::bernoulli_distribution dist(kP * 10.0); - auto v = generate(dist); - EXPECT_EQ(35, urbg.invocations()); - EXPECT_EQ(v, "00000100010010010010000011000011010") << dist; - } - { - absl::bernoulli_distribution dist(kP * 20.0); - auto v = generate(dist); - EXPECT_EQ(35, urbg.invocations()); - EXPECT_EQ(v, "00011110010110110011011111110111011") << dist; - } - { - absl::bernoulli_distribution dist(1.0 - kP); - auto v = generate(dist); - EXPECT_EQ(35, urbg.invocations()); - EXPECT_EQ(v, "11111111111111111111011111111111111") << dist; - } -} - -TEST(BernoulliTest, StabilityTest2) { - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - // Generate a string of '0' and '1' for the distribution output. - auto generate = [&urbg](absl::bernoulli_distribution& dist) { - std::string output; - output.reserve(13); - urbg.reset(); - for (int i = 0; i < 12; i++) { - output.append(dist(urbg) ? "1" : "0"); - } - return output; - }; - - constexpr double b0 = 1.0 / 13.0 / 0.2; - constexpr double b1 = 2.0 / 13.0 / 0.2; - constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1)); - { - absl::bernoulli_distribution dist(b0); - auto v = generate(dist); - EXPECT_EQ(12, urbg.invocations()); - EXPECT_EQ(v, "000011100101") << dist; - } - { - absl::bernoulli_distribution dist(b1); - auto v = generate(dist); - EXPECT_EQ(12, urbg.invocations()); - EXPECT_EQ(v, "001111101101") << dist; - } - { - absl::bernoulli_distribution dist(b3); - auto v = generate(dist); - EXPECT_EQ(12, urbg.invocations()); - EXPECT_EQ(v, "001111101111") << dist; - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/beta_distribution.h b/third_party/abseil_cpp/absl/random/beta_distribution.h deleted file mode 100644 index c154066fb813..000000000000 --- a/third_party/abseil_cpp/absl/random/beta_distribution.h +++ /dev/null @@ -1,427 +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. - -#ifndef ABSL_RANDOM_BETA_DISTRIBUTION_H_ -#define ABSL_RANDOM_BETA_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <ostream> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::beta_distribution: -// Generate a floating-point variate conforming to a Beta distribution: -// pdf(x) \propto x^(alpha-1) * (1-x)^(beta-1), -// where the params alpha and beta are both strictly positive real values. -// -// The support is the open interval (0, 1), but the return value might be equal -// to 0 or 1, due to numerical errors when alpha and beta are very different. -// -// Usage note: One usage is that alpha and beta are counts of number of -// successes and failures. When the total number of trials are large, consider -// approximating a beta distribution with a Gaussian distribution with the same -// mean and variance. One could use the skewness, which depends only on the -// smaller of alpha and beta when the number of trials are sufficiently large, -// to quantify how far a beta distribution is from the normal distribution. -template <typename RealType = double> -class beta_distribution { - public: - using result_type = RealType; - - class param_type { - public: - using distribution_type = beta_distribution; - - explicit param_type(result_type alpha, result_type beta) - : alpha_(alpha), beta_(beta) { - assert(alpha >= 0); - assert(beta >= 0); - assert(alpha <= (std::numeric_limits<result_type>::max)()); - assert(beta <= (std::numeric_limits<result_type>::max)()); - if (alpha == 0 || beta == 0) { - method_ = DEGENERATE_SMALL; - x_ = (alpha >= beta) ? 1 : 0; - return; - } - // a_ = min(beta, alpha), b_ = max(beta, alpha). - if (beta < alpha) { - inverted_ = true; - a_ = beta; - b_ = alpha; - } else { - inverted_ = false; - a_ = alpha; - b_ = beta; - } - if (a_ <= 1 && b_ >= ThresholdForLargeA()) { - method_ = DEGENERATE_SMALL; - x_ = inverted_ ? result_type(1) : result_type(0); - return; - } - // For threshold values, see also: - // Evaluation of Beta Generation Algorithms, Ying-Chao Hung, et. al. - // February, 2009. - if ((b_ < 1.0 && a_ + b_ <= 1.2) || a_ <= ThresholdForSmallA()) { - // Choose Joehnk over Cheng when it's faster or when Cheng encounters - // numerical issues. - method_ = JOEHNK; - a_ = result_type(1) / alpha_; - b_ = result_type(1) / beta_; - if (std::isinf(a_) || std::isinf(b_)) { - method_ = DEGENERATE_SMALL; - x_ = inverted_ ? result_type(1) : result_type(0); - } - return; - } - if (a_ >= ThresholdForLargeA()) { - method_ = DEGENERATE_LARGE; - // Note: on PPC for long double, evaluating - // `std::numeric_limits::max() / ThresholdForLargeA` results in NaN. - result_type r = a_ / b_; - x_ = (inverted_ ? result_type(1) : r) / (1 + r); - return; - } - x_ = a_ + b_; - log_x_ = std::log(x_); - if (a_ <= 1) { - method_ = CHENG_BA; - y_ = result_type(1) / a_; - gamma_ = a_ + a_; - return; - } - method_ = CHENG_BB; - result_type r = (a_ - 1) / (b_ - 1); - y_ = std::sqrt((1 + r) / (b_ * r * 2 - r + 1)); - gamma_ = a_ + result_type(1) / y_; - } - - result_type alpha() const { return alpha_; } - result_type beta() const { return beta_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.alpha_ == b.alpha_ && a.beta_ == b.beta_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class beta_distribution; - -#ifdef _MSC_VER - // MSVC does not have constexpr implementations for std::log and std::exp - // so they are computed at runtime. -#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR -#else -#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR constexpr -#endif - - // The threshold for whether std::exp(1/a) is finite. - // Note that this value is quite large, and a smaller a_ is NOT abnormal. - static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type - ThresholdForSmallA() { - return result_type(1) / - std::log((std::numeric_limits<result_type>::max)()); - } - - // The threshold for whether a * std::log(a) is finite. - static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type - ThresholdForLargeA() { - return std::exp( - std::log((std::numeric_limits<result_type>::max)()) - - std::log(std::log((std::numeric_limits<result_type>::max)())) - - ThresholdPadding()); - } - -#undef ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR - - // Pad the threshold for large A for long double on PPC. This is done via a - // template specialization below. - static constexpr result_type ThresholdPadding() { return 0; } - - enum Method { - JOEHNK, // Uses algorithm Joehnk - CHENG_BA, // Uses algorithm BA in Cheng - CHENG_BB, // Uses algorithm BB in Cheng - - // Note: See also: - // Hung et al. Evaluation of beta generation algorithms. Communications - // in Statistics-Simulation and Computation 38.4 (2009): 750-770. - // especially: - // Zechner, Heinz, and Ernst Stadlober. Generating beta variates via - // patchwork rejection. Computing 50.1 (1993): 1-18. - - DEGENERATE_SMALL, // a_ is abnormally small. - DEGENERATE_LARGE, // a_ is abnormally large. - }; - - result_type alpha_; - result_type beta_; - - result_type a_; // the smaller of {alpha, beta}, or 1.0/alpha_ in JOEHNK - result_type b_; // the larger of {alpha, beta}, or 1.0/beta_ in JOEHNK - result_type x_; // alpha + beta, or the result in degenerate cases - result_type log_x_; // log(x_) - result_type y_; // "beta" in Cheng - result_type gamma_; // "gamma" in Cheng - - Method method_; - - // Placing this last for optimal alignment. - // Whether alpha_ != a_, i.e. true iff alpha_ > beta_. - bool inverted_; - - static_assert(std::is_floating_point<RealType>::value, - "Class-template absl::beta_distribution<> must be " - "parameterized using a floating-point type."); - }; - - beta_distribution() : beta_distribution(1) {} - - explicit beta_distribution(result_type alpha, result_type beta = 1) - : param_(alpha, beta) {} - - explicit beta_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - // Generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { return 0; } - result_type(max)() const { return 1; } - - result_type alpha() const { return param_.alpha(); } - result_type beta() const { return param_.beta(); } - - friend bool operator==(const beta_distribution& a, - const beta_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const beta_distribution& a, - const beta_distribution& b) { - return a.param_ != b.param_; - } - - private: - template <typename URBG> - result_type AlgorithmJoehnk(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - template <typename URBG> - result_type AlgorithmCheng(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - template <typename URBG> - result_type DegenerateCase(URBG& g, // NOLINT(runtime/references) - const param_type& p) { - if (p.method_ == param_type::DEGENERATE_SMALL && p.alpha_ == p.beta_) { - // Returns 0 or 1 with equal probability. - random_internal::FastUniformBits<uint8_t> fast_u8; - return static_cast<result_type>((fast_u8(g) & 0x10) != - 0); // pick any single bit. - } - return p.x_; - } - - param_type param_; - random_internal::FastUniformBits<uint64_t> fast_u64_; -}; - -#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ - defined(__ppc__) || defined(__PPC__) -// PPC needs a more stringent boundary for long double. -template <> -constexpr long double -beta_distribution<long double>::param_type::ThresholdPadding() { - return 10; -} -#endif - -template <typename RealType> -template <typename URBG> -typename beta_distribution<RealType>::result_type -beta_distribution<RealType>::AlgorithmJoehnk( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - using real_type = - absl::conditional_t<std::is_same<RealType, float>::value, float, double>; - - // Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten - // Zufallszahlen. Metrika 8.1 (1964): 5-15. - // This method is described in Knuth, Vol 2 (Third Edition), pp 134. - - result_type u, v, x, y, z; - for (;;) { - u = GenerateRealFromBits<real_type, GeneratePositiveTag, false>( - fast_u64_(g)); - v = GenerateRealFromBits<real_type, GeneratePositiveTag, false>( - fast_u64_(g)); - - // Direct method. std::pow is slow for float, so rely on the optimizer to - // remove the std::pow() path for that case. - if (!std::is_same<float, result_type>::value) { - x = std::pow(u, p.a_); - y = std::pow(v, p.b_); - z = x + y; - if (z > 1) { - // Reject if and only if `x + y > 1.0` - continue; - } - if (z > 0) { - // When both alpha and beta are small, x and y are both close to 0, so - // divide by (x+y) directly may result in nan. - return x / z; - } - } - - // Log transform. - // x = log( pow(u, p.a_) ), y = log( pow(v, p.b_) ) - // since u, v <= 1.0, x, y < 0. - x = std::log(u) * p.a_; - y = std::log(v) * p.b_; - if (!std::isfinite(x) || !std::isfinite(y)) { - continue; - } - // z = log( pow(u, a) + pow(v, b) ) - z = x > y ? (x + std::log(1 + std::exp(y - x))) - : (y + std::log(1 + std::exp(x - y))); - // Reject iff log(x+y) > 0. - if (z > 0) { - continue; - } - return std::exp(x - z); - } -} - -template <typename RealType> -template <typename URBG> -typename beta_distribution<RealType>::result_type -beta_distribution<RealType>::AlgorithmCheng( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - using real_type = - absl::conditional_t<std::is_same<RealType, float>::value, float, double>; - - // Based on Cheng, Russell CH. Generating beta variates with nonintegral - // shape parameters. Communications of the ACM 21.4 (1978): 317-322. - // (https://dl.acm.org/citation.cfm?id=359482). - static constexpr result_type kLogFour = - result_type(1.3862943611198906188344642429163531361); // log(4) - static constexpr result_type kS = - result_type(2.6094379124341003746007593332261876); // 1+log(5) - - const bool use_algorithm_ba = (p.method_ == param_type::CHENG_BA); - result_type u1, u2, v, w, z, r, s, t, bw_inv, lhs; - for (;;) { - u1 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>( - fast_u64_(g)); - u2 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>( - fast_u64_(g)); - v = p.y_ * std::log(u1 / (1 - u1)); - w = p.a_ * std::exp(v); - bw_inv = result_type(1) / (p.b_ + w); - r = p.gamma_ * v - kLogFour; - s = p.a_ + r - w; - z = u1 * u1 * u2; - if (!use_algorithm_ba && s + kS >= 5 * z) { - break; - } - t = std::log(z); - if (!use_algorithm_ba && s >= t) { - break; - } - lhs = p.x_ * (p.log_x_ + std::log(bw_inv)) + r; - if (lhs >= t) { - break; - } - } - return p.inverted_ ? (1 - w * bw_inv) : w * bw_inv; -} - -template <typename RealType> -template <typename URBG> -typename beta_distribution<RealType>::result_type -beta_distribution<RealType>::operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p) { - switch (p.method_) { - case param_type::JOEHNK: - return AlgorithmJoehnk(g, p); - case param_type::CHENG_BA: - ABSL_FALLTHROUGH_INTENDED; - case param_type::CHENG_BB: - return AlgorithmCheng(g, p); - default: - return DegenerateCase(g, p); - } -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const beta_distribution<RealType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<RealType>::kPrecision); - os << x.alpha() << os.fill() << x.beta(); - return os; -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - beta_distribution<RealType>& x) { // NOLINT(runtime/references) - using result_type = typename beta_distribution<RealType>::result_type; - using param_type = typename beta_distribution<RealType>::param_type; - result_type alpha, beta; - - auto saver = random_internal::make_istream_state_saver(is); - alpha = random_internal::read_floating_point<result_type>(is); - if (is.fail()) return is; - beta = random_internal::read_floating_point<result_type>(is); - if (!is.fail()) { - x.param(param_type(alpha, beta)); - } - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_BETA_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/beta_distribution_test.cc b/third_party/abseil_cpp/absl/random/beta_distribution_test.cc deleted file mode 100644 index 277e4dc6eed7..000000000000 --- a/third_party/abseil_cpp/absl/random/beta_distribution_test.cc +++ /dev/null @@ -1,619 +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/beta_distribution.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <random> -#include <sstream> -#include <string> -#include <unordered_map> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -namespace { - -template <typename IntType> -class BetaDistributionInterfaceTest : public ::testing::Test {}; - -using RealTypes = ::testing::Types<float, double, long double>; -TYPED_TEST_CASE(BetaDistributionInterfaceTest, RealTypes); - -TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) { - // The threshold for whether std::exp(1/a) is finite. - const TypeParam kSmallA = - 1.0f / std::log((std::numeric_limits<TypeParam>::max)()); - // The threshold for whether a * std::log(a) is finite. - const TypeParam kLargeA = - std::exp(std::log((std::numeric_limits<TypeParam>::max)()) - - std::log(std::log((std::numeric_limits<TypeParam>::max)()))); - 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; - absl::InsecureBitGen gen; - const TypeParam kValues[] = { - TypeParam(1e-20), TypeParam(1e-12), TypeParam(1e-8), TypeParam(1e-4), - TypeParam(1e-3), TypeParam(0.1), TypeParam(0.25), - std::nextafter(TypeParam(0.5), TypeParam(0)), // 0.5 - epsilon - std::nextafter(TypeParam(0.5), TypeParam(1)), // 0.5 + epsilon - TypeParam(0.5), TypeParam(1.0), // - std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon - std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon - TypeParam(12.5), TypeParam(1e2), TypeParam(1e8), TypeParam(1e12), - TypeParam(1e20), // - kSmallA, // - std::nextafter(kSmallA, TypeParam(0)), // - std::nextafter(kSmallA, TypeParam(1)), // - kLargeA, // - std::nextafter(kLargeA, TypeParam(0)), // - std::nextafter(kLargeA, std::numeric_limits<TypeParam>::max()), - 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(), - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(1)), // min + epsilon - std::numeric_limits<TypeParam>::min(), // smallest normal - std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm - std::numeric_limits<TypeParam>::min() / 2, // denorm - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(0)), // denorm_max - }; - for (TypeParam alpha : kValues) { - for (TypeParam beta : kValues) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("Smoke test for Beta(%a, %a)", alpha, beta)); - - param_type param(alpha, beta); - absl::beta_distribution<TypeParam> before(alpha, beta); - EXPECT_EQ(before.alpha(), param.alpha()); - EXPECT_EQ(before.beta(), param.beta()); - - { - absl::beta_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - EXPECT_EQ(via_param.param(), before.param()); - } - - // Smoke test. - for (int i = 0; i < kCount; ++i) { - auto sample = before(gen); - EXPECT_TRUE(std::isfinite(sample)); - EXPECT_GE(sample, before.min()); - EXPECT_LE(sample, before.max()); - } - - // Validate stream serialization. - std::stringstream ss; - ss << before; - absl::beta_distribution<TypeParam> after(3.8f, 1.43f); - EXPECT_NE(before.alpha(), after.alpha()); - EXPECT_NE(before.beta(), after.beta()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - -#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) // - << ss.str() << " " // - << (ss.good() ? "good " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - } - } -} - -TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) { - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6); - - // Extreme cases when the params are abnormal. - constexpr int kCount = 1000; - const TypeParam kSmallValues[] = { - std::numeric_limits<TypeParam>::min(), - std::numeric_limits<TypeParam>::denorm_min(), - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(0)), // denorm_max - std::numeric_limits<TypeParam>::epsilon(), - }; - const TypeParam kLargeValues[] = { - std::numeric_limits<TypeParam>::max() * static_cast<TypeParam>(0.9999), - std::numeric_limits<TypeParam>::max() - 1, - std::numeric_limits<TypeParam>::max(), - }; - { - // Small alpha and beta. - // Useful WolframAlpha plots: - // * plot InverseBetaRegularized[x, 0.0001, 0.0001] from 0.495 to 0.505 - // * Beta[1.0, 0.0000001, 0.0000001] - // * Beta[0.9999, 0.0000001, 0.0000001] - for (TypeParam alpha : kSmallValues) { - for (TypeParam beta : kSmallValues) { - int zeros = 0; - int ones = 0; - absl::beta_distribution<TypeParam> d(alpha, beta); - for (int i = 0; i < kCount; ++i) { - TypeParam x = d(rng); - if (x == 0.0) { - zeros++; - } else if (x == 1.0) { - ones++; - } - } - EXPECT_EQ(ones + zeros, kCount); - if (alpha == beta) { - EXPECT_NE(ones, 0); - EXPECT_NE(zeros, 0); - } - } - } - } - { - // Small alpha, large beta. - // Useful WolframAlpha plots: - // * plot InverseBetaRegularized[x, 0.0001, 10000] from 0.995 to 1 - // * Beta[0, 0.0000001, 1000000] - // * Beta[0.001, 0.0000001, 1000000] - // * Beta[1, 0.0000001, 1000000] - for (TypeParam alpha : kSmallValues) { - for (TypeParam beta : kLargeValues) { - absl::beta_distribution<TypeParam> d(alpha, beta); - for (int i = 0; i < kCount; ++i) { - EXPECT_EQ(d(rng), 0.0); - } - } - } - } - { - // Large alpha, small beta. - // Useful WolframAlpha plots: - // * plot InverseBetaRegularized[x, 10000, 0.0001] from 0 to 0.001 - // * Beta[0.99, 1000000, 0.0000001] - // * Beta[1, 1000000, 0.0000001] - for (TypeParam alpha : kLargeValues) { - for (TypeParam beta : kSmallValues) { - absl::beta_distribution<TypeParam> d(alpha, beta); - for (int i = 0; i < kCount; ++i) { - EXPECT_EQ(d(rng), 1.0); - } - } - } - } - { - // Large alpha and beta. - absl::beta_distribution<TypeParam> d(std::numeric_limits<TypeParam>::max(), - std::numeric_limits<TypeParam>::max()); - for (int i = 0; i < kCount; ++i) { - EXPECT_EQ(d(rng), 0.5); - } - } - { - // Large alpha and beta but unequal. - absl::beta_distribution<TypeParam> d( - std::numeric_limits<TypeParam>::max(), - std::numeric_limits<TypeParam>::max() * 0.9999); - for (int i = 0; i < kCount; ++i) { - TypeParam x = d(rng); - EXPECT_NE(x, 0.5f); - EXPECT_FLOAT_EQ(x, 0.500025f); - } - } -} - -class BetaDistributionModel { - public: - explicit BetaDistributionModel(::testing::tuple<double, double> p) - : alpha_(::testing::get<0>(p)), beta_(::testing::get<1>(p)) {} - - double Mean() const { return alpha_ / (alpha_ + beta_); } - - double Variance() const { - return alpha_ * beta_ / (alpha_ + beta_ + 1) / (alpha_ + beta_) / - (alpha_ + beta_); - } - - double Kurtosis() const { - return 3 + 6 * - ((alpha_ - beta_) * (alpha_ - beta_) * (alpha_ + beta_ + 1) - - alpha_ * beta_ * (2 + alpha_ + beta_)) / - alpha_ / beta_ / (alpha_ + beta_ + 2) / (alpha_ + beta_ + 3); - } - - protected: - const double alpha_; - const double beta_; -}; - -class BetaDistributionTest - : public ::testing::TestWithParam<::testing::tuple<double, double>>, - public BetaDistributionModel { - public: - BetaDistributionTest() : BetaDistributionModel(GetParam()) {} - - protected: - template <class D> - bool SingleZTestOnMeanAndVariance(double p, size_t samples); - - template <class D> - bool SingleChiSquaredTest(double p, size_t samples, size_t buckets); - - absl::InsecureBitGen rng_; -}; - -template <class D> -bool BetaDistributionTest::SingleZTestOnMeanAndVariance(double p, - size_t samples) { - D dis(alpha_, beta_); - - std::vector<double> data; - data.reserve(samples); - for (size_t i = 0; i < samples; i++) { - const double variate = dis(rng_); - EXPECT_FALSE(std::isnan(variate)); - // Note that equality is allowed on both sides. - EXPECT_GE(variate, 0.0); - EXPECT_LE(variate, 1.0); - data.push_back(variate); - } - - // We validate that the sample mean and sample variance are indeed from a - // Beta distribution with the given shape parameters. - const auto m = absl::random_internal::ComputeDistributionMoments(data); - - // The variance of the sample mean is variance / n. - const double mean_stddev = std::sqrt(Variance() / static_cast<double>(m.n)); - - // The variance of the sample variance is (approximately): - // (kurtosis - 1) * variance^2 / n - const double variance_stddev = std::sqrt( - (Kurtosis() - 1) * Variance() * Variance() / static_cast<double>(m.n)); - // z score for the sample variance. - const double z_variance = (m.variance - Variance()) / variance_stddev; - - const double max_err = absl::random_internal::MaxErrorTolerance(p); - const double z_mean = absl::random_internal::ZScore(Mean(), m); - const bool pass = - absl::random_internal::Near("z", z_mean, 0.0, max_err) && - absl::random_internal::Near("z_variance", z_variance, 0.0, max_err); - if (!pass) { - ABSL_INTERNAL_LOG( - INFO, - absl::StrFormat( - "Beta(%f, %f), " - "mean: sample %f, expect %f, which is %f stddevs away, " - "variance: sample %f, expect %f, which is %f stddevs away.", - alpha_, beta_, m.mean, Mean(), - std::abs(m.mean - Mean()) / mean_stddev, m.variance, Variance(), - std::abs(m.variance - Variance()) / variance_stddev)); - } - return pass; -} - -template <class D> -bool BetaDistributionTest::SingleChiSquaredTest(double p, size_t samples, - size_t buckets) { - constexpr double kErr = 1e-7; - std::vector<double> cutoffs, expected; - const double bucket_width = 1.0 / static_cast<double>(buckets); - int i = 1; - int unmerged_buckets = 0; - for (; i < buckets; ++i) { - const double p = bucket_width * static_cast<double>(i); - const double boundary = - absl::random_internal::BetaIncompleteInv(alpha_, beta_, p); - // The intention is to add `boundary` to the list of `cutoffs`. It becomes - // problematic, however, when the boundary values are not monotone, due to - // numerical issues when computing the inverse regularized incomplete - // Beta function. In these cases, we merge that bucket with its previous - // neighbor and merge their expected counts. - if ((cutoffs.empty() && boundary < kErr) || - (!cutoffs.empty() && boundary <= cutoffs.back())) { - unmerged_buckets++; - continue; - } - if (boundary >= 1.0 - 1e-10) { - break; - } - cutoffs.push_back(boundary); - expected.push_back(static_cast<double>(1 + unmerged_buckets) * - bucket_width * static_cast<double>(samples)); - unmerged_buckets = 0; - } - cutoffs.push_back(std::numeric_limits<double>::infinity()); - // Merge all remaining buckets. - expected.push_back(static_cast<double>(buckets - i + 1) * bucket_width * - static_cast<double>(samples)); - // Make sure that we don't merge all the buckets, making this test - // meaningless. - EXPECT_GE(cutoffs.size(), 3) << alpha_ << ", " << beta_; - - D dis(alpha_, beta_); - - std::vector<int32_t> counts(cutoffs.size(), 0); - for (int i = 0; i < samples; i++) { - const double x = dis(rng_); - auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x); - counts[std::distance(cutoffs.begin(), it)]++; - } - - // Null-hypothesis is that the distribution is beta distributed with the - // provided alpha, beta params (not estimated from the data). - const int dof = cutoffs.size() - 1; - - const double chi_square = absl::random_internal::ChiSquare( - counts.begin(), counts.end(), expected.begin(), expected.end()); - const bool pass = - (absl::random_internal::ChiSquarePValue(chi_square, dof) >= p); - if (!pass) { - for (int i = 0; i < cutoffs.size(); i++) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("cutoff[%d] = %f, actual count %d, expected %d", - i, cutoffs[i], counts[i], - static_cast<int>(expected[i]))); - } - - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat( - "Beta(%f, %f) %s %f, p = %f", alpha_, beta_, - absl::random_internal::kChiSquared, chi_square, - absl::random_internal::ChiSquarePValue(chi_square, dof))); - } - return pass; -} - -TEST_P(BetaDistributionTest, TestSampleStatistics) { - static constexpr int kRuns = 20; - static constexpr double kPFail = 0.02; - const double p = - absl::random_internal::RequiredSuccessProbability(kPFail, kRuns); - static constexpr int kSampleCount = 10000; - static constexpr int kBucketCount = 100; - int failed = 0; - for (int i = 0; i < kRuns; ++i) { - if (!SingleZTestOnMeanAndVariance<absl::beta_distribution<double>>( - p, kSampleCount)) { - failed++; - } - if (!SingleChiSquaredTest<absl::beta_distribution<double>>( - 0.005, kSampleCount, kBucketCount)) { - failed++; - } - } - // Set so that the test is not flaky at --runs_per_test=10000 - EXPECT_LE(failed, 5); -} - -std::string ParamName( - const ::testing::TestParamInfo<::testing::tuple<double, double>>& info) { - std::string name = absl::StrCat("alpha_", ::testing::get<0>(info.param), - "__beta_", ::testing::get<1>(info.param)); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_CASE_P( - TestSampleStatisticsCombinations, BetaDistributionTest, - ::testing::Combine(::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4), - ::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4)), - ParamName); - -INSTANTIATE_TEST_CASE_P( - TestSampleStatistics_SelectedPairs, BetaDistributionTest, - ::testing::Values(std::make_pair(0.5, 1000), std::make_pair(1000, 0.5), - std::make_pair(900, 1000), std::make_pair(10000, 20000), - std::make_pair(4e5, 2e7), std::make_pair(1e7, 1e5)), - ParamName); - -// NOTE: absl::beta_distribution is not guaranteed to be stable. -TEST(BetaDistributionTest, StabilityTest) { - // absl::beta_distribution stability relies on the stability of - // absl::random_interna::RandU64ToDouble, std::exp, std::log, std::pow, - // and std::sqrt. - // - // This test also depends on the stability of std::frexp. - using testing::ElementsAre; - absl::random_internal::sequence_urbg urbg({ - 0xffff00000000e6c8ull, 0xffff0000000006c8ull, 0x800003766295CFA9ull, - 0x11C819684E734A41ull, 0x832603766295CFA9ull, 0x7fbe76c8b4395800ull, - 0xB3472DCA7B14A94Aull, 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, - 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, 0x00035C904C70A239ull, - 0x00009E0BCBAADE14ull, 0x0000000000622CA7ull, 0x4864f22c059bf29eull, - 0x247856d8b862665cull, 0xe46e86e9a1337e10ull, 0xd8c8541f3519b133ull, - 0xffe75b52c567b9e4ull, 0xfffff732e5709c5bull, 0xff1f7f0b983532acull, - 0x1ec2e8986d2362caull, 0xC332DDEFBE6C5AA5ull, 0x6558218568AB9702ull, - 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, 0xECDD4775619F1510ull, - 0x814c8e35fe9a961aull, 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, - 0x1224e62c978bbc7full, 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, - 0x1bbc23cfa8fac721ull, 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, - 0x836d794457c08849ull, 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, - 0xb12d74fdd718c8c5ull, 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, - 0x5738341045ba0d85ull, 0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull, - 0xffe6ea4d6edb0c73ull, 0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull, - 0xEAAD8E716B93D5A0ull, 0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull, - 0x8FF6E2FBF2122B64ull, 0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull, - 0xD1CFF191B3A8C1ADull, 0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull, - }); - - // Convert the real-valued result into a unit64 where we compare - // 5 (float) or 10 (double) decimal digits plus the base-2 exponent. - auto float_to_u64 = [](float d) { - int exp = 0; - auto f = std::frexp(d, &exp); - return (static_cast<uint64_t>(1e5 * f) * 10000) + std::abs(exp); - }; - auto double_to_u64 = [](double d) { - int exp = 0; - auto f = std::frexp(d, &exp); - return (static_cast<uint64_t>(1e10 * f) * 10000) + std::abs(exp); - }; - - std::vector<uint64_t> output(20); - { - // Algorithm Joehnk (float) - absl::beta_distribution<float> dist(0.1f, 0.2f); - std::generate(std::begin(output), std::end(output), - [&] { return float_to_u64(dist(urbg)); }); - EXPECT_EQ(44, urbg.invocations()); - EXPECT_THAT(output, // - testing::ElementsAre( - 998340000, 619030004, 500000001, 999990000, 996280000, - 500000001, 844740004, 847210001, 999970000, 872320000, - 585480007, 933280000, 869080042, 647670031, 528240004, - 969980004, 626050008, 915930002, 833440033, 878040015)); - } - - urbg.reset(); - { - // Algorithm Joehnk (double) - absl::beta_distribution<double> dist(0.1, 0.2); - std::generate(std::begin(output), std::end(output), - [&] { return double_to_u64(dist(urbg)); }); - EXPECT_EQ(44, urbg.invocations()); - EXPECT_THAT( - output, // - testing::ElementsAre( - 99834713000000, 61903356870004, 50000000000001, 99999721170000, - 99628374770000, 99999999990000, 84474397860004, 84721276240001, - 99997407490000, 87232528120000, 58548364780007, 93328932910000, - 86908237770042, 64767917930031, 52824581970004, 96998544140004, - 62605946270008, 91593604380002, 83345031740033, 87804397230015)); - } - - urbg.reset(); - { - // Algorithm Cheng 1 - absl::beta_distribution<double> dist(0.9, 2.0); - std::generate(std::begin(output), std::end(output), - [&] { return double_to_u64(dist(urbg)); }); - EXPECT_EQ(62, urbg.invocations()); - EXPECT_THAT( - output, // - testing::ElementsAre( - 62069004780001, 64433204450001, 53607416560000, 89644295430008, - 61434586310019, 55172615890002, 62187161490000, 56433684810003, - 80454622050005, 86418558710003, 92920514700001, 64645184680001, - 58549183380000, 84881283650005, 71078728590002, 69949694970000, - 73157461710001, 68592191300001, 70747623900000, 78584696930005)); - } - - urbg.reset(); - { - // Algorithm Cheng 2 - absl::beta_distribution<double> dist(1.5, 2.5); - std::generate(std::begin(output), std::end(output), - [&] { return double_to_u64(dist(urbg)); }); - EXPECT_EQ(54, urbg.invocations()); - EXPECT_THAT( - output, // - testing::ElementsAre( - 75000029250001, 76751482860001, 53264575220000, 69193133650005, - 78028324470013, 91573587560002, 59167523770000, 60658618560002, - 80075870540000, 94141320460004, 63196592770003, 78883906300002, - 96797992590001, 76907587800001, 56645167560000, 65408302280003, - 53401156320001, 64731238570000, 83065573750001, 79788333820001)); - } -} - -// This is an implementation-specific test. If any part of the implementation -// changes, then it is likely that this test will change as well. Also, if -// dependencies of the distribution change, such as RandU64ToDouble, then this -// is also likely to change. -TEST(BetaDistributionTest, AlgorithmBounds) { - { - absl::random_internal::sequence_urbg urbg( - {0x7fbe76c8b4395800ull, 0x8000000000000000ull}); - // u=0.499, v=0.5 - absl::beta_distribution<double> dist(1e-4, 1e-4); - double a = dist(urbg); - EXPECT_EQ(a, 2.0202860861567108529e-09); - EXPECT_EQ(2, urbg.invocations()); - } - - // Test that both the float & double algorithms appropriately reject the - // initial draw. - { - // 1/alpha = 1/beta = 2. - absl::beta_distribution<float> dist(0.5, 0.5); - - // first two outputs are close to 1.0 - epsilon, - // thus: (u ^ 2 + v ^ 2) > 1.0 - absl::random_internal::sequence_urbg urbg( - {0xffff00000006e6c8ull, 0xffff00000007c7c8ull, 0x800003766295CFA9ull, - 0x11C819684E734A41ull}); - { - double y = absl::beta_distribution<double>(0.5, 0.5)(urbg); - EXPECT_EQ(4, urbg.invocations()); - EXPECT_EQ(y, 0.9810668952633862) << y; - } - - // ...and: log(u) * a ~= log(v) * b ~= -0.02 - // thus z ~= -0.02 + log(1 + e(~0)) - // ~= -0.02 + 0.69 - // thus z > 0 - urbg.reset(); - { - float x = absl::beta_distribution<float>(0.5, 0.5)(urbg); - EXPECT_EQ(4, urbg.invocations()); - EXPECT_NEAR(0.98106688261032104, x, 0.0000005) << x << "f"; - } - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/bit_gen_ref.h b/third_party/abseil_cpp/absl/random/bit_gen_ref.h deleted file mode 100644 index 9555460fd491..000000000000 --- a/third_party/abseil_cpp/absl/random/bit_gen_ref.h +++ /dev/null @@ -1,181 +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: bit_gen_ref.h -// ----------------------------------------------------------------------------- -// -// This header defines a bit generator "reference" class, for use in interfaces -// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g. -// `std::mt19937`) bit generators. - -#ifndef ABSL_RANDOM_BIT_GEN_REF_H_ -#define ABSL_RANDOM_BIT_GEN_REF_H_ - -#include "absl/base/internal/fast_type_id.h" -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" -#include "absl/random/internal/distribution_caller.h" -#include "absl/random/internal/fast_uniform_bits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -template <typename URBG, typename = void, typename = void, typename = void> -struct is_urbg : std::false_type {}; - -template <typename URBG> -struct is_urbg< - URBG, - absl::enable_if_t<std::is_same< - typename URBG::result_type, - typename std::decay<decltype((URBG::min)())>::type>::value>, - absl::enable_if_t<std::is_same< - typename URBG::result_type, - typename std::decay<decltype((URBG::max)())>::type>::value>, - absl::enable_if_t<std::is_same< - typename URBG::result_type, - typename std::decay<decltype(std::declval<URBG>()())>::type>::value>> - : std::true_type {}; - -template <typename> -struct DistributionCaller; -class MockHelpers; - -} // namespace random_internal - -// ----------------------------------------------------------------------------- -// absl::BitGenRef -// ----------------------------------------------------------------------------- -// -// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic -// non-owning "reference" interface for use in place of any specific uniform -// random bit generator (URBG). This class may be used for both Abseil -// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g -// `std::mt19937`, `std::minstd_rand`) bit generators. -// -// Like other reference classes, `absl::BitGenRef` does not own the -// underlying bit generator, and the underlying instance must outlive the -// `absl::BitGenRef`. -// -// `absl::BitGenRef` is particularly useful when used with an -// `absl::MockingBitGen` to test specific paths in functions which use random -// values. -// -// Example: -// void TakesBitGenRef(absl::BitGenRef gen) { -// int x = absl::Uniform<int>(gen, 0, 1000); -// } -// -class BitGenRef { - // SFINAE to detect whether the URBG type includes a member matching - // bool InvokeMock(base_internal::FastTypeIdType, void*, void*). - // - // These live inside BitGenRef so that they have friend access - // to MockingBitGen. (see similar methods in DistributionCaller). - template <template <class...> class Trait, class AlwaysVoid, class... Args> - struct detector : std::false_type {}; - template <template <class...> class Trait, class... Args> - struct detector<Trait, absl::void_t<Trait<Args...>>, Args...> - : std::true_type {}; - - template <class T> - using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock( - std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(), - std::declval<void*>())); - - template <typename T> - using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type; - - public: - BitGenRef(const BitGenRef&) = default; - BitGenRef(BitGenRef&&) = default; - BitGenRef& operator=(const BitGenRef&) = default; - BitGenRef& operator=(BitGenRef&&) = default; - - template <typename URBG, typename absl::enable_if_t< - (!std::is_same<URBG, BitGenRef>::value && - random_internal::is_urbg<URBG>::value && - !HasInvokeMock<URBG>::value)>* = nullptr> - BitGenRef(URBG& gen) // NOLINT - : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)), - mock_call_(NotAMock), - generate_impl_fn_(ImplFn<URBG>) {} - - template <typename URBG, - typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value && - random_internal::is_urbg<URBG>::value && - HasInvokeMock<URBG>::value)>* = nullptr> - BitGenRef(URBG& gen) // NOLINT - : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)), - mock_call_(&MockCall<URBG>), - generate_impl_fn_(ImplFn<URBG>) {} - - using result_type = uint64_t; - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); } - - private: - using impl_fn = result_type (*)(uintptr_t); - using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*, - void*); - - template <typename URBG> - static result_type ImplFn(uintptr_t ptr) { - // Ensure that the return values from operator() fill the entire - // range promised by result_type, min() and max(). - absl::random_internal::FastUniformBits<result_type> fast_uniform_bits; - return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr)); - } - - // Get a type-erased InvokeMock pointer. - template <typename URBG> - static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type, - void* result, void* arg_tuple) { - return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result, - arg_tuple); - } - static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) { - return false; - } - - inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple, - void* result) { - if (mock_call_ == NotAMock) return false; // avoids an indirect call. - return mock_call_(t_erased_gen_ptr_, type, args_tuple, result); - } - - uintptr_t t_erased_gen_ptr_; - mock_call_fn mock_call_; - impl_fn generate_impl_fn_; - - template <typename> - friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock - friend class ::absl::random_internal::MockHelpers; // for InvokeMock -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_BIT_GEN_REF_H_ diff --git a/third_party/abseil_cpp/absl/random/bit_gen_ref_test.cc b/third_party/abseil_cpp/absl/random/bit_gen_ref_test.cc deleted file mode 100644 index 1135cf2da0bf..000000000000 --- a/third_party/abseil_cpp/absl/random/bit_gen_ref_test.cc +++ /dev/null @@ -1,102 +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/random/bit_gen_ref.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/fast_type_id.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class ConstBitGen { - public: - // URBG interface - using result_type = absl::BitGen::result_type; - - static constexpr result_type(min)() { return (absl::BitGen::min)(); } - static constexpr result_type(max)() { return (absl::BitGen::max)(); } - result_type operator()() { return 1; } - - // InvokeMock method - bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) { - *static_cast<int*>(result) = 42; - return true; - } -}; - -namespace { - -int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); } - -template <typename T> -class BitGenRefTest : public testing::Test {}; - -using BitGenTypes = - ::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937, - std::mt19937_64, std::minstd_rand>; -TYPED_TEST_SUITE(BitGenRefTest, BitGenTypes); - -TYPED_TEST(BitGenRefTest, BasicTest) { - TypeParam gen; - auto x = FnTest(gen); - EXPECT_NEAR(x, 4, 3); -} - -TYPED_TEST(BitGenRefTest, Copyable) { - TypeParam gen; - absl::BitGenRef gen_ref(gen); - FnTest(gen_ref); // Copy -} - -TEST(BitGenRefTest, PassThroughEquivalence) { - // sequence_urbg returns 64-bit results. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<uint64_t> output(12); - - { - absl::BitGenRef view(urbg); - for (auto& v : output) { - v = view(); - } - } - - std::vector<uint64_t> expected( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - EXPECT_THAT(output, testing::Eq(expected)); -} - -TEST(BitGenRefTest, MockingBitGenBaseOverrides) { - ConstBitGen const_gen; - EXPECT_EQ(FnTest(const_gen), 42); - - absl::BitGenRef gen_ref(const_gen); - EXPECT_EQ(FnTest(gen_ref), 42); // Copy -} -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/discrete_distribution.cc b/third_party/abseil_cpp/absl/random/discrete_distribution.cc deleted file mode 100644 index 081accee52a4..000000000000 --- a/third_party/abseil_cpp/absl/random/discrete_distribution.cc +++ /dev/null @@ -1,98 +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/discrete_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Initializes the distribution table for Walker's Aliasing algorithm, described -// in Knuth, Vol 2. as well as in https://en.wikipedia.org/wiki/Alias_method -std::vector<std::pair<double, size_t>> InitDiscreteDistribution( - std::vector<double>* probabilities) { - // The empty-case should already be handled by the constructor. - assert(probabilities); - assert(!probabilities->empty()); - - // Step 1. Normalize the input probabilities to 1.0. - double sum = std::accumulate(std::begin(*probabilities), - std::end(*probabilities), 0.0); - if (std::fabs(sum - 1.0) > 1e-6) { - // Scale `probabilities` only when the sum is too far from 1.0. Scaling - // unconditionally will alter the probabilities slightly. - for (double& item : *probabilities) { - item = item / sum; - } - } - - // Step 2. At this point `probabilities` is set to the conditional - // probabilities of each element which sum to 1.0, to within reasonable error. - // These values are used to construct the proportional probability tables for - // the selection phases of Walker's Aliasing algorithm. - // - // To construct the table, pick an element which is under-full (i.e., an - // element for which `(*probabilities)[i] < 1.0/n`), and pair it with an - // element which is over-full (i.e., an element for which - // `(*probabilities)[i] > 1.0/n`). The smaller value can always be retired. - // The larger may still be greater than 1.0/n, or may now be less than 1.0/n, - // and put back onto the appropriate collection. - const size_t n = probabilities->size(); - std::vector<std::pair<double, size_t>> q; - q.reserve(n); - - std::vector<size_t> over; - std::vector<size_t> under; - size_t idx = 0; - for (const double item : *probabilities) { - assert(item >= 0); - const double v = item * n; - q.emplace_back(v, 0); - if (v < 1.0) { - under.push_back(idx++); - } else { - over.push_back(idx++); - } - } - while (!over.empty() && !under.empty()) { - auto lo = under.back(); - under.pop_back(); - auto hi = over.back(); - over.pop_back(); - - q[lo].second = hi; - const double r = q[hi].first - (1.0 - q[lo].first); - q[hi].first = r; - if (r < 1.0) { - under.push_back(hi); - } else { - over.push_back(hi); - } - } - - // Due to rounding errors, there may be un-paired elements in either - // collection; these should all be values near 1.0. For these values, set `q` - // to 1.0 and set the alternate to the identity. - for (auto i : over) { - q[i] = {1.0, i}; - } - for (auto i : under) { - q[i] = {1.0, i}; - } - return q; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/discrete_distribution.h b/third_party/abseil_cpp/absl/random/discrete_distribution.h deleted file mode 100644 index 171aa11a1eb4..000000000000 --- a/third_party/abseil_cpp/absl/random/discrete_distribution.h +++ /dev/null @@ -1,247 +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. - -#ifndef ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_ -#define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <numeric> -#include <type_traits> -#include <utility> -#include <vector> - -#include "absl/random/bernoulli_distribution.h" -#include "absl/random/internal/iostream_state_saver.h" -#include "absl/random/uniform_int_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::discrete_distribution -// -// A discrete distribution produces random integers i, where 0 <= i < n -// distributed according to the discrete probability function: -// -// P(i|p0,...,pn−1)=pi -// -// This class is an implementation of discrete_distribution (see -// [rand.dist.samp.discrete]). -// -// The algorithm used is Walker's Aliasing algorithm, described in Knuth, Vol 2. -// absl::discrete_distribution takes O(N) time to precompute the probabilities -// (where N is the number of possible outcomes in the distribution) at -// construction, and then takes O(1) time for each variate generation. Many -// other implementations also take O(N) time to construct an ordered sequence of -// partial sums, plus O(log N) time per variate to binary search. -// -template <typename IntType = int> -class discrete_distribution { - public: - using result_type = IntType; - - class param_type { - public: - using distribution_type = discrete_distribution; - - param_type() { init(); } - - template <typename InputIterator> - explicit param_type(InputIterator begin, InputIterator end) - : p_(begin, end) { - init(); - } - - explicit param_type(std::initializer_list<double> weights) : p_(weights) { - init(); - } - - template <class UnaryOperation> - explicit param_type(size_t nw, double xmin, double xmax, - UnaryOperation fw) { - if (nw > 0) { - p_.reserve(nw); - double delta = (xmax - xmin) / static_cast<double>(nw); - assert(delta > 0); - double t = delta * 0.5; - for (size_t i = 0; i < nw; ++i) { - p_.push_back(fw(xmin + i * delta + t)); - } - } - init(); - } - - const std::vector<double>& probabilities() const { return p_; } - size_t n() const { return p_.size() - 1; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.probabilities() == b.probabilities(); - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class discrete_distribution; - - void init(); - - std::vector<double> p_; // normalized probabilities - std::vector<std::pair<double, size_t>> q_; // (acceptance, alternate) pairs - - static_assert(std::is_integral<result_type>::value, - "Class-template absl::discrete_distribution<> must be " - "parameterized using an integral type."); - }; - - discrete_distribution() : param_() {} - - explicit discrete_distribution(const param_type& p) : param_(p) {} - - template <typename InputIterator> - explicit discrete_distribution(InputIterator begin, InputIterator end) - : param_(begin, end) {} - - explicit discrete_distribution(std::initializer_list<double> weights) - : param_(weights) {} - - template <class UnaryOperation> - explicit discrete_distribution(size_t nw, double xmin, double xmax, - UnaryOperation fw) - : param_(nw, xmin, xmax, std::move(fw)) {} - - void reset() {} - - // generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - const param_type& param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { return 0; } - result_type(max)() const { - return static_cast<result_type>(param_.n()); - } // inclusive - - // NOTE [rand.dist.sample.discrete] returns a std::vector<double> not a - // const std::vector<double>&. - const std::vector<double>& probabilities() const { - return param_.probabilities(); - } - - friend bool operator==(const discrete_distribution& a, - const discrete_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const discrete_distribution& a, - const discrete_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; -}; - -// -------------------------------------------------------------------------- -// Implementation details only below -// -------------------------------------------------------------------------- - -namespace random_internal { - -// Using the vector `*probabilities`, whose values are the weights or -// probabilities of an element being selected, constructs the proportional -// probabilities used by the discrete distribution. `*probabilities` will be -// scaled, if necessary, so that its entries sum to a value sufficiently close -// to 1.0. -std::vector<std::pair<double, size_t>> InitDiscreteDistribution( - std::vector<double>* probabilities); - -} // namespace random_internal - -template <typename IntType> -void discrete_distribution<IntType>::param_type::init() { - if (p_.empty()) { - p_.push_back(1.0); - q_.emplace_back(1.0, 0); - } else { - assert(n() <= (std::numeric_limits<IntType>::max)()); - q_ = random_internal::InitDiscreteDistribution(&p_); - } -} - -template <typename IntType> -template <typename URBG> -typename discrete_distribution<IntType>::result_type -discrete_distribution<IntType>::operator()( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - const auto idx = absl::uniform_int_distribution<result_type>(0, p.n())(g); - const auto& q = p.q_[idx]; - const bool selected = absl::bernoulli_distribution(q.first)(g); - return selected ? idx : static_cast<result_type>(q.second); -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const discrete_distribution<IntType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - const auto& probabilities = x.param().probabilities(); - os << probabilities.size(); - - os.precision(random_internal::stream_precision_helper<double>::kPrecision); - for (const auto& p : probabilities) { - os << os.fill() << p; - } - return os; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - discrete_distribution<IntType>& x) { // NOLINT(runtime/references) - using param_type = typename discrete_distribution<IntType>::param_type; - auto saver = random_internal::make_istream_state_saver(is); - - size_t n; - std::vector<double> p; - - is >> n; - if (is.fail()) return is; - if (n > 0) { - p.reserve(n); - for (IntType i = 0; i < n && !is.fail(); ++i) { - auto tmp = random_internal::read_floating_point<double>(is); - if (is.fail()) return is; - p.push_back(tmp); - } - } - x.param(param_type(p.begin(), p.end())); - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/discrete_distribution_test.cc b/third_party/abseil_cpp/absl/random/discrete_distribution_test.cc deleted file mode 100644 index 6d007006ef48..000000000000 --- a/third_party/abseil_cpp/absl/random/discrete_distribution_test.cc +++ /dev/null @@ -1,250 +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/discrete_distribution.h" - -#include <cmath> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <numeric> -#include <random> -#include <sstream> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/strip.h" - -namespace { - -template <typename IntType> -class DiscreteDistributionTypeTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, - uint32_t, int64_t, uint64_t>; -TYPED_TEST_SUITE(DiscreteDistributionTypeTest, IntTypes); - -TYPED_TEST(DiscreteDistributionTypeTest, ParamSerializeTest) { - using param_type = - typename absl::discrete_distribution<TypeParam>::param_type; - - absl::discrete_distribution<TypeParam> empty; - EXPECT_THAT(empty.probabilities(), testing::ElementsAre(1.0)); - - absl::discrete_distribution<TypeParam> before({1.0, 2.0, 1.0}); - - // Validate that the probabilities sum to 1.0. We picked values which - // can be represented exactly to avoid floating-point roundoff error. - double s = 0; - for (const auto& x : before.probabilities()) { - s += x; - } - EXPECT_EQ(s, 1.0); - EXPECT_THAT(before.probabilities(), testing::ElementsAre(0.25, 0.5, 0.25)); - - // Validate the same data via an initializer list. - { - std::vector<double> data({1.0, 2.0, 1.0}); - - absl::discrete_distribution<TypeParam> via_param{ - param_type(std::begin(data), std::end(data))}; - - EXPECT_EQ(via_param, before); - } - - std::stringstream ss; - ss << before; - absl::discrete_distribution<TypeParam> after; - - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before, after); -} - -TYPED_TEST(DiscreteDistributionTypeTest, Constructor) { - auto fn = [](double x) { return x; }; - { - absl::discrete_distribution<int> unary(0, 1.0, 9.0, fn); - EXPECT_THAT(unary.probabilities(), testing::ElementsAre(1.0)); - } - - { - absl::discrete_distribution<int> unary(2, 1.0, 9.0, fn); - // => fn(1.0 + 0 * 4 + 2) => 3 - // => fn(1.0 + 1 * 4 + 2) => 7 - EXPECT_THAT(unary.probabilities(), testing::ElementsAre(0.3, 0.7)); - } -} - -TEST(DiscreteDistributionTest, InitDiscreteDistribution) { - using testing::Pair; - - { - std::vector<double> p({1.0, 2.0, 3.0}); - std::vector<std::pair<double, size_t>> q = - absl::random_internal::InitDiscreteDistribution(&p); - - EXPECT_THAT(p, testing::ElementsAre(1 / 6.0, 2 / 6.0, 3 / 6.0)); - - // Each bucket is p=1/3, so bucket 0 will send half it's traffic - // to bucket 2, while the rest will retain all of their traffic. - EXPECT_THAT(q, testing::ElementsAre(Pair(0.5, 2), // - Pair(1.0, 1), // - Pair(1.0, 2))); - } - - { - std::vector<double> p({1.0, 2.0, 3.0, 5.0, 2.0}); - - std::vector<std::pair<double, size_t>> q = - absl::random_internal::InitDiscreteDistribution(&p); - - EXPECT_THAT(p, testing::ElementsAre(1 / 13.0, 2 / 13.0, 3 / 13.0, 5 / 13.0, - 2 / 13.0)); - - // A more complex bucketing solution: Each bucket has p=0.2 - // So buckets 0, 1, 4 will send their alternate traffic elsewhere, which - // happens to be bucket 3. - // However, summing up that alternate traffic gives bucket 3 too much - // traffic, so it will send some traffic to bucket 2. - constexpr double b0 = 1.0 / 13.0 / 0.2; - constexpr double b1 = 2.0 / 13.0 / 0.2; - constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1)); - - EXPECT_THAT(q, testing::ElementsAre(Pair(b0, 3), // - Pair(b1, 3), // - Pair(1.0, 2), // - Pair(b3, 2), // - Pair(b1, 3))); - } -} - -TEST(DiscreteDistributionTest, ChiSquaredTest50) { - using absl::random_internal::kChiSquared; - - constexpr size_t kTrials = 10000; - constexpr int kBuckets = 50; // inclusive, so actally +1 - - // 1-in-100000 threshold, but remember, there are about 8 tests - // in this file. And the test could fail for other reasons. - // Empirically validated with --runs_per_test=10000. - const int kThreshold = - absl::random_internal::ChiSquareValue(kBuckets, 0.99999); - - std::vector<double> weights(kBuckets, 0); - std::iota(std::begin(weights), std::end(weights), 1); - absl::discrete_distribution<int> dist(std::begin(weights), std::end(weights)); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6); - - std::vector<int32_t> counts(kBuckets, 0); - for (size_t i = 0; i < kTrials; i++) { - auto x = dist(rng); - counts[x]++; - } - - // Scale weights. - double sum = 0; - for (double x : weights) { - sum += x; - } - for (double& x : weights) { - x = kTrials * (x / sum); - } - - double chi_square = - absl::random_internal::ChiSquare(std::begin(counts), std::end(counts), - std::begin(weights), std::end(weights)); - - if (chi_square > kThreshold) { - double p_value = - absl::random_internal::ChiSquarePValue(chi_square, kBuckets); - - // Chi-squared test failed. Output does not appear to be uniform. - std::string msg; - for (size_t i = 0; i < counts.size(); i++) { - absl::StrAppend(&msg, i, ": ", counts[i], " vs ", weights[i], "\n"); - } - absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n"); - absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ", - kThreshold); - ABSL_RAW_LOG(INFO, "%s", msg.c_str()); - FAIL() << msg; - } -} - -TEST(DiscreteDistributionTest, StabilityTest) { - // absl::discrete_distribution stabilitiy relies on - // absl::uniform_int_distribution and absl::bernoulli_distribution. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(6); - - { - absl::discrete_distribution<int32_t> dist({1.0, 2.0, 3.0, 5.0, 2.0}); - EXPECT_EQ(0, dist.min()); - EXPECT_EQ(4, dist.max()); - for (auto& v : output) { - v = dist(urbg); - } - EXPECT_EQ(12, urbg.invocations()); - } - - // With 12 calls to urbg, each call into discrete_distribution consumes - // precisely 2 values: one for the uniform call, and a second for the - // bernoulli. - // - // Given the alt mapping: 0=>3, 1=>3, 2=>2, 3=>2, 4=>3, we can - // - // uniform: 443210143131 - // bernoulli: b0 000011100101 - // bernoulli: b1 001111101101 - // bernoulli: b2 111111111111 - // bernoulli: b3 001111101111 - // bernoulli: b4 001111101101 - // ... - EXPECT_THAT(output, testing::ElementsAre(3, 3, 1, 3, 3, 3)); - - { - urbg.reset(); - absl::discrete_distribution<int64_t> dist({1.0, 2.0, 3.0, 5.0, 2.0}); - EXPECT_EQ(0, dist.min()); - EXPECT_EQ(4, dist.max()); - for (auto& v : output) { - v = dist(urbg); - } - EXPECT_EQ(12, urbg.invocations()); - } - EXPECT_THAT(output, testing::ElementsAre(3, 3, 0, 3, 0, 4)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/distributions.h b/third_party/abseil_cpp/absl/random/distributions.h deleted file mode 100644 index 31c79694e51b..000000000000 --- a/third_party/abseil_cpp/absl/random/distributions.h +++ /dev/null @@ -1,452 +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. -// -// ----------------------------------------------------------------------------- -// File: distributions.h -// ----------------------------------------------------------------------------- -// -// This header defines functions representing distributions, which you use in -// combination with an Abseil random bit generator to produce random values -// according to the rules of that distribution. -// -// The Abseil random library defines the following distributions within this -// file: -// -// * `absl::Uniform` for uniform (constant) distributions having constant -// probability -// * `absl::Bernoulli` for discrete distributions having exactly two outcomes -// * `absl::Beta` for continuous distributions parameterized through two -// free parameters -// * `absl::Exponential` for discrete distributions of events occurring -// continuously and independently at a constant average rate -// * `absl::Gaussian` (also known as "normal distributions") for continuous -// distributions using an associated quadratic function -// * `absl::LogUniform` for continuous uniform distributions where the log -// to the given base of all values is uniform -// * `absl::Poisson` for discrete probability distributions that express the -// probability of a given number of events occurring within a fixed interval -// * `absl::Zipf` for discrete probability distributions commonly used for -// modelling of rare events -// -// Prefer use of these distribution function classes over manual construction of -// your own distribution classes, as it allows library maintainers greater -// flexibility to change the underlying implementation in the future. - -#ifndef ABSL_RANDOM_DISTRIBUTIONS_H_ -#define ABSL_RANDOM_DISTRIBUTIONS_H_ - -#include <algorithm> -#include <cmath> -#include <limits> -#include <random> -#include <type_traits> - -#include "absl/base/internal/inline_variable.h" -#include "absl/random/bernoulli_distribution.h" -#include "absl/random/beta_distribution.h" -#include "absl/random/exponential_distribution.h" -#include "absl/random/gaussian_distribution.h" -#include "absl/random/internal/distribution_caller.h" // IWYU pragma: export -#include "absl/random/internal/uniform_helper.h" // IWYU pragma: export -#include "absl/random/log_uniform_int_distribution.h" -#include "absl/random/poisson_distribution.h" -#include "absl/random/uniform_int_distribution.h" -#include "absl/random/uniform_real_distribution.h" -#include "absl/random/zipf_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed, - {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {}); -ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {}); - -// ----------------------------------------------------------------------------- -// absl::Uniform<T>(tag, bitgen, lo, hi) -// ----------------------------------------------------------------------------- -// -// `absl::Uniform()` produces random values of type `T` uniformly distributed in -// a defined interval {lo, hi}. The interval `tag` defines the type of interval -// which should be one of the following possible values: -// -// * `absl::IntervalOpenOpen` -// * `absl::IntervalOpenClosed` -// * `absl::IntervalClosedOpen` -// * `absl::IntervalClosedClosed` -// -// where "open" refers to an exclusive value (excluded) from the output, while -// "closed" refers to an inclusive value (included) from the output. -// -// In the absence of an explicit return type `T`, `absl::Uniform()` will deduce -// the return type based on the provided endpoint arguments {A lo, B hi}. -// Given these endpoints, one of {A, B} will be chosen as the return type, if -// a type can be implicitly converted into the other in a lossless way. The -// lack of any such implicit conversion between {A, B} will produce a -// compile-time error -// -// See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous) -// -// Example: -// -// absl::BitGen bitgen; -// -// // Produce a random float value between 0.0 and 1.0, inclusive -// auto x = absl::Uniform(absl::IntervalClosedClosed, bitgen, 0.0f, 1.0f); -// -// // The most common interval of `absl::IntervalClosedOpen` is available by -// // default: -// -// auto x = absl::Uniform(bitgen, 0.0f, 1.0f); -// -// // Return-types are typically inferred from the arguments, however callers -// // can optionally provide an explicit return-type to the template. -// -// auto x = absl::Uniform<float>(bitgen, 0, 1); -// -template <typename R = void, typename TagType, typename URBG> -typename absl::enable_if_t<!std::is_same<R, void>::value, R> // -Uniform(TagType tag, - URBG&& urbg, // NOLINT(runtime/references) - R lo, R hi) { - using gen_t = absl::decay_t<URBG>; - using distribution_t = random_internal::UniformDistributionWrapper<R>; - - auto a = random_internal::uniform_lower_bound(tag, lo, hi); - auto b = random_internal::uniform_upper_bound(tag, lo, hi); - if (!random_internal::is_uniform_range_valid(a, b)) return lo; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, tag, lo, hi); -} - -// absl::Uniform<T>(bitgen, lo, hi) -// -// Overload of `Uniform()` using the default closed-open interval of [lo, hi), -// and returning values of type `T` -template <typename R = void, typename URBG> -typename absl::enable_if_t<!std::is_same<R, void>::value, R> // -Uniform(URBG&& urbg, // NOLINT(runtime/references) - R lo, R hi) { - using gen_t = absl::decay_t<URBG>; - using distribution_t = random_internal::UniformDistributionWrapper<R>; - constexpr auto tag = absl::IntervalClosedOpen; - - auto a = random_internal::uniform_lower_bound(tag, lo, hi); - auto b = random_internal::uniform_upper_bound(tag, lo, hi); - if (!random_internal::is_uniform_range_valid(a, b)) return lo; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, lo, hi); -} - -// absl::Uniform(tag, bitgen, lo, hi) -// -// Overload of `Uniform()` using different (but compatible) lo, hi types. Note -// that a compile-error will result if the return type cannot be deduced -// correctly from the passed types. -template <typename R = void, typename TagType, typename URBG, typename A, - typename B> -typename absl::enable_if_t<std::is_same<R, void>::value, - random_internal::uniform_inferred_return_t<A, B>> -Uniform(TagType tag, - URBG&& urbg, // NOLINT(runtime/references) - A lo, B hi) { - using gen_t = absl::decay_t<URBG>; - using return_t = typename random_internal::uniform_inferred_return_t<A, B>; - using distribution_t = random_internal::UniformDistributionWrapper<return_t>; - - auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi); - auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi); - if (!random_internal::is_uniform_range_valid(a, b)) return lo; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, tag, static_cast<return_t>(lo), - static_cast<return_t>(hi)); -} - -// absl::Uniform(bitgen, lo, hi) -// -// Overload of `Uniform()` using different (but compatible) lo, hi types and the -// default closed-open interval of [lo, hi). Note that a compile-error will -// result if the return type cannot be deduced correctly from the passed types. -template <typename R = void, typename URBG, typename A, typename B> -typename absl::enable_if_t<std::is_same<R, void>::value, - random_internal::uniform_inferred_return_t<A, B>> -Uniform(URBG&& urbg, // NOLINT(runtime/references) - A lo, B hi) { - using gen_t = absl::decay_t<URBG>; - using return_t = typename random_internal::uniform_inferred_return_t<A, B>; - using distribution_t = random_internal::UniformDistributionWrapper<return_t>; - - constexpr auto tag = absl::IntervalClosedOpen; - auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi); - auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi); - if (!random_internal::is_uniform_range_valid(a, b)) return lo; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, static_cast<return_t>(lo), - static_cast<return_t>(hi)); -} - -// absl::Uniform<unsigned T>(bitgen) -// -// Overload of Uniform() using the minimum and maximum values of a given type -// `T` (which must be unsigned), returning a value of type `unsigned T` -template <typename R, typename URBG> -typename absl::enable_if_t<!std::is_signed<R>::value, R> // -Uniform(URBG&& urbg) { // NOLINT(runtime/references) - using gen_t = absl::decay_t<URBG>; - using distribution_t = random_internal::UniformDistributionWrapper<R>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg); -} - -// ----------------------------------------------------------------------------- -// absl::Bernoulli(bitgen, p) -// ----------------------------------------------------------------------------- -// -// `absl::Bernoulli` produces a random boolean value, with probability `p` -// (where 0.0 <= p <= 1.0) equaling `true`. -// -// Prefer `absl::Bernoulli` to produce boolean values over other alternatives -// such as comparing an `absl::Uniform()` value to a specific output. -// -// See https://en.wikipedia.org/wiki/Bernoulli_distribution -// -// Example: -// -// absl::BitGen bitgen; -// ... -// if (absl::Bernoulli(bitgen, 1.0/3721.0)) { -// std::cout << "Asteroid field navigation successful."; -// } -// -template <typename URBG> -bool Bernoulli(URBG&& urbg, // NOLINT(runtime/references) - double p) { - using gen_t = absl::decay_t<URBG>; - using distribution_t = absl::bernoulli_distribution; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, p); -} - -// ----------------------------------------------------------------------------- -// absl::Beta<T>(bitgen, alpha, beta) -// ----------------------------------------------------------------------------- -// -// `absl::Beta` produces a floating point number distributed in the closed -// interval [0,1] and parameterized by two values `alpha` and `beta` as per a -// Beta distribution. `T` must be a floating point type, but may be inferred -// from the types of `alpha` and `beta`. -// -// See https://en.wikipedia.org/wiki/Beta_distribution. -// -// Example: -// -// absl::BitGen bitgen; -// ... -// double sample = absl::Beta(bitgen, 3.0, 2.0); -// -template <typename RealType, typename URBG> -RealType Beta(URBG&& urbg, // NOLINT(runtime/references) - RealType alpha, RealType beta) { - static_assert( - std::is_floating_point<RealType>::value, - "Template-argument 'RealType' must be a floating-point type, in " - "absl::Beta<RealType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::beta_distribution<RealType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, alpha, beta); -} - -// ----------------------------------------------------------------------------- -// absl::Exponential<T>(bitgen, lambda = 1) -// ----------------------------------------------------------------------------- -// -// `absl::Exponential` produces a floating point number representing the -// distance (time) between two consecutive events in a point process of events -// occurring continuously and independently at a constant average rate. `T` must -// be a floating point type, but may be inferred from the type of `lambda`. -// -// See https://en.wikipedia.org/wiki/Exponential_distribution. -// -// Example: -// -// absl::BitGen bitgen; -// ... -// double call_length = absl::Exponential(bitgen, 7.0); -// -template <typename RealType, typename URBG> -RealType Exponential(URBG&& urbg, // NOLINT(runtime/references) - RealType lambda = 1) { - static_assert( - std::is_floating_point<RealType>::value, - "Template-argument 'RealType' must be a floating-point type, in " - "absl::Exponential<RealType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::exponential_distribution<RealType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, lambda); -} - -// ----------------------------------------------------------------------------- -// absl::Gaussian<T>(bitgen, mean = 0, stddev = 1) -// ----------------------------------------------------------------------------- -// -// `absl::Gaussian` produces a floating point number selected from the Gaussian -// (ie. "Normal") distribution. `T` must be a floating point type, but may be -// inferred from the types of `mean` and `stddev`. -// -// See https://en.wikipedia.org/wiki/Normal_distribution -// -// Example: -// -// absl::BitGen bitgen; -// ... -// double giraffe_height = absl::Gaussian(bitgen, 16.3, 3.3); -// -template <typename RealType, typename URBG> -RealType Gaussian(URBG&& urbg, // NOLINT(runtime/references) - RealType mean = 0, RealType stddev = 1) { - static_assert( - std::is_floating_point<RealType>::value, - "Template-argument 'RealType' must be a floating-point type, in " - "absl::Gaussian<RealType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::gaussian_distribution<RealType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, mean, stddev); -} - -// ----------------------------------------------------------------------------- -// absl::LogUniform<T>(bitgen, lo, hi, base = 2) -// ----------------------------------------------------------------------------- -// -// `absl::LogUniform` produces random values distributed where the log to a -// given base of all values is uniform in a closed interval [lo, hi]. `T` must -// be an integral type, but may be inferred from the types of `lo` and `hi`. -// -// I.e., `LogUniform(0, n, b)` is uniformly distributed across buckets -// [0], [1, b-1], [b, b^2-1] .. [b^(k-1), (b^k)-1] .. [b^floor(log(n, b)), n] -// and is uniformly distributed within each bucket. -// -// The resulting probability density is inversely related to bucket size, though -// values in the final bucket may be more likely than previous values. (In the -// extreme case where n = b^i the final value will be tied with zero as the most -// probable result. -// -// If `lo` is nonzero then this distribution is shifted to the desired interval, -// so LogUniform(lo, hi, b) is equivalent to LogUniform(0, hi-lo, b)+lo. -// -// See http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution -// -// Example: -// -// absl::BitGen bitgen; -// ... -// int v = absl::LogUniform(bitgen, 0, 1000); -// -template <typename IntType, typename URBG> -IntType LogUniform(URBG&& urbg, // NOLINT(runtime/references) - IntType lo, IntType hi, IntType base = 2) { - static_assert(std::is_integral<IntType>::value, - "Template-argument 'IntType' must be an integral type, in " - "absl::LogUniform<IntType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::log_uniform_int_distribution<IntType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, lo, hi, base); -} - -// ----------------------------------------------------------------------------- -// absl::Poisson<T>(bitgen, mean = 1) -// ----------------------------------------------------------------------------- -// -// `absl::Poisson` produces discrete probabilities for a given number of events -// occurring within a fixed interval within the closed interval [0, max]. `T` -// must be an integral type. -// -// See https://en.wikipedia.org/wiki/Poisson_distribution -// -// Example: -// -// absl::BitGen bitgen; -// ... -// int requests_per_minute = absl::Poisson<int>(bitgen, 3.2); -// -template <typename IntType, typename URBG> -IntType Poisson(URBG&& urbg, // NOLINT(runtime/references) - double mean = 1.0) { - static_assert(std::is_integral<IntType>::value, - "Template-argument 'IntType' must be an integral type, in " - "absl::Poisson<IntType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::poisson_distribution<IntType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, mean); -} - -// ----------------------------------------------------------------------------- -// absl::Zipf<T>(bitgen, hi = max, q = 2, v = 1) -// ----------------------------------------------------------------------------- -// -// `absl::Zipf` produces discrete probabilities commonly used for modelling of -// rare events over the closed interval [0, hi]. The parameters `v` and `q` -// determine the skew of the distribution. `T` must be an integral type, but -// may be inferred from the type of `hi`. -// -// See http://mathworld.wolfram.com/ZipfDistribution.html -// -// Example: -// -// absl::BitGen bitgen; -// ... -// int term_rank = absl::Zipf<int>(bitgen); -// -template <typename IntType, typename URBG> -IntType Zipf(URBG&& urbg, // NOLINT(runtime/references) - IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0, - double v = 1.0) { - static_assert(std::is_integral<IntType>::value, - "Template-argument 'IntType' must be an integral type, in " - "absl::Zipf<IntType, URBG>(...)"); - - using gen_t = absl::decay_t<URBG>; - using distribution_t = typename absl::zipf_distribution<IntType>; - - return random_internal::DistributionCaller<gen_t>::template Call< - distribution_t>(&urbg, hi, q, v); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_DISTRIBUTIONS_H_ diff --git a/third_party/abseil_cpp/absl/random/distributions_test.cc b/third_party/abseil_cpp/absl/random/distributions_test.cc deleted file mode 100644 index 5866a07257e5..000000000000 --- a/third_party/abseil_cpp/absl/random/distributions_test.cc +++ /dev/null @@ -1,455 +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/distributions.h" - -#include <cmath> -#include <cstdint> -#include <random> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/random.h" - -namespace { - -constexpr int kSize = 400000; - -class RandomDistributionsTest : public testing::Test {}; - - -struct Invalid {}; - -template <typename A, typename B> -auto InferredUniformReturnT(int) - -> decltype(absl::Uniform(std::declval<absl::InsecureBitGen&>(), - std::declval<A>(), std::declval<B>())); - -template <typename, typename> -Invalid InferredUniformReturnT(...); - -template <typename TagType, typename A, typename B> -auto InferredTaggedUniformReturnT(int) - -> decltype(absl::Uniform(std::declval<TagType>(), - std::declval<absl::InsecureBitGen&>(), - std::declval<A>(), std::declval<B>())); - -template <typename, typename, typename> -Invalid InferredTaggedUniformReturnT(...); - -// Given types <A, B, Expect>, CheckArgsInferType() verifies that -// -// absl::Uniform(gen, A{}, B{}) -// -// returns the type "Expect". -// -// This interface can also be used to assert that a given absl::Uniform() -// overload does not exist / will not compile. Given types <A, B>, the -// expression -// -// decltype(absl::Uniform(..., std::declval<A>(), std::declval<B>())) -// -// will not compile, leaving the definition of InferredUniformReturnT<A, B> to -// resolve (via SFINAE) to the overload which returns type "Invalid". This -// allows tests to assert that an invocation such as -// -// absl::Uniform(gen, 1.23f, std::numeric_limits<int>::max() - 1) -// -// should not compile, since neither type, float nor int, can precisely -// represent both endpoint-values. Writing: -// -// CheckArgsInferType<float, int, Invalid>() -// -// will assert that this overload does not exist. -template <typename A, typename B, typename Expect> -void CheckArgsInferType() { - static_assert( - absl::conjunction< - std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>, - std::is_same<Expect, - decltype(InferredUniformReturnT<B, A>(0))>>::value, - ""); - static_assert( - absl::conjunction< - std::is_same<Expect, decltype(InferredTaggedUniformReturnT< - absl::IntervalOpenOpenTag, A, B>(0))>, - std::is_same<Expect, - decltype(InferredTaggedUniformReturnT< - absl::IntervalOpenOpenTag, B, A>(0))>>::value, - ""); -} - -template <typename A, typename B, typename ExplicitRet> -auto ExplicitUniformReturnT(int) -> decltype( - absl::Uniform<ExplicitRet>(*std::declval<absl::InsecureBitGen*>(), - std::declval<A>(), std::declval<B>())); - -template <typename, typename, typename ExplicitRet> -Invalid ExplicitUniformReturnT(...); - -template <typename TagType, typename A, typename B, typename ExplicitRet> -auto ExplicitTaggedUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>( - std::declval<TagType>(), *std::declval<absl::InsecureBitGen*>(), - std::declval<A>(), std::declval<B>())); - -template <typename, typename, typename, typename ExplicitRet> -Invalid ExplicitTaggedUniformReturnT(...); - -// Given types <A, B, Expect>, CheckArgsReturnExpectedType() verifies that -// -// absl::Uniform<Expect>(gen, A{}, B{}) -// -// returns the type "Expect", and that the function-overload has the signature -// -// Expect(URBG&, Expect, Expect) -template <typename A, typename B, typename Expect> -void CheckArgsReturnExpectedType() { - static_assert( - absl::conjunction< - std::is_same<Expect, - decltype(ExplicitUniformReturnT<A, B, Expect>(0))>, - std::is_same<Expect, decltype(ExplicitUniformReturnT<B, A, Expect>( - 0))>>::value, - ""); - static_assert( - absl::conjunction< - std::is_same<Expect, - decltype(ExplicitTaggedUniformReturnT< - absl::IntervalOpenOpenTag, A, B, Expect>(0))>, - std::is_same<Expect, decltype(ExplicitTaggedUniformReturnT< - absl::IntervalOpenOpenTag, B, A, - Expect>(0))>>::value, - ""); -} - -TEST_F(RandomDistributionsTest, UniformTypeInference) { - // Infers common types. - CheckArgsInferType<uint16_t, uint16_t, uint16_t>(); - CheckArgsInferType<uint32_t, uint32_t, uint32_t>(); - CheckArgsInferType<uint64_t, uint64_t, uint64_t>(); - CheckArgsInferType<int16_t, int16_t, int16_t>(); - CheckArgsInferType<int32_t, int32_t, int32_t>(); - CheckArgsInferType<int64_t, int64_t, int64_t>(); - CheckArgsInferType<float, float, float>(); - CheckArgsInferType<double, double, double>(); - - // Explicitly-specified return-values override inferences. - CheckArgsReturnExpectedType<int16_t, int16_t, int32_t>(); - CheckArgsReturnExpectedType<uint16_t, uint16_t, int32_t>(); - CheckArgsReturnExpectedType<int16_t, int16_t, int64_t>(); - CheckArgsReturnExpectedType<int16_t, int32_t, int64_t>(); - CheckArgsReturnExpectedType<int16_t, int32_t, double>(); - CheckArgsReturnExpectedType<float, float, double>(); - CheckArgsReturnExpectedType<int, int, int16_t>(); - - // Properly promotes uint16_t. - CheckArgsInferType<uint16_t, uint32_t, uint32_t>(); - CheckArgsInferType<uint16_t, uint64_t, uint64_t>(); - CheckArgsInferType<uint16_t, int32_t, int32_t>(); - CheckArgsInferType<uint16_t, int64_t, int64_t>(); - CheckArgsInferType<uint16_t, float, float>(); - CheckArgsInferType<uint16_t, double, double>(); - - // Properly promotes int16_t. - CheckArgsInferType<int16_t, int32_t, int32_t>(); - CheckArgsInferType<int16_t, int64_t, int64_t>(); - CheckArgsInferType<int16_t, float, float>(); - CheckArgsInferType<int16_t, double, double>(); - - // Invalid (u)int16_t-pairings do not compile. - // See "CheckArgsInferType" comments above, for how this is achieved. - CheckArgsInferType<uint16_t, int16_t, Invalid>(); - CheckArgsInferType<int16_t, uint32_t, Invalid>(); - CheckArgsInferType<int16_t, uint64_t, Invalid>(); - - // Properly promotes uint32_t. - CheckArgsInferType<uint32_t, uint64_t, uint64_t>(); - CheckArgsInferType<uint32_t, int64_t, int64_t>(); - CheckArgsInferType<uint32_t, double, double>(); - - // Properly promotes int32_t. - CheckArgsInferType<int32_t, int64_t, int64_t>(); - CheckArgsInferType<int32_t, double, double>(); - - // Invalid (u)int32_t-pairings do not compile. - CheckArgsInferType<uint32_t, int32_t, Invalid>(); - CheckArgsInferType<int32_t, uint64_t, Invalid>(); - CheckArgsInferType<int32_t, float, Invalid>(); - CheckArgsInferType<uint32_t, float, Invalid>(); - - // Invalid (u)int64_t-pairings do not compile. - CheckArgsInferType<uint64_t, int64_t, Invalid>(); - CheckArgsInferType<int64_t, float, Invalid>(); - CheckArgsInferType<int64_t, double, Invalid>(); - - // Properly promotes float. - CheckArgsInferType<float, double, double>(); -} - -TEST_F(RandomDistributionsTest, UniformExamples) { - // Examples. - absl::InsecureBitGen gen; - EXPECT_NE(1, absl::Uniform(gen, static_cast<uint16_t>(0), 1.0f)); - EXPECT_NE(1, absl::Uniform(gen, 0, 1.0)); - EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, - static_cast<uint16_t>(0), 1.0f)); - EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, 0, 1.0)); - EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, -1, 1.0)); - EXPECT_NE(1, absl::Uniform<double>(absl::IntervalOpenOpen, gen, -1, 1)); - EXPECT_NE(1, absl::Uniform<float>(absl::IntervalOpenOpen, gen, 0, 1)); - EXPECT_NE(1, absl::Uniform<float>(gen, 0, 1)); -} - -TEST_F(RandomDistributionsTest, UniformNoBounds) { - absl::InsecureBitGen gen; - - absl::Uniform<uint8_t>(gen); - absl::Uniform<uint16_t>(gen); - absl::Uniform<uint32_t>(gen); - absl::Uniform<uint64_t>(gen); -} - -TEST_F(RandomDistributionsTest, UniformNonsenseRanges) { - // The ranges used in this test are undefined behavior. - // The results are arbitrary and subject to future changes. - absl::InsecureBitGen gen; - - // <uint> - EXPECT_EQ(0, absl::Uniform<uint64_t>(gen, 0, 0)); - EXPECT_EQ(1, absl::Uniform<uint64_t>(gen, 1, 0)); - EXPECT_EQ(0, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 0, 0)); - EXPECT_EQ(1, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 1, 0)); - - constexpr auto m = (std::numeric_limits<uint64_t>::max)(); - - EXPECT_EQ(m, absl::Uniform(gen, m, m)); - EXPECT_EQ(m, absl::Uniform(gen, m, m - 1)); - EXPECT_EQ(m - 1, absl::Uniform(gen, m - 1, m)); - EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m)); - EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m - 1)); - EXPECT_EQ(m - 1, absl::Uniform(absl::IntervalOpenOpen, gen, m - 1, m)); - - // <int> - EXPECT_EQ(0, absl::Uniform<int64_t>(gen, 0, 0)); - EXPECT_EQ(1, absl::Uniform<int64_t>(gen, 1, 0)); - EXPECT_EQ(0, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 0, 0)); - EXPECT_EQ(1, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 1, 0)); - - constexpr auto l = (std::numeric_limits<int64_t>::min)(); - constexpr auto r = (std::numeric_limits<int64_t>::max)(); - - EXPECT_EQ(l, absl::Uniform(gen, l, l)); - EXPECT_EQ(r, absl::Uniform(gen, r, r)); - EXPECT_EQ(r, absl::Uniform(gen, r, r - 1)); - EXPECT_EQ(r - 1, absl::Uniform(gen, r - 1, r)); - EXPECT_EQ(l, absl::Uniform(absl::IntervalOpenOpen, gen, l, l)); - EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r)); - EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r - 1)); - EXPECT_EQ(r - 1, absl::Uniform(absl::IntervalOpenOpen, gen, r - 1, r)); - - // <double> - const double e = std::nextafter(1.0, 2.0); // 1 + epsilon - const double f = std::nextafter(1.0, 0.0); // 1 - epsilon - const double g = std::numeric_limits<double>::denorm_min(); - - EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, e)); - EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, f)); - EXPECT_EQ(0.0, absl::Uniform(gen, 0.0, g)); - - EXPECT_EQ(e, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, e)); - EXPECT_EQ(f, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, f)); - EXPECT_EQ(g, absl::Uniform(absl::IntervalOpenOpen, gen, 0.0, g)); -} - -// TODO(lar): Validate properties of non-default interval-semantics. -TEST_F(RandomDistributionsTest, UniformReal) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Uniform(gen, 0, 1.0); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(0.5, moments.mean, 0.02); - EXPECT_NEAR(1 / 12.0, moments.variance, 0.02); - EXPECT_NEAR(0.0, moments.skewness, 0.02); - EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02); -} - -TEST_F(RandomDistributionsTest, UniformInt) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - const int64_t kMax = 1000000000000ll; - int64_t j = absl::Uniform(absl::IntervalClosedClosed, gen, 0, kMax); - // convert to double. - values[i] = static_cast<double>(j) / static_cast<double>(kMax); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(0.5, moments.mean, 0.02); - EXPECT_NEAR(1 / 12.0, moments.variance, 0.02); - EXPECT_NEAR(0.0, moments.skewness, 0.02); - EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02); - - /* - // NOTE: These are not supported by absl::Uniform, which is specialized - // on integer and real valued types. - - enum E { E0, E1 }; // enum - enum S : int { S0, S1 }; // signed enum - enum U : unsigned int { U0, U1 }; // unsigned enum - - absl::Uniform(gen, E0, E1); - absl::Uniform(gen, S0, S1); - absl::Uniform(gen, U0, U1); - */ -} - -TEST_F(RandomDistributionsTest, Exponential) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Exponential<double>(gen); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(1.0, moments.mean, 0.02); - EXPECT_NEAR(1.0, moments.variance, 0.025); - EXPECT_NEAR(2.0, moments.skewness, 0.1); - EXPECT_LT(5.0, moments.kurtosis); -} - -TEST_F(RandomDistributionsTest, PoissonDefault) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Poisson<int64_t>(gen); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(1.0, moments.mean, 0.02); - EXPECT_NEAR(1.0, moments.variance, 0.02); - EXPECT_NEAR(1.0, moments.skewness, 0.025); - EXPECT_LT(2.0, moments.kurtosis); -} - -TEST_F(RandomDistributionsTest, PoissonLarge) { - constexpr double kMean = 100000000.0; - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Poisson<int64_t>(gen, kMean); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(kMean, moments.mean, kMean * 0.015); - EXPECT_NEAR(kMean, moments.variance, kMean * 0.015); - EXPECT_NEAR(std::sqrt(kMean), moments.skewness, kMean * 0.02); - EXPECT_LT(2.0, moments.kurtosis); -} - -TEST_F(RandomDistributionsTest, Bernoulli) { - constexpr double kP = 0.5151515151; - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Bernoulli(gen, kP); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(kP, moments.mean, 0.01); -} - -TEST_F(RandomDistributionsTest, Beta) { - constexpr double kAlpha = 2.0; - constexpr double kBeta = 3.0; - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Beta(gen, kAlpha, kBeta); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(0.4, moments.mean, 0.01); -} - -TEST_F(RandomDistributionsTest, Zipf) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Zipf<int64_t>(gen, 100); - } - - // The mean of a zipf distribution is: H(N, s-1) / H(N,s). - // Given the parameter v = 1, this gives the following function: - // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944 - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(6.5944, moments.mean, 2000) << moments; -} - -TEST_F(RandomDistributionsTest, Gaussian) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::Gaussian<double>(gen); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(0.0, moments.mean, 0.02); - EXPECT_NEAR(1.0, moments.variance, 0.04); - EXPECT_NEAR(0, moments.skewness, 0.2); - EXPECT_NEAR(3.0, moments.kurtosis, 0.5); -} - -TEST_F(RandomDistributionsTest, LogUniform) { - std::vector<double> values(kSize); - - absl::InsecureBitGen gen; - for (int i = 0; i < kSize; i++) { - values[i] = absl::LogUniform<int64_t>(gen, 0, (1 << 10) - 1); - } - - // The mean is the sum of the fractional means of the uniform distributions: - // [0..0][1..1][2..3][4..7][8..15][16..31][32..63] - // [64..127][128..255][256..511][512..1023] - const double mean = (0 + 1 + 1 + 2 + 3 + 4 + 7 + 8 + 15 + 16 + 31 + 32 + 63 + - 64 + 127 + 128 + 255 + 256 + 511 + 512 + 1023) / - (2.0 * 11.0); - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(mean, moments.mean, 2) << moments; -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/examples_test.cc b/third_party/abseil_cpp/absl/random/examples_test.cc deleted file mode 100644 index 1dcb5146f3d0..000000000000 --- a/third_party/abseil_cpp/absl/random/examples_test.cc +++ /dev/null @@ -1,99 +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 <cinttypes> -#include <random> -#include <sstream> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/random/random.h" - -template <typename T> -void Use(T) {} - -TEST(Examples, Basic) { - absl::BitGen gen; - std::vector<int> objs = {10, 20, 30, 40, 50}; - - // Choose an element from a set. - auto elem = objs[absl::Uniform(gen, 0u, objs.size())]; - Use(elem); - - // Generate a uniform value between 1 and 6. - auto dice_roll = absl::Uniform<int>(absl::IntervalClosedClosed, gen, 1, 6); - Use(dice_roll); - - // Generate a random byte. - auto byte = absl::Uniform<uint8_t>(gen); - Use(byte); - - // Generate a fractional value from [0f, 1f). - auto fraction = absl::Uniform<float>(gen, 0, 1); - Use(fraction); - - // Toss a fair coin; 50/50 probability. - bool coin_toss = absl::Bernoulli(gen, 0.5); - Use(coin_toss); - - // Select a file size between 1k and 10MB, biased towards smaller file sizes. - auto file_size = absl::LogUniform<size_t>(gen, 1000, 10 * 1000 * 1000); - Use(file_size); - - // Randomize (shuffle) a collection. - std::shuffle(std::begin(objs), std::end(objs), gen); -} - -TEST(Examples, CreateingCorrelatedVariateSequences) { - // Unexpected PRNG correlation is often a source of bugs, - // so when using absl::BitGen it must be an intentional choice. - // NOTE: All of these only exhibit process-level stability. - - // Create a correlated sequence from system entropy. - { - auto my_seed = absl::MakeSeedSeq(); - - absl::BitGen gen_1(my_seed); - absl::BitGen gen_2(my_seed); // Produces same variates as gen_1. - - EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5)); - EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2)); - } - - // Create a correlated sequence from an existing URBG. - { - absl::BitGen gen; - - auto my_seed = absl::CreateSeedSeqFrom(&gen); - absl::BitGen gen_1(my_seed); - absl::BitGen gen_2(my_seed); - - EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5)); - EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2)); - } - - // An alternate construction which uses user-supplied data - // instead of a random seed. - { - const char kData[] = "A simple seed string"; - std::seed_seq my_seed(std::begin(kData), std::end(kData)); - - absl::BitGen gen_1(my_seed); - absl::BitGen gen_2(my_seed); - - EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5)); - EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2)); - } -} - diff --git a/third_party/abseil_cpp/absl/random/exponential_distribution.h b/third_party/abseil_cpp/absl/random/exponential_distribution.h deleted file mode 100644 index b5caf8a1e1f3..000000000000 --- a/third_party/abseil_cpp/absl/random/exponential_distribution.h +++ /dev/null @@ -1,165 +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. - -#ifndef ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_ -#define ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::exponential_distribution: -// Generates a number conforming to an exponential distribution and is -// equivalent to the standard [rand.dist.pois.exp] distribution. -template <typename RealType = double> -class exponential_distribution { - public: - using result_type = RealType; - - class param_type { - public: - using distribution_type = exponential_distribution; - - explicit param_type(result_type lambda = 1) : lambda_(lambda) { - assert(lambda > 0); - neg_inv_lambda_ = -result_type(1) / lambda_; - } - - result_type lambda() const { return lambda_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.lambda_ == b.lambda_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class exponential_distribution; - - result_type lambda_; - result_type neg_inv_lambda_; - - static_assert( - std::is_floating_point<RealType>::value, - "Class-template absl::exponential_distribution<> must be parameterized " - "using a floating-point type."); - }; - - exponential_distribution() : exponential_distribution(1) {} - - explicit exponential_distribution(result_type lambda) : param_(lambda) {} - - explicit exponential_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - // Generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { return 0; } - result_type(max)() const { - return std::numeric_limits<result_type>::infinity(); - } - - result_type lambda() const { return param_.lambda(); } - - friend bool operator==(const exponential_distribution& a, - const exponential_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const exponential_distribution& a, - const exponential_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; - random_internal::FastUniformBits<uint64_t> fast_u64_; -}; - -// -------------------------------------------------------------------------- -// Implementation details follow -// -------------------------------------------------------------------------- - -template <typename RealType> -template <typename URBG> -typename exponential_distribution<RealType>::result_type -exponential_distribution<RealType>::operator()( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - using random_internal::GenerateNegativeTag; - using random_internal::GenerateRealFromBits; - using real_type = - absl::conditional_t<std::is_same<RealType, float>::value, float, double>; - - const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag, - false>(fast_u64_(g)); // U(-1, 0) - - // log1p(-x) is mathematically equivalent to log(1 - x) but has more - // accuracy for x near zero. - return p.neg_inv_lambda_ * std::log1p(u); -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const exponential_distribution<RealType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<RealType>::kPrecision); - os << x.lambda(); - return os; -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - exponential_distribution<RealType>& x) { // NOLINT(runtime/references) - using result_type = typename exponential_distribution<RealType>::result_type; - using param_type = typename exponential_distribution<RealType>::param_type; - result_type lambda; - - auto saver = random_internal::make_istream_state_saver(is); - lambda = random_internal::read_floating_point<result_type>(is); - if (!is.fail()) { - x.param(param_type(lambda)); - } - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/exponential_distribution_test.cc b/third_party/abseil_cpp/absl/random/exponential_distribution_test.cc deleted file mode 100644 index 8e9e69b64b29..000000000000 --- a/third_party/abseil_cpp/absl/random/exponential_distribution_test.cc +++ /dev/null @@ -1,430 +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/exponential_distribution.h" - -#include <algorithm> -#include <cmath> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <limits> -#include <random> -#include <sstream> -#include <string> -#include <type_traits> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -namespace { - -using absl::random_internal::kChiSquared; - -template <typename RealType> -class ExponentialDistributionTypedTest : public ::testing::Test {}; - -#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) { - using param_type = - typename absl::exponential_distribution<TypeParam>::param_type; - - const TypeParam kParams[] = { - // Cases around 1. - 1, // - std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon - std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon - // Typical cases. - TypeParam(1e-8), TypeParam(1e-4), TypeParam(1), TypeParam(2), - TypeParam(1e4), TypeParam(1e8), TypeParam(1e20), TypeParam(2.5), - // Boundary cases. - std::numeric_limits<TypeParam>::max(), - std::numeric_limits<TypeParam>::epsilon(), - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(1)), // min + epsilon - std::numeric_limits<TypeParam>::min(), // smallest normal - // There are some errors dealing with denorms on apple platforms. - std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm - std::numeric_limits<TypeParam>::min() / 2, // denorm - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(0)), // denorm_max - }; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - - for (const TypeParam lambda : kParams) { - // Some values may be invalid; skip those. - if (!std::isfinite(lambda)) continue; - ABSL_ASSERT(lambda > 0); - - const param_type param(lambda); - - absl::exponential_distribution<TypeParam> before(lambda); - EXPECT_EQ(before.lambda(), param.lambda()); - - { - absl::exponential_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - EXPECT_EQ(via_param.param(), before.param()); - } - - // Smoke test. - auto sample_min = before.max(); - auto sample_max = before.min(); - for (int i = 0; i < kCount; i++) { - auto sample = before(gen); - EXPECT_GE(sample, before.min()) << before; - EXPECT_LE(sample, before.max()) << before; - if (sample > sample_max) sample_max = sample; - if (sample < sample_min) sample_min = sample; - } - if (!std::is_same<TypeParam, long double>::value) { - ABSL_INTERNAL_LOG(INFO, - absl::StrFormat("Range {%f}: %f, %f, lambda=%f", lambda, - sample_min, sample_max, lambda)); - } - - std::stringstream ss; - ss << before; - - if (!std::isfinite(lambda)) { - // Streams do not deserialize inf/nan correctly. - continue; - } - // Validate stream serialization. - absl::exponential_distribution<TypeParam> after(34.56f); - - EXPECT_NE(before.lambda(), after.lambda()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - -#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 " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - } -} - -// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm - -class ExponentialModel { - public: - explicit ExponentialModel(double lambda) - : lambda_(lambda), beta_(1.0 / lambda) {} - - double lambda() const { return lambda_; } - - double mean() const { return beta_; } - double variance() const { return beta_ * beta_; } - double stddev() const { return std::sqrt(variance()); } - double skew() const { return 2; } - double kurtosis() const { return 6.0; } - - double CDF(double x) { return 1.0 - std::exp(-lambda_ * x); } - - // The inverse CDF, or PercentPoint function of the distribution - double InverseCDF(double p) { - ABSL_ASSERT(p >= 0.0); - ABSL_ASSERT(p < 1.0); - return -beta_ * std::log(1.0 - p); - } - - private: - const double lambda_; - const double beta_; -}; - -struct Param { - double lambda; - double p_fail; - int trials; -}; - -class ExponentialDistributionTests : public testing::TestWithParam<Param>, - public ExponentialModel { - public: - ExponentialDistributionTests() : ExponentialModel(GetParam().lambda) {} - - // SingleZTest provides a basic z-squared test of the mean vs. expected - // mean for data generated by the poisson distribution. - template <typename D> - bool SingleZTest(const double p, const size_t samples); - - // SingleChiSquaredTest provides a basic chi-squared test of the normal - // distribution. - template <typename D> - double SingleChiSquaredTest(); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -template <typename D> -bool ExponentialDistributionTests::SingleZTest(const double p, - const size_t samples) { - D dis(lambda()); - - std::vector<double> data; - data.reserve(samples); - for (size_t i = 0; i < samples; i++) { - const double x = dis(rng_); - data.push_back(x); - } - - const auto m = absl::random_internal::ComputeDistributionMoments(data); - const double max_err = absl::random_internal::MaxErrorTolerance(p); - const double z = absl::random_internal::ZScore(mean(), m); - const bool pass = absl::random_internal::Near("z", z, 0.0, max_err); - - if (!pass) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("p=%f max_err=%f\n" - " lambda=%f\n" - " mean=%f vs. %f\n" - " stddev=%f vs. %f\n" - " skewness=%f vs. %f\n" - " kurtosis=%f vs. %f\n" - " z=%f vs. 0", - p, max_err, lambda(), m.mean, mean(), - std::sqrt(m.variance), stddev(), m.skewness, - skew(), m.kurtosis, kurtosis(), z)); - } - return pass; -} - -template <typename D> -double ExponentialDistributionTests::SingleChiSquaredTest() { - const size_t kSamples = 10000; - const int kBuckets = 50; - - // The InverseCDF is the percent point function of the distribution, and can - // be used to assign buckets roughly uniformly. - std::vector<double> cutoffs; - const double kInc = 1.0 / static_cast<double>(kBuckets); - for (double p = kInc; p < 1.0; p += kInc) { - cutoffs.push_back(InverseCDF(p)); - } - if (cutoffs.back() != std::numeric_limits<double>::infinity()) { - cutoffs.push_back(std::numeric_limits<double>::infinity()); - } - - D dis(lambda()); - - std::vector<int32_t> counts(cutoffs.size(), 0); - for (int j = 0; j < kSamples; j++) { - const double x = dis(rng_); - auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x); - counts[std::distance(cutoffs.begin(), it)]++; - } - - // Null-hypothesis is that the distribution is exponentially distributed - // with the provided lambda (not estimated from the data). - const int dof = static_cast<int>(counts.size()) - 1; - - // Our threshold for logging is 1-in-50. - const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98); - - const double expected = - static_cast<double>(kSamples) / static_cast<double>(counts.size()); - - double chi_square = absl::random_internal::ChiSquareWithExpected( - std::begin(counts), std::end(counts), expected); - double p = absl::random_internal::ChiSquarePValue(chi_square, dof); - - if (chi_square > threshold) { - for (int i = 0; i < cutoffs.size(); i++) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("%d : (%f) = %d", i, cutoffs[i], counts[i])); - } - - ABSL_INTERNAL_LOG(INFO, - absl::StrCat("lambda ", lambda(), "\n", // - " expected ", expected, "\n", // - kChiSquared, " ", chi_square, " (", p, ")\n", - kChiSquared, " @ 0.98 = ", threshold)); - } - return p; -} - -TEST_P(ExponentialDistributionTests, ZTest) { - const size_t kSamples = 10000; - const auto& param = GetParam(); - const int expected_failures = - std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail))); - const double p = absl::random_internal::RequiredSuccessProbability( - param.p_fail, param.trials); - - int failures = 0; - for (int i = 0; i < param.trials; i++) { - failures += SingleZTest<absl::exponential_distribution<double>>(p, kSamples) - ? 0 - : 1; - } - EXPECT_LE(failures, expected_failures); -} - -TEST_P(ExponentialDistributionTests, ChiSquaredTest) { - const int kTrials = 20; - int failures = 0; - - for (int i = 0; i < kTrials; i++) { - double p_value = - SingleChiSquaredTest<absl::exponential_distribution<double>>(); - if (p_value < 0.005) { // 1/200 - failures++; - } - } - - // There is a 0.10% chance of producing at least one failure, so raise the - // failure threshold high enough to allow for a flake rate < 10,000. - EXPECT_LE(failures, 4); -} - -std::vector<Param> GenParams() { - return { - Param{1.0, 0.02, 100}, - Param{2.5, 0.02, 100}, - Param{10, 0.02, 100}, - // large - Param{1e4, 0.02, 100}, - Param{1e9, 0.02, 100}, - // small - Param{0.1, 0.02, 100}, - Param{1e-3, 0.02, 100}, - Param{1e-5, 0.02, 100}, - }; -} - -std::string ParamName(const ::testing::TestParamInfo<Param>& info) { - const auto& p = info.param; - std::string name = absl::StrCat("lambda_", absl::SixDigits(p.lambda)); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_CASE_P(All, ExponentialDistributionTests, - ::testing::ValuesIn(GenParams()), ParamName); - -// NOTE: absl::exponential_distribution is not guaranteed to be stable. -TEST(ExponentialDistributionTest, StabilityTest) { - // absl::exponential_distribution stability relies on std::log1p and - // absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(14); - - { - absl::exponential_distribution<double> dist; - std::generate(std::begin(output), std::end(output), - [&] { return static_cast<int>(10000.0 * dist(urbg)); }); - - EXPECT_EQ(14, urbg.invocations()); - EXPECT_THAT(output, - testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936, - 804, 126, 12337, 17984, 27002, 0, 71913)); - } - - urbg.reset(); - { - absl::exponential_distribution<float> dist; - std::generate(std::begin(output), std::end(output), - [&] { return static_cast<int>(10000.0f * dist(urbg)); }); - - EXPECT_EQ(14, urbg.invocations()); - EXPECT_THAT(output, - testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936, - 804, 126, 12337, 17984, 27002, 0, 71913)); - } -} - -TEST(ExponentialDistributionTest, AlgorithmBounds) { - // Relies on absl::uniform_real_distribution, so some of these comments - // reference that. - absl::exponential_distribution<double> dist; - - { - // This returns the smallest value >0 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0x0000000000000001ull}); - double a = dist(urbg); - EXPECT_EQ(a, 5.42101086242752217004e-20); - } - - { - // This returns a value very near 0.5 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull}); - double a = dist(urbg); - EXPECT_EQ(a, 0.693147180559945175204); - } - - { - // This returns the largest value <1 from absl::uniform_real_distribution. - // WolframAlpha: ~39.1439465808987766283058547296341915292187253 - absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFeFull}); - double a = dist(urbg); - EXPECT_EQ(a, 36.7368005696771007251); - } - { - // This *ALSO* returns the largest value <1. - absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull}); - double a = dist(urbg); - EXPECT_EQ(a, 36.7368005696771007251); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/gaussian_distribution.cc b/third_party/abseil_cpp/absl/random/gaussian_distribution.cc deleted file mode 100644 index c7a72cb2f61c..000000000000 --- a/third_party/abseil_cpp/absl/random/gaussian_distribution.cc +++ /dev/null @@ -1,104 +0,0 @@ -// BEGIN GENERATED CODE; DO NOT EDIT -// clang-format off - -#include "absl/random/gaussian_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -const gaussian_distribution_base::Tables - gaussian_distribution_base::zg_ = { - {3.7130862467425505, 3.442619855899000214, 3.223084984581141565, - 3.083228858216868318, 2.978696252647779819, 2.894344007021528942, - 2.82312535054891045, 2.761169372387176857, 2.706113573121819549, - 2.656406411261359679, 2.610972248431847387, 2.56903362592493778, - 2.530009672388827457, 2.493454522095372106, 2.459018177411830486, - 2.426420645533749809, 2.395434278011062457, 2.365871370117638595, - 2.337575241339236776, 2.310413683698762988, 2.284274059677471769, - 2.25905957386919809, 2.234686395590979036, 2.21108140887870297, - 2.188180432076048731, 2.165926793748921497, 2.144270182360394905, - 2.123165708673976138, 2.102573135189237608, 2.082456237992015957, - 2.062782274508307978, 2.043521536655067194, 2.02464697337738464, - 2.006133869963471206, 1.987959574127619033, 1.970103260854325633, - 1.952545729553555764, 1.935269228296621957, 1.918257300864508963, - 1.901494653105150423, 1.884967035707758143, 1.868661140994487768, - 1.852564511728090002, 1.836665460258444904, 1.820952996596124418, - 1.805416764219227366, 1.790046982599857506, 1.77483439558606837, - 1.759770224899592339, 1.744846128113799244, 1.730054160563729182, - 1.71538674071366648, 1.700836618569915748, 1.686396846779167014, - 1.6720607540975998, 1.657821920954023254, 1.643674156862867441, - 1.629611479470633562, 1.615628095043159629, 1.601718380221376581, - 1.587876864890574558, 1.574098216022999264, 1.560377222366167382, - 1.546708779859908844, 1.533087877674041755, 1.519509584765938559, - 1.505969036863201937, 1.492461423781352714, 1.478981976989922842, - 1.465525957342709296, 1.452088642889222792, 1.438665316684561546, - 1.425251254514058319, 1.411841712447055919, 1.398431914131003539, - 1.385017037732650058, 1.371592202427340812, 1.358152454330141534, - 1.34469275175354519, 1.331207949665625279, 1.317692783209412299, - 1.304141850128615054, 1.290549591926194894, 1.27691027356015363, - 1.263217961454619287, 1.249466499573066436, 1.23564948326336066, - 1.221760230539994385, 1.207791750415947662, 1.193736707833126465, - 1.17958738466398616, 1.165335636164750222, 1.150972842148865416, - 1.136489852013158774, 1.121876922582540237, 1.107123647534034028, - 1.092218876907275371, 1.077150624892893482, 1.061905963694822042, - 1.046470900764042922, 1.030830236068192907, 1.014967395251327842, - 0.9988642334929808131, 0.9825008035154263464, 0.9658550794011470098, - 0.9489026255113034436, 0.9316161966151479401, 0.9139652510230292792, - 0.8959153525809346874, 0.8774274291129204872, 0.8584568431938099931, - 0.8389522142975741614, 0.8188539067003538507, 0.7980920606440534693, - 0.7765839878947563557, 0.7542306644540520688, 0.7309119106424850631, - 0.7064796113354325779, 0.6807479186691505202, 0.6534786387399710295, - 0.6243585973360461505, 0.5929629424714434327, 0.5586921784081798625, - 0.5206560387620546848, 0.4774378372966830431, 0.4265479863554152429, - 0.3628714310970211909, 0.2723208648139477384, 0}, - {0.001014352564120377413, 0.002669629083880922793, 0.005548995220771345792, - 0.008624484412859888607, 0.01183947865788486861, 0.01516729801054656976, - 0.01859210273701129151, 0.02210330461592709475, 0.02569329193593428151, - 0.02935631744000685023, 0.03308788614622575758, 0.03688438878665621645, - 0.04074286807444417458, 0.04466086220049143157, 0.04863629585986780496, - 0.05266740190305100461, 0.05675266348104984759, 0.06089077034804041277, - 0.06508058521306804567, 0.06932111739357792179, 0.07361150188411341722, - 0.07795098251397346301, 0.08233889824223575293, 0.08677467189478028919, - 0.09125780082683036809, 0.095787849121731522, 0.1003644410286559929, - 0.1049872554094214289, 0.1096560210148404546, 0.1143705124488661323, - 0.1191305467076509556, 0.1239359802028679736, 0.1287867061959434012, - 0.1336826525834396151, 0.1386237799845948804, 0.1436100800906280339, - 0.1486415742423425057, 0.1537183122081819397, 0.1588403711394795748, - 0.1640078546834206341, 0.1692208922373653057, 0.1744796383307898324, - 0.1797842721232958407, 0.1851349970089926078, 0.1905320403191375633, - 0.1959756531162781534, 0.2014661100743140865, 0.2070037094399269362, - 0.2125887730717307134, 0.2182216465543058426, 0.2239026993850088965, - 0.229632325232116602, 0.2354109422634795556, 0.2412389935454402889, - 0.2471169475123218551, 0.2530452985073261551, 0.2590245673962052742, - 0.2650553022555897087, 0.271138079138385224, 0.2772735029191887857, - 0.2834622082232336471, 0.2897048604429605656, 0.2960021568469337061, - 0.3023548277864842593, 0.3087636380061818397, 0.3152293880650116065, - 0.3217529158759855901, 0.3283350983728509642, 0.3349768533135899506, - 0.3416791412315512977, 0.3484429675463274756, 0.355269384847918035, - 0.3621594953693184626, 0.3691144536644731522, 0.376135469510563536, - 0.3832238110559021416, 0.3903808082373155797, 0.3976078564938743676, - 0.404906420807223999, 0.4122780401026620578, 0.4197243320495753771, - 0.4272469983049970721, 0.4348478302499918513, 0.4425287152754694975, - 0.4502916436820402768, 0.458138716267873114, 0.4660721526894572309, - 0.4740943006930180559, 0.4822076463294863724, 0.4904148252838453348, - 0.4987186354709807201, 0.5071220510755701794, 0.5156282382440030565, - 0.5242405726729852944, 0.5329626593838373561, 0.5417983550254266145, - 0.5507517931146057588, 0.5598274127040882009, 0.5690299910679523787, - 0.5783646811197646898, 0.5878370544347081283, 0.5974531509445183408, - 0.6072195366251219584, 0.6171433708188825973, 0.6272324852499290282, - 0.6374954773350440806, 0.6479418211102242475, 0.6585820000500898219, - 0.6694276673488921414, 0.6804918409973358395, 0.6917891434366769676, - 0.7033360990161600101, 0.7151515074105005976, 0.7272569183441868201, - 0.7396772436726493094, 0.7524415591746134169, 0.7655841738977066102, - 0.7791460859296898134, 0.7931770117713072832, 0.8077382946829627652, - 0.8229072113814113187, 0.8387836052959920519, 0.8555006078694531446, - 0.873243048910072206, 0.8922816507840289901, 0.9130436479717434217, - 0.9362826816850632339, 0.9635996931270905952, 1}}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -// clang-format on -// END GENERATED CODE diff --git a/third_party/abseil_cpp/absl/random/gaussian_distribution.h b/third_party/abseil_cpp/absl/random/gaussian_distribution.h deleted file mode 100644 index 4b07a5c0af9d..000000000000 --- a/third_party/abseil_cpp/absl/random/gaussian_distribution.h +++ /dev/null @@ -1,275 +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. - -#ifndef ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_ -#define ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_ - -// absl::gaussian_distribution implements the Ziggurat algorithm -// for generating random gaussian numbers. -// -// Implementation based on "The Ziggurat Method for Generating Random Variables" -// by George Marsaglia and Wai Wan Tsang: http://www.jstatsoft.org/v05/i08/ -// - -#include <cmath> -#include <cstdint> -#include <istream> -#include <limits> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// absl::gaussian_distribution_base implements the underlying ziggurat algorithm -// using the ziggurat tables generated by the gaussian_distribution_gentables -// binary. -// -// The specific algorithm has some of the improvements suggested by the -// 2005 paper, "An Improved Ziggurat Method to Generate Normal Random Samples", -// Jurgen A Doornik. (https://www.doornik.com/research/ziggurat.pdf) -class ABSL_DLL gaussian_distribution_base { - public: - template <typename URBG> - inline double zignor(URBG& g); // NOLINT(runtime/references) - - private: - friend class TableGenerator; - - template <typename URBG> - inline double zignor_fallback(URBG& g, // NOLINT(runtime/references) - bool neg); - - // Constants used for the gaussian distribution. - static constexpr double kR = 3.442619855899; // Start of the tail. - static constexpr double kRInv = 0.29047645161474317; // ~= (1.0 / kR) . - static constexpr double kV = 9.91256303526217e-3; - static constexpr uint64_t kMask = 0x07f; - - // The ziggurat tables store the pdf(f) and inverse-pdf(x) for equal-area - // points on one-half of the normal distribution, where the pdf function, - // pdf = e ^ (-1/2 *x^2), assumes that the mean = 0 & stddev = 1. - // - // These tables are just over 2kb in size; larger tables might improve the - // distributions, but also lead to more cache pollution. - // - // x = {3.71308, 3.44261, 3.22308, ..., 0} - // f = {0.00101, 0.00266, 0.00554, ..., 1} - struct Tables { - double x[kMask + 2]; - double f[kMask + 2]; - }; - static const Tables zg_; - random_internal::FastUniformBits<uint64_t> fast_u64_; -}; - -} // namespace random_internal - -// absl::gaussian_distribution: -// Generates a number conforming to a Gaussian distribution. -template <typename RealType = double> -class gaussian_distribution : random_internal::gaussian_distribution_base { - public: - using result_type = RealType; - - class param_type { - public: - using distribution_type = gaussian_distribution; - - explicit param_type(result_type mean = 0, result_type stddev = 1) - : mean_(mean), stddev_(stddev) {} - - // Returns the mean distribution parameter. The mean specifies the location - // of the peak. The default value is 0.0. - result_type mean() const { return mean_; } - - // Returns the deviation distribution parameter. The default value is 1.0. - result_type stddev() const { return stddev_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.mean_ == b.mean_ && a.stddev_ == b.stddev_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - result_type mean_; - result_type stddev_; - - static_assert( - std::is_floating_point<RealType>::value, - "Class-template absl::gaussian_distribution<> must be parameterized " - "using a floating-point type."); - }; - - gaussian_distribution() : gaussian_distribution(0) {} - - explicit gaussian_distribution(result_type mean, result_type stddev = 1) - : param_(mean, stddev) {} - - explicit gaussian_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - // Generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { - return -std::numeric_limits<result_type>::infinity(); - } - result_type(max)() const { - return std::numeric_limits<result_type>::infinity(); - } - - result_type mean() const { return param_.mean(); } - result_type stddev() const { return param_.stddev(); } - - friend bool operator==(const gaussian_distribution& a, - const gaussian_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const gaussian_distribution& a, - const gaussian_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; -}; - -// -------------------------------------------------------------------------- -// Implementation details only below -// -------------------------------------------------------------------------- - -template <typename RealType> -template <typename URBG> -typename gaussian_distribution<RealType>::result_type -gaussian_distribution<RealType>::operator()( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - return p.mean() + p.stddev() * static_cast<result_type>(zignor(g)); -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const gaussian_distribution<RealType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<RealType>::kPrecision); - os << x.mean() << os.fill() << x.stddev(); - return os; -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - gaussian_distribution<RealType>& x) { // NOLINT(runtime/references) - using result_type = typename gaussian_distribution<RealType>::result_type; - using param_type = typename gaussian_distribution<RealType>::param_type; - - auto saver = random_internal::make_istream_state_saver(is); - auto mean = random_internal::read_floating_point<result_type>(is); - if (is.fail()) return is; - auto stddev = random_internal::read_floating_point<result_type>(is); - if (!is.fail()) { - x.param(param_type(mean, stddev)); - } - return is; -} - -namespace random_internal { - -template <typename URBG> -inline double gaussian_distribution_base::zignor_fallback(URBG& g, bool neg) { - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - - // This fallback path happens approximately 0.05% of the time. - double x, y; - do { - // kRInv = 1/r, U(0, 1) - x = kRInv * - std::log(GenerateRealFromBits<double, GeneratePositiveTag, false>( - fast_u64_(g))); - y = -std::log( - GenerateRealFromBits<double, GeneratePositiveTag, false>(fast_u64_(g))); - } while ((y + y) < (x * x)); - return neg ? (x - kR) : (kR - x); -} - -template <typename URBG> -inline double gaussian_distribution_base::zignor( - URBG& g) { // NOLINT(runtime/references) - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - using random_internal::GenerateSignedTag; - - while (true) { - // We use a single uint64_t to generate both a double and a strip. - // These bits are unused when the generated double is > 1/2^5. - // This may introduce some bias from the duplicated low bits of small - // values (those smaller than 1/2^5, which all end up on the left tail). - uint64_t bits = fast_u64_(g); - int i = static_cast<int>(bits & kMask); // pick a random strip - double j = GenerateRealFromBits<double, GenerateSignedTag, false>( - bits); // U(-1, 1) - const double x = j * zg_.x[i]; - - // Retangular box. Handles >97% of all cases. - // For any given box, this handles between 75% and 99% of values. - // Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5% - if (std::abs(x) < zg_.x[i + 1]) { - return x; - } - - // i == 0: Base box. Sample using a ratio of uniforms. - if (i == 0) { - // This path happens about 0.05% of the time. - return zignor_fallback(g, j < 0); - } - - // i > 0: Wedge samples using precomputed values. - double v = GenerateRealFromBits<double, GeneratePositiveTag, false>( - fast_u64_(g)); // U(0, 1) - if ((zg_.f[i + 1] + v * (zg_.f[i] - zg_.f[i + 1])) < - std::exp(-0.5 * x * x)) { - return x; - } - - // The wedge was missed; reject the value and try again. - } -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/gaussian_distribution_test.cc b/third_party/abseil_cpp/absl/random/gaussian_distribution_test.cc deleted file mode 100644 index 02ac578a5c18..000000000000 --- a/third_party/abseil_cpp/absl/random/gaussian_distribution_test.cc +++ /dev/null @@ -1,579 +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/gaussian_distribution.h" - -#include <algorithm> -#include <cmath> -#include <cstddef> -#include <ios> -#include <iterator> -#include <random> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -namespace { - -using absl::random_internal::kChiSquared; - -template <typename RealType> -class GaussianDistributionInterfaceTest : public ::testing::Test {}; - -using RealTypes = ::testing::Types<float, double, long double>; -TYPED_TEST_CASE(GaussianDistributionInterfaceTest, RealTypes); - -TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) { - using param_type = - typename absl::gaussian_distribution<TypeParam>::param_type; - - const TypeParam kParams[] = { - // Cases around 1. - 1, // - std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon - std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon - // Arbitrary values. - TypeParam(1e-8), TypeParam(1e-4), TypeParam(2), TypeParam(1e4), - TypeParam(1e8), TypeParam(1e20), TypeParam(2.5), - // Boundary cases. - std::numeric_limits<TypeParam>::infinity(), - std::numeric_limits<TypeParam>::max(), - std::numeric_limits<TypeParam>::epsilon(), - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(1)), // min + epsilon - std::numeric_limits<TypeParam>::min(), // smallest normal - // There are some errors dealing with denorms on apple platforms. - std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm - std::numeric_limits<TypeParam>::min() / 2, - std::nextafter(std::numeric_limits<TypeParam>::min(), - TypeParam(0)), // denorm_max - }; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - - // Use a loop to generate the combinations of {+/-x, +/-y}, and assign x, y to - // all values in kParams, - for (const auto mod : {0, 1, 2, 3}) { - for (const auto x : kParams) { - if (!std::isfinite(x)) continue; - for (const auto y : kParams) { - const TypeParam mean = (mod & 0x1) ? -x : x; - const TypeParam stddev = (mod & 0x2) ? -y : y; - const param_type param(mean, stddev); - - absl::gaussian_distribution<TypeParam> before(mean, stddev); - EXPECT_EQ(before.mean(), param.mean()); - EXPECT_EQ(before.stddev(), param.stddev()); - - { - absl::gaussian_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - EXPECT_EQ(via_param.param(), before.param()); - } - - // Smoke test. - auto sample_min = before.max(); - auto sample_max = before.min(); - for (int i = 0; i < kCount; i++) { - auto sample = before(gen); - if (sample > sample_max) sample_max = sample; - if (sample < sample_min) sample_min = sample; - EXPECT_GE(sample, before.min()) << before; - EXPECT_LE(sample, before.max()) << before; - } - if (!std::is_same<TypeParam, long double>::value) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("Range{%f, %f}: %f, %f", mean, stddev, - sample_min, sample_max)); - } - - std::stringstream ss; - ss << before; - - if (!std::isfinite(mean) || !std::isfinite(stddev)) { - // Streams do not parse inf/nan. - continue; - } - - // Validate stream serialization. - absl::gaussian_distribution<TypeParam> after(-0.53f, 2.3456f); - - EXPECT_NE(before.mean(), after.mean()); - EXPECT_NE(before.stddev(), after.stddev()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - -#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ - defined(__ppc__) || defined(__PPC__) || defined(__EMSCRIPTEN__) - 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}. - // - // Emscripten is even worse, implementing long double as a 128-bit - // type, but shipping with a strtold() that doesn't support that. - 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() << " " // - << (ss.good() ? "good " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - } - } - } -} - -// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm - -class GaussianModel { - public: - GaussianModel(double mean, double stddev) : mean_(mean), stddev_(stddev) {} - - double mean() const { return mean_; } - double variance() const { return stddev() * stddev(); } - double stddev() const { return stddev_; } - double skew() const { return 0; } - double kurtosis() const { return 3.0; } - - // The inverse CDF, or PercentPoint function. - double InverseCDF(double p) { - ABSL_ASSERT(p >= 0.0); - ABSL_ASSERT(p < 1.0); - return mean() + stddev() * -absl::random_internal::InverseNormalSurvival(p); - } - - private: - const double mean_; - const double stddev_; -}; - -struct Param { - double mean; - double stddev; - double p_fail; // Z-Test probability of failure. - int trials; // Z-Test trials. -}; - -// GaussianDistributionTests implements a z-test for the gaussian -// distribution. -class GaussianDistributionTests : public testing::TestWithParam<Param>, - public GaussianModel { - public: - GaussianDistributionTests() - : GaussianModel(GetParam().mean, GetParam().stddev) {} - - // SingleZTest provides a basic z-squared test of the mean vs. expected - // mean for data generated by the poisson distribution. - template <typename D> - bool SingleZTest(const double p, const size_t samples); - - // SingleChiSquaredTest provides a basic chi-squared test of the normal - // distribution. - template <typename D> - double SingleChiSquaredTest(); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -template <typename D> -bool GaussianDistributionTests::SingleZTest(const double p, - const size_t samples) { - D dis(mean(), stddev()); - - std::vector<double> data; - data.reserve(samples); - for (size_t i = 0; i < samples; i++) { - const double x = dis(rng_); - data.push_back(x); - } - - const double max_err = absl::random_internal::MaxErrorTolerance(p); - const auto m = absl::random_internal::ComputeDistributionMoments(data); - const double z = absl::random_internal::ZScore(mean(), m); - const bool pass = absl::random_internal::Near("z", z, 0.0, max_err); - - // NOTE: Informational statistical test: - // - // Compute the Jarque-Bera test statistic given the excess skewness - // and kurtosis. The statistic is drawn from a chi-square(2) distribution. - // https://en.wikipedia.org/wiki/Jarque%E2%80%93Bera_test - // - // The null-hypothesis (normal distribution) is rejected when - // (p = 0.05 => jb > 5.99) - // (p = 0.01 => jb > 9.21) - // NOTE: JB has a large type-I error rate, so it will reject the - // null-hypothesis even when it is true more often than the z-test. - // - const double jb = - static_cast<double>(m.n) / 6.0 * - (std::pow(m.skewness, 2.0) + std::pow(m.kurtosis - 3.0, 2.0) / 4.0); - - if (!pass || jb > 9.21) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("p=%f max_err=%f\n" - " mean=%f vs. %f\n" - " stddev=%f vs. %f\n" - " skewness=%f vs. %f\n" - " kurtosis=%f vs. %f\n" - " z=%f vs. 0\n" - " jb=%f vs. 9.21", - p, max_err, m.mean, mean(), std::sqrt(m.variance), - stddev(), m.skewness, skew(), m.kurtosis, - kurtosis(), z, jb)); - } - return pass; -} - -template <typename D> -double GaussianDistributionTests::SingleChiSquaredTest() { - const size_t kSamples = 10000; - const int kBuckets = 50; - - // The InverseCDF is the percent point function of the - // distribution, and can be used to assign buckets - // roughly uniformly. - std::vector<double> cutoffs; - const double kInc = 1.0 / static_cast<double>(kBuckets); - for (double p = kInc; p < 1.0; p += kInc) { - cutoffs.push_back(InverseCDF(p)); - } - if (cutoffs.back() != std::numeric_limits<double>::infinity()) { - cutoffs.push_back(std::numeric_limits<double>::infinity()); - } - - D dis(mean(), stddev()); - - std::vector<int32_t> counts(cutoffs.size(), 0); - for (int j = 0; j < kSamples; j++) { - const double x = dis(rng_); - auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x); - counts[std::distance(cutoffs.begin(), it)]++; - } - - // Null-hypothesis is that the distribution is a gaussian distribution - // with the provided mean and stddev (not estimated from the data). - const int dof = static_cast<int>(counts.size()) - 1; - - // Our threshold for logging is 1-in-50. - const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98); - - const double expected = - static_cast<double>(kSamples) / static_cast<double>(counts.size()); - - double chi_square = absl::random_internal::ChiSquareWithExpected( - std::begin(counts), std::end(counts), expected); - double p = absl::random_internal::ChiSquarePValue(chi_square, dof); - - // Log if the chi_square value is above the threshold. - if (chi_square > threshold) { - for (int i = 0; i < cutoffs.size(); i++) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("%d : (%f) = %d", i, cutoffs[i], counts[i])); - } - - ABSL_INTERNAL_LOG( - INFO, absl::StrCat("mean=", mean(), " stddev=", stddev(), "\n", // - " expected ", expected, "\n", // - kChiSquared, " ", chi_square, " (", p, ")\n", // - kChiSquared, " @ 0.98 = ", threshold)); - } - return p; -} - -TEST_P(GaussianDistributionTests, ZTest) { - // TODO(absl-team): Run these tests against std::normal_distribution<double> - // to validate outcomes are similar. - const size_t kSamples = 10000; - const auto& param = GetParam(); - const int expected_failures = - std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail))); - const double p = absl::random_internal::RequiredSuccessProbability( - param.p_fail, param.trials); - - int failures = 0; - for (int i = 0; i < param.trials; i++) { - failures += - SingleZTest<absl::gaussian_distribution<double>>(p, kSamples) ? 0 : 1; - } - EXPECT_LE(failures, expected_failures); -} - -TEST_P(GaussianDistributionTests, ChiSquaredTest) { - const int kTrials = 20; - int failures = 0; - - for (int i = 0; i < kTrials; i++) { - double p_value = - SingleChiSquaredTest<absl::gaussian_distribution<double>>(); - if (p_value < 0.0025) { // 1/400 - failures++; - } - } - // There is a 0.05% chance of producing at least one failure, so raise the - // failure threshold high enough to allow for a flake rate of less than one in - // 10,000. - EXPECT_LE(failures, 4); -} - -std::vector<Param> GenParams() { - return { - // Mean around 0. - Param{0.0, 1.0, 0.01, 100}, - Param{0.0, 1e2, 0.01, 100}, - Param{0.0, 1e4, 0.01, 100}, - Param{0.0, 1e8, 0.01, 100}, - Param{0.0, 1e16, 0.01, 100}, - Param{0.0, 1e-3, 0.01, 100}, - Param{0.0, 1e-5, 0.01, 100}, - Param{0.0, 1e-9, 0.01, 100}, - Param{0.0, 1e-17, 0.01, 100}, - - // Mean around 1. - Param{1.0, 1.0, 0.01, 100}, - Param{1.0, 1e2, 0.01, 100}, - Param{1.0, 1e-2, 0.01, 100}, - - // Mean around 100 / -100 - Param{1e2, 1.0, 0.01, 100}, - Param{-1e2, 1.0, 0.01, 100}, - Param{1e2, 1e6, 0.01, 100}, - Param{-1e2, 1e6, 0.01, 100}, - - // More extreme - Param{1e4, 1e4, 0.01, 100}, - Param{1e8, 1e4, 0.01, 100}, - Param{1e12, 1e4, 0.01, 100}, - }; -} - -std::string ParamName(const ::testing::TestParamInfo<Param>& info) { - const auto& p = info.param; - std::string name = absl::StrCat("mean_", absl::SixDigits(p.mean), "__stddev_", - absl::SixDigits(p.stddev)); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_SUITE_P(All, GaussianDistributionTests, - ::testing::ValuesIn(GenParams()), ParamName); - -// NOTE: absl::gaussian_distribution is not guaranteed to be stable. -TEST(GaussianDistributionTest, StabilityTest) { - // absl::gaussian_distribution stability relies on the underlying zignor - // data, absl::random_interna::RandU64ToDouble, std::exp, std::log, and - // std::abs. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(11); - - { - absl::gaussian_distribution<double> dist; - std::generate(std::begin(output), std::end(output), - [&] { return static_cast<int>(10000000.0 * dist(urbg)); }); - - EXPECT_EQ(13, urbg.invocations()); - EXPECT_THAT(output, // - testing::ElementsAre(1494, 25518841, 9991550, 1351856, - -20373238, 3456682, 333530, -6804981, - -15279580, -16459654, 1494)); - } - - urbg.reset(); - { - absl::gaussian_distribution<float> dist; - std::generate(std::begin(output), std::end(output), - [&] { return static_cast<int>(1000000.0f * dist(urbg)); }); - - EXPECT_EQ(13, urbg.invocations()); - EXPECT_THAT( - output, // - testing::ElementsAre(149, 2551884, 999155, 135185, -2037323, 345668, - 33353, -680498, -1527958, -1645965, 149)); - } -} - -// This is an implementation-specific test. If any part of the implementation -// changes, then it is likely that this test will change as well. -// Also, if dependencies of the distribution change, such as RandU64ToDouble, -// then this is also likely to change. -TEST(GaussianDistributionTest, AlgorithmBounds) { - absl::gaussian_distribution<double> dist; - - // In ~95% of cases, a single value is used to generate the output. - // for all inputs where |x| < 0.750461021389 this should be the case. - // - // The exact constraints are based on the ziggurat tables, and any - // changes to the ziggurat tables may require adjusting these bounds. - // - // for i in range(0, len(X)-1): - // print i, X[i+1]/X[i], (X[i+1]/X[i] > 0.984375) - // - // 0.125 <= |values| <= 0.75 - const uint64_t kValues[] = { - 0x1000000000000100ull, 0x2000000000000100ull, 0x3000000000000100ull, - 0x4000000000000100ull, 0x5000000000000100ull, 0x6000000000000100ull, - // negative values - 0x9000000000000100ull, 0xa000000000000100ull, 0xb000000000000100ull, - 0xc000000000000100ull, 0xd000000000000100ull, 0xe000000000000100ull}; - - // 0.875 <= |values| <= 0.984375 - const uint64_t kExtraValues[] = { - 0x7000000000000100ull, 0x7800000000000100ull, // - 0x7c00000000000100ull, 0x7e00000000000100ull, // - // negative values - 0xf000000000000100ull, 0xf800000000000100ull, // - 0xfc00000000000100ull, 0xfe00000000000100ull}; - - auto make_box = [](uint64_t v, uint64_t box) { - return (v & 0xffffffffffffff80ull) | box; - }; - - // The box is the lower 7 bits of the value. When the box == 0, then - // the algorithm uses an escape hatch to select the result for large - // outputs. - for (uint64_t box = 0; box < 0x7f; box++) { - for (const uint64_t v : kValues) { - // Extra values are added to the sequence to attempt to avoid - // infinite loops from rejection sampling on bugs/errors. - absl::random_internal::sequence_urbg urbg( - {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull}); - - auto a = dist(urbg); - EXPECT_EQ(1, urbg.invocations()) << box << " " << std::hex << v; - if (v & 0x8000000000000000ull) { - EXPECT_LT(a, 0.0) << box << " " << std::hex << v; - } else { - EXPECT_GT(a, 0.0) << box << " " << std::hex << v; - } - } - if (box > 10 && box < 100) { - // The center boxes use the fast algorithm for more - // than 98.4375% of values. - for (const uint64_t v : kExtraValues) { - absl::random_internal::sequence_urbg urbg( - {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull}); - - auto a = dist(urbg); - EXPECT_EQ(1, urbg.invocations()) << box << " " << std::hex << v; - if (v & 0x8000000000000000ull) { - EXPECT_LT(a, 0.0) << box << " " << std::hex << v; - } else { - EXPECT_GT(a, 0.0) << box << " " << std::hex << v; - } - } - } - } - - // When the box == 0, the fallback algorithm uses a ratio of uniforms, - // which consumes 2 additional values from the urbg. - // Fallback also requires that the initial value be > 0.9271586026096681. - auto make_fallback = [](uint64_t v) { return (v & 0xffffffffffffff80ull); }; - - double tail[2]; - { - // 0.9375 - absl::random_internal::sequence_urbg urbg( - {make_fallback(0x7800000000000000ull), 0x13CCA830EB61BD96ull, - 0x00000076f6f7f755ull}); - tail[0] = dist(urbg); - EXPECT_EQ(3, urbg.invocations()); - EXPECT_GT(tail[0], 0); - } - { - // -0.9375 - absl::random_internal::sequence_urbg urbg( - {make_fallback(0xf800000000000000ull), 0x13CCA830EB61BD96ull, - 0x00000076f6f7f755ull}); - tail[1] = dist(urbg); - EXPECT_EQ(3, urbg.invocations()); - EXPECT_LT(tail[1], 0); - } - EXPECT_EQ(tail[0], -tail[1]); - EXPECT_EQ(418610, static_cast<int64_t>(tail[0] * 100000.0)); - - // When the box != 0, the fallback algorithm computes a wedge function. - // Depending on the box, the threshold for varies as high as - // 0.991522480228. - { - // 0.9921875, 0.875 - absl::random_internal::sequence_urbg urbg( - {make_box(0x7f00000000000000ull, 120), 0xe000000000000001ull, - 0x13CCA830EB61BD96ull}); - tail[0] = dist(urbg); - EXPECT_EQ(2, urbg.invocations()); - EXPECT_GT(tail[0], 0); - } - { - // -0.9921875, 0.875 - absl::random_internal::sequence_urbg urbg( - {make_box(0xff00000000000000ull, 120), 0xe000000000000001ull, - 0x13CCA830EB61BD96ull}); - tail[1] = dist(urbg); - EXPECT_EQ(2, urbg.invocations()); - EXPECT_LT(tail[1], 0); - } - EXPECT_EQ(tail[0], -tail[1]); - EXPECT_EQ(61948, static_cast<int64_t>(tail[0] * 100000.0)); - - // Fallback rejected, try again. - { - // -0.9921875, 0.0625 - absl::random_internal::sequence_urbg urbg( - {make_box(0xff00000000000000ull, 120), 0x1000000000000001, - make_box(0x1000000000000100ull, 50), 0x13CCA830EB61BD96ull}); - dist(urbg); - EXPECT_EQ(3, urbg.invocations()); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/generators_test.cc b/third_party/abseil_cpp/absl/random/generators_test.cc deleted file mode 100644 index 41725f139cd3..000000000000 --- a/third_party/abseil_cpp/absl/random/generators_test.cc +++ /dev/null @@ -1,179 +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 <cstddef> -#include <cstdint> -#include <random> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/random/distributions.h" -#include "absl/random/random.h" - -namespace { - -template <typename URBG> -void TestUniform(URBG* gen) { - // [a, b) default-semantics, inferred types. - absl::Uniform(*gen, 0, 100); // int - absl::Uniform(*gen, 0, 1.0); // Promoted to double - absl::Uniform(*gen, 0.0f, 1.0); // Promoted to double - absl::Uniform(*gen, 0.0, 1.0); // double - absl::Uniform(*gen, -1, 1L); // Promoted to long - - // Roll a die. - absl::Uniform(absl::IntervalClosedClosed, *gen, 1, 6); - - // Get a fraction. - absl::Uniform(absl::IntervalOpenOpen, *gen, 0.0, 1.0); - - // Assign a value to a random element. - std::vector<int> elems = {10, 20, 30, 40, 50}; - elems[absl::Uniform(*gen, 0u, elems.size())] = 5; - elems[absl::Uniform<size_t>(*gen, 0, elems.size())] = 3; - - // Choose some epsilon around zero. - absl::Uniform(absl::IntervalOpenOpen, *gen, -1.0, 1.0); - - // (a, b) semantics, inferred types. - absl::Uniform(absl::IntervalOpenOpen, *gen, 0, 1.0); // Promoted to double - - // Explict overriding of types. - absl::Uniform<int>(*gen, 0, 100); - absl::Uniform<int8_t>(*gen, 0, 100); - absl::Uniform<int16_t>(*gen, 0, 100); - absl::Uniform<uint16_t>(*gen, 0, 100); - absl::Uniform<int32_t>(*gen, 0, 1 << 10); - absl::Uniform<uint32_t>(*gen, 0, 1 << 10); - absl::Uniform<int64_t>(*gen, 0, 1 << 10); - absl::Uniform<uint64_t>(*gen, 0, 1 << 10); - - absl::Uniform<float>(*gen, 0.0, 1.0); - absl::Uniform<float>(*gen, 0, 1); - absl::Uniform<float>(*gen, -1, 1); - absl::Uniform<double>(*gen, 0.0, 1.0); - - absl::Uniform<float>(*gen, -1.0, 0); - absl::Uniform<double>(*gen, -1.0, 0); - - // Tagged - absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1); - absl::Uniform<double>(absl::IntervalClosedOpen, *gen, 0, 1); - absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1); - absl::Uniform<double>(absl::IntervalOpenClosed, *gen, 0, 1); - absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1); - absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1); - - absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100); - absl::Uniform<int>(absl::IntervalClosedOpen, *gen, 0, 100); - absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100); - absl::Uniform<int>(absl::IntervalOpenClosed, *gen, 0, 100); - absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100); - absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100); - - // With *generator as an R-value reference. - absl::Uniform<int>(URBG(), 0, 100); - absl::Uniform<double>(URBG(), 0.0, 1.0); -} - -template <typename URBG> -void TestExponential(URBG* gen) { - absl::Exponential<float>(*gen); - absl::Exponential<double>(*gen); - absl::Exponential<double>(URBG()); -} - -template <typename URBG> -void TestPoisson(URBG* gen) { - // [rand.dist.pois] Indicates that the std::poisson_distribution - // is parameterized by IntType, however MSVC does not allow 8-bit - // types. - absl::Poisson<int>(*gen); - absl::Poisson<int16_t>(*gen); - absl::Poisson<uint16_t>(*gen); - absl::Poisson<int32_t>(*gen); - absl::Poisson<uint32_t>(*gen); - absl::Poisson<int64_t>(*gen); - absl::Poisson<uint64_t>(*gen); - absl::Poisson<uint64_t>(URBG()); -} - -template <typename URBG> -void TestBernoulli(URBG* gen) { - absl::Bernoulli(*gen, 0.5); - absl::Bernoulli(*gen, 0.5); -} - -template <typename URBG> -void TestZipf(URBG* gen) { - absl::Zipf<int>(*gen, 100); - absl::Zipf<int8_t>(*gen, 100); - absl::Zipf<int16_t>(*gen, 100); - absl::Zipf<uint16_t>(*gen, 100); - absl::Zipf<int32_t>(*gen, 1 << 10); - absl::Zipf<uint32_t>(*gen, 1 << 10); - absl::Zipf<int64_t>(*gen, 1 << 10); - absl::Zipf<uint64_t>(*gen, 1 << 10); - absl::Zipf<uint64_t>(URBG(), 1 << 10); -} - -template <typename URBG> -void TestGaussian(URBG* gen) { - absl::Gaussian<float>(*gen, 1.0, 1.0); - absl::Gaussian<double>(*gen, 1.0, 1.0); - absl::Gaussian<double>(URBG(), 1.0, 1.0); -} - -template <typename URBG> -void TestLogNormal(URBG* gen) { - absl::LogUniform<int>(*gen, 0, 100); - absl::LogUniform<int8_t>(*gen, 0, 100); - absl::LogUniform<int16_t>(*gen, 0, 100); - absl::LogUniform<uint16_t>(*gen, 0, 100); - absl::LogUniform<int32_t>(*gen, 0, 1 << 10); - absl::LogUniform<uint32_t>(*gen, 0, 1 << 10); - absl::LogUniform<int64_t>(*gen, 0, 1 << 10); - absl::LogUniform<uint64_t>(*gen, 0, 1 << 10); - absl::LogUniform<uint64_t>(URBG(), 0, 1 << 10); -} - -template <typename URBG> -void CompatibilityTest() { - URBG gen; - - TestUniform(&gen); - TestExponential(&gen); - TestPoisson(&gen); - TestBernoulli(&gen); - TestZipf(&gen); - TestGaussian(&gen); - TestLogNormal(&gen); -} - -TEST(std_mt19937_64, Compatibility) { - // Validate with std::mt19937_64 - CompatibilityTest<std::mt19937_64>(); -} - -TEST(BitGen, Compatibility) { - // Validate with absl::BitGen - CompatibilityTest<absl::BitGen>(); -} - -TEST(InsecureBitGen, Compatibility) { - // Validate with absl::InsecureBitGen - CompatibilityTest<absl::InsecureBitGen>(); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/BUILD.bazel b/third_party/abseil_cpp/absl/random/internal/BUILD.bazel deleted file mode 100644 index 8485e28b010b..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/BUILD.bazel +++ /dev/null @@ -1,730 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") - -# Internal-only implementation classes for Abseil Random -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_RANDOM_RANDEN_COPTS", - "ABSL_TEST_COPTS", - "absl_random_randen_copts_init", -) - -package(default_visibility = [ - "//absl/random:__pkg__", -]) - -licenses(["notice"]) - -cc_library( - name = "traits", - hdrs = ["traits.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], -) - -cc_library( - name = "distribution_caller", - hdrs = ["distribution_caller.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:fast_type_id", - "//absl/utility", - ], -) - -cc_library( - name = "fast_uniform_bits", - hdrs = [ - "fast_uniform_bits.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "seed_material", - srcs = [ - "seed_material.cc", - ], - hdrs = [ - "seed_material.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS + select({ - "//absl:windows": ["-DEFAULTLIB:bcrypt.lib"], - "//conditions:default": [], - }), - deps = [ - ":fast_uniform_bits", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/strings", - "//absl/types:optional", - "//absl/types:span", - ], -) - -cc_library( - name = "pool_urbg", - srcs = [ - "pool_urbg.cc", - ], - hdrs = [ - "pool_urbg.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = select({ - "//absl:windows": [], - "//absl:wasm": [], - "//conditions:default": ["-pthread"], - }) + ABSL_DEFAULT_LINKOPTS, - deps = [ - ":randen", - ":seed_material", - ":traits", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/base:raw_logging_internal", - "//absl/random:seed_gen_exception", - "//absl/types:span", - ], -) - -cc_library( - name = "explicit_seed_seq", - testonly = 1, - hdrs = [ - "explicit_seed_seq.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], -) - -cc_library( - name = "sequence_urbg", - testonly = 1, - hdrs = [ - "sequence_urbg.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], -) - -cc_library( - name = "salted_seed_seq", - hdrs = [ - "salted_seed_seq.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":seed_material", - "//absl/container:inlined_vector", - "//absl/meta:type_traits", - "//absl/types:optional", - "//absl/types:span", - ], -) - -cc_library( - name = "iostream_state_saver", - hdrs = ["iostream_state_saver.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/meta:type_traits", - "//absl/numeric:int128", - ], -) - -cc_library( - name = "generate_real", - hdrs = [ - "generate_real.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fastmath", - ":traits", - "//absl/base:bits", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "fastmath", - hdrs = [ - "fastmath.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:bits"], -) - -cc_library( - name = "wide_multiply", - hdrs = ["wide_multiply.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":traits", - "//absl/base:bits", - "//absl/base:config", - "//absl/numeric:int128", - ], -) - -cc_library( - name = "nonsecure_base", - hdrs = ["nonsecure_base.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":pool_urbg", - ":salted_seed_seq", - ":seed_material", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/types:optional", - "//absl/types:span", - ], -) - -cc_library( - name = "pcg_engine", - hdrs = ["pcg_engine.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fastmath", - ":iostream_state_saver", - "//absl/base:config", - "//absl/meta:type_traits", - "//absl/numeric:int128", - ], -) - -cc_library( - name = "randen_engine", - hdrs = ["randen_engine.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":iostream_state_saver", - ":randen", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "platform", - srcs = [ - "randen_round_keys.cc", - ], - hdrs = [ - "randen_traits.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - textual_hdrs = [ - "platform.h", - ], - deps = ["//absl/base:config"], -) - -cc_library( - name = "randen", - srcs = [ - "randen.cc", - ], - hdrs = [ - "randen.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":platform", - ":randen_hwaes", - ":randen_slow", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "randen_slow", - srcs = ["randen_slow.cc"], - hdrs = ["randen_slow.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":platform", - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -absl_random_randen_copts_init() - -cc_library( - name = "randen_hwaes", - srcs = [ - "randen_detect.cc", - ], - hdrs = [ - "randen_detect.h", - "randen_hwaes.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":platform", - ":randen_hwaes_impl", - "//absl/base:config", - ], -) - -# build with --save_temps to see assembly language output. -cc_library( - name = "randen_hwaes_impl", - srcs = [ - "randen_hwaes.cc", - "randen_hwaes.h", - ], - copts = ABSL_DEFAULT_COPTS + ABSL_RANDOM_RANDEN_COPTS + select({ - "//absl:windows": [], - "//conditions:default": ["-Wno-pass-failed"], - }), - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":platform", - "//absl/base:config", - "//absl/base:core_headers", - ], -) - -cc_binary( - name = "gaussian_distribution_gentables", - srcs = [ - "gaussian_distribution_gentables.cc", - ], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:core_headers", - "//absl/random:distributions", - ], -) - -cc_library( - name = "distribution_test_util", - testonly = 1, - srcs = [ - "chi_square.cc", - "distribution_test_util.cc", - ], - hdrs = [ - "chi_square.h", - "distribution_test_util.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/strings", - "//absl/strings:str_format", - "//absl/types:span", - ], -) - -# Common tags for tests, etc. -ABSL_RANDOM_NONPORTABLE_TAGS = [ - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - "no_test_darwin_x86_64", - "no_test_ios_x86_64", - "no_test_loonix", - "no_test_msvc_x64", - "no_test_wasm", -] - -cc_test( - name = "traits_test", - size = "small", - srcs = ["traits_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "generate_real_test", - size = "small", - srcs = [ - "generate_real_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":generate_real", - "//absl/base:bits", - "//absl/flags:flag", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "distribution_test_util_test", - size = "small", - srcs = ["distribution_test_util_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distribution_test_util", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "fastmath_test", - size = "small", - srcs = ["fastmath_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fastmath", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "explicit_seed_seq_test", - size = "small", - srcs = ["explicit_seed_seq_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":explicit_seed_seq", - "//absl/random:seed_sequences", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "salted_seed_seq_test", - size = "small", - srcs = ["salted_seed_seq_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":salted_seed_seq", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "chi_square_test", - size = "small", - srcs = [ - "chi_square_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":distribution_test_util", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "fast_uniform_bits_test", - size = "small", - srcs = [ - "fast_uniform_bits_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":fast_uniform_bits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "mock_helpers", - hdrs = ["mock_helpers.h"], - deps = [ - "//absl/base:fast_type_id", - "//absl/types:optional", - ], -) - -cc_library( - name = "mock_overload_set", - testonly = 1, - hdrs = ["mock_overload_set.h"], - deps = [ - ":mock_helpers", - "//absl/random:mocking_bit_gen", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "nonsecure_base_test", - size = "small", - srcs = [ - "nonsecure_base_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":nonsecure_base", - "//absl/random", - "//absl/random:distributions", - "//absl/random:seed_sequences", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "seed_material_test", - size = "small", - srcs = ["seed_material_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":seed_material", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "pool_urbg_test", - size = "small", - srcs = [ - "pool_urbg_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":pool_urbg", - "//absl/meta:type_traits", - "//absl/types:span", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "pcg_engine_test", - size = "medium", # Trying to measure accuracy. - srcs = ["pcg_engine_test.cc"], - copts = ABSL_TEST_COPTS, - flaky = 1, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":explicit_seed_seq", - ":pcg_engine", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "randen_engine_test", - size = "medium", - srcs = [ - "randen_engine_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":explicit_seed_seq", - ":randen_engine", - "//absl/base:raw_logging_internal", - "//absl/strings", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "randen_test", - size = "small", - srcs = ["randen_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":randen", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "randen_slow_test", - size = "small", - srcs = ["randen_slow_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":platform", - ":randen_slow", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "randen_hwaes_test", - size = "small", - srcs = ["randen_hwaes_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ABSL_RANDOM_NONPORTABLE_TAGS, - deps = [ - ":platform", - ":randen_hwaes", - ":randen_hwaes_impl", # build_cleaner: keep - "//absl/base:raw_logging_internal", - "//absl/strings:str_format", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "wide_multiply_test", - size = "small", - srcs = ["wide_multiply_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":wide_multiply", - "//absl/base:bits", - "//absl/numeric:int128", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "nanobenchmark", - srcs = ["nanobenchmark.cc"], - linkopts = ABSL_DEFAULT_LINKOPTS, - textual_hdrs = ["nanobenchmark.h"], - deps = [ - ":platform", - ":randen_engine", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "uniform_helper", - hdrs = ["uniform_helper.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":traits", - "//absl/base:config", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "nanobenchmark_test", - size = "small", - srcs = ["nanobenchmark_test.cc"], - flaky = 1, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = [ - "benchmark", - "no_test_ios_x86_64", - "no_test_loonix", # Crashing. - ], - deps = [ - ":nanobenchmark", - "//absl/base:raw_logging_internal", - "//absl/strings", - ], -) - -cc_test( - name = "randen_benchmarks", - size = "medium", - timeout = "long", - srcs = ["randen_benchmarks.cc"], - copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS, - flaky = 1, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ABSL_RANDOM_NONPORTABLE_TAGS + ["benchmark"], - deps = [ - ":nanobenchmark", - ":platform", - ":randen", - ":randen_engine", - ":randen_hwaes", - ":randen_hwaes_impl", - ":randen_slow", - "//absl/base:raw_logging_internal", - "//absl/strings", - ], -) - -cc_test( - name = "iostream_state_saver_test", - size = "small", - srcs = ["iostream_state_saver_test.cc"], - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":iostream_state_saver", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "uniform_helper_test", - size = "small", - srcs = ["uniform_helper_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":uniform_helper", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/random/internal/chi_square.cc b/third_party/abseil_cpp/absl/random/internal/chi_square.cc deleted file mode 100644 index 640d48cea6f4..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/chi_square.cc +++ /dev/null @@ -1,232 +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/chi_square.h" - -#include <cmath> - -#include "absl/random/internal/distribution_test_util.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -#if defined(__EMSCRIPTEN__) -// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found. -inline double fma(double x, double y, double z) { - return (x * y) + z; -} -#endif - -// Use Horner's method to evaluate a polynomial. -template <typename T, unsigned N> -inline T EvaluatePolynomial(T x, const T (&poly)[N]) { -#if !defined(__EMSCRIPTEN__) - using std::fma; -#endif - T p = poly[N - 1]; - for (unsigned i = 2; i <= N; i++) { - p = fma(p, x, poly[N - i]); - } - return p; -} - -static constexpr int kLargeDOF = 150; - -// Returns the probability of a normal z-value. -// -// Adapted from the POZ function in: -// Ibbetson D, Algorithm 209 -// Collected Algorithms of the CACM 1963 p. 616 -// -double POZ(double z) { - static constexpr double kP1[] = { - 0.797884560593, -0.531923007300, 0.319152932694, - -0.151968751364, 0.059054035642, -0.019198292004, - 0.005198775019, -0.001075204047, 0.000124818987, - }; - static constexpr double kP2[] = { - 0.999936657524, 0.000535310849, -0.002141268741, 0.005353579108, - -0.009279453341, 0.011630447319, -0.010557625006, 0.006549791214, - -0.002034254874, -0.000794620820, 0.001390604284, -0.000676904986, - -0.000019538132, 0.000152529290, -0.000045255659, - }; - - const double kZMax = 6.0; // Maximum meaningful z-value. - if (z == 0.0) { - return 0.5; - } - double x; - double y = 0.5 * std::fabs(z); - if (y >= (kZMax * 0.5)) { - x = 1.0; - } else if (y < 1.0) { - double w = y * y; - x = EvaluatePolynomial(w, kP1) * y * 2.0; - } else { - y -= 2.0; - x = EvaluatePolynomial(y, kP2); - } - return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5); -} - -// Approximates the survival function of the normal distribution. -// -// Algorithm 26.2.18, from: -// [Abramowitz and Stegun, Handbook of Mathematical Functions,p.932] -// http://people.math.sfu.ca/~cbm/aands/abramowitz_and_stegun.pdf -// -double normal_survival(double z) { - // Maybe replace with the alternate formulation. - // 0.5 * erfc((x - mean)/(sqrt(2) * sigma)) - static constexpr double kR[] = { - 1.0, 0.196854, 0.115194, 0.000344, 0.019527, - }; - double r = EvaluatePolynomial(z, kR); - r *= r; - return 0.5 / (r * r); -} - -} // namespace - -// Calculates the critical chi-square value given degrees-of-freedom and a -// p-value, usually using bisection. Also known by the name CRITCHI. -double ChiSquareValue(int dof, double p) { - static constexpr double kChiEpsilon = - 0.000001; // Accuracy of the approximation. - static constexpr double kChiMax = - 99999.0; // Maximum chi-squared value. - - const double p_value = 1.0 - p; - if (dof < 1 || p_value > 1.0) { - return 0.0; - } - - if (dof > kLargeDOF) { - // For large degrees of freedom, use the normal approximation by - // Wilson, E. B. and Hilferty, M. M. (1931) - // chi^2 - mean - // Z = -------------- - // stddev - const double z = InverseNormalSurvival(p_value); - const double mean = 1 - 2.0 / (9 * dof); - const double variance = 2.0 / (9 * dof); - // Cannot use this method if the variance is 0. - if (variance != 0) { - return std::pow(z * std::sqrt(variance) + mean, 3.0) * dof; - } - } - - if (p_value <= 0.0) return kChiMax; - - // Otherwise search for the p value by bisection - double min_chisq = 0.0; - double max_chisq = kChiMax; - double current = dof / std::sqrt(p_value); - while ((max_chisq - min_chisq) > kChiEpsilon) { - if (ChiSquarePValue(current, dof) < p_value) { - max_chisq = current; - } else { - min_chisq = current; - } - current = (max_chisq + min_chisq) * 0.5; - } - return current; -} - -// Calculates the p-value (probability) of a given chi-square value -// and degrees of freedom. -// -// Adapted from the POCHISQ function from: -// Hill, I. D. and Pike, M. C. Algorithm 299 -// Collected Algorithms of the CACM 1963 p. 243 -// -double ChiSquarePValue(double chi_square, int dof) { - static constexpr double kLogSqrtPi = - 0.5723649429247000870717135; // Log[Sqrt[Pi]] - static constexpr double kInverseSqrtPi = - 0.5641895835477562869480795; // 1/(Sqrt[Pi]) - - // For large degrees of freedom, use the normal approximation by - // Wilson, E. B. and Hilferty, M. M. (1931) - // Via Wikipedia: - // By the Central Limit Theorem, because the chi-square distribution is the - // sum of k independent random variables with finite mean and variance, it - // converges to a normal distribution for large k. - if (dof > kLargeDOF) { - // Re-scale everything. - const double chi_square_scaled = std::pow(chi_square / dof, 1.0 / 3); - const double mean = 1 - 2.0 / (9 * dof); - const double variance = 2.0 / (9 * dof); - // If variance is 0, this method cannot be used. - if (variance != 0) { - const double z = (chi_square_scaled - mean) / std::sqrt(variance); - if (z > 0) { - return normal_survival(z); - } else if (z < 0) { - return 1.0 - normal_survival(-z); - } else { - return 0.5; - } - } - } - - // The chi square function is >= 0 for any degrees of freedom. - // In other words, probability that the chi square function >= 0 is 1. - if (chi_square <= 0.0) return 1.0; - - // If the degrees of freedom is zero, the chi square function is always 0 by - // definition. In other words, the probability that the chi square function - // is > 0 is zero (chi square values <= 0 have been filtered above). - if (dof < 1) return 0; - - auto capped_exp = [](double x) { return x < -20 ? 0.0 : std::exp(x); }; - static constexpr double kBigX = 20; - - double a = 0.5 * chi_square; - const bool even = !(dof & 1); // True if dof is an even number. - const double y = capped_exp(-a); - double s = even ? y : (2.0 * POZ(-std::sqrt(chi_square))); - - if (dof <= 2) { - return s; - } - - chi_square = 0.5 * (dof - 1.0); - double z = (even ? 1.0 : 0.5); - if (a > kBigX) { - double e = (even ? 0.0 : kLogSqrtPi); - double c = std::log(a); - while (z <= chi_square) { - e = std::log(z) + e; - s += capped_exp(c * z - a - e); - z += 1.0; - } - return s; - } - - double e = (even ? 1.0 : (kInverseSqrtPi / std::sqrt(a))); - double c = 0.0; - while (z <= chi_square) { - e = e * (a / z); - c = c + e; - z += 1.0; - } - return c * y + s; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/chi_square.h b/third_party/abseil_cpp/absl/random/internal/chi_square.h deleted file mode 100644 index 07f4fbe52298..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/chi_square.h +++ /dev/null @@ -1,89 +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. - -#ifndef ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_ -#define ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_ - -// The chi-square statistic. -// -// Useful for evaluating if `D` independent random variables are behaving as -// expected, or if two distributions are similar. (`D` is the degrees of -// freedom). -// -// Each bucket should have an expected count of 10 or more for the chi square to -// be meaningful. - -#include <cassert> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -constexpr const char kChiSquared[] = "chi-squared"; - -// Returns the measured chi square value, using a single expected value. This -// assumes that the values in [begin, end) are uniformly distributed. -template <typename Iterator> -double ChiSquareWithExpected(Iterator begin, Iterator end, double expected) { - // Compute the sum and the number of buckets. - assert(expected >= 10); // require at least 10 samples per bucket. - double chi_square = 0; - for (auto it = begin; it != end; it++) { - double d = static_cast<double>(*it) - expected; - chi_square += d * d; - } - chi_square = chi_square / expected; - return chi_square; -} - -// Returns the measured chi square value, taking the actual value of each bucket -// from the first set of iterators, and the expected value of each bucket from -// the second set of iterators. -template <typename Iterator, typename Expected> -double ChiSquare(Iterator it, Iterator end, Expected eit, Expected eend) { - double chi_square = 0; - for (; it != end && eit != eend; ++it, ++eit) { - if (*it > 0) { - assert(*eit > 0); - } - double e = static_cast<double>(*eit); - double d = static_cast<double>(*it - *eit); - if (d != 0) { - assert(e > 0); - chi_square += (d * d) / e; - } - } - assert(it == end && eit == eend); - return chi_square; -} - -// ====================================================================== -// The following methods can be used for an arbitrary significance level. -// - -// Calculates critical chi-square values to produce the given p-value using a -// bisection search for a value within epsilon, relying on the monotonicity of -// ChiSquarePValue(). -double ChiSquareValue(int dof, double p); - -// Calculates the p-value (probability) of a given chi-square value. -double ChiSquarePValue(double chi_square, int dof); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/chi_square_test.cc b/third_party/abseil_cpp/absl/random/internal/chi_square_test.cc deleted file mode 100644 index 5025defac12c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/chi_square_test.cc +++ /dev/null @@ -1,365 +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/chi_square.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <numeric> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/macros.h" - -using absl::random_internal::ChiSquare; -using absl::random_internal::ChiSquarePValue; -using absl::random_internal::ChiSquareValue; -using absl::random_internal::ChiSquareWithExpected; - -namespace { - -TEST(ChiSquare, Value) { - struct { - int line; - double chi_square; - int df; - double confidence; - } const specs[] = { - // Testing lookup at 1% confidence - {__LINE__, 0, 0, 0.01}, - {__LINE__, 0.00016, 1, 0.01}, - {__LINE__, 1.64650, 8, 0.01}, - {__LINE__, 5.81221, 16, 0.01}, - {__LINE__, 156.4319, 200, 0.01}, - {__LINE__, 1121.3784, 1234, 0.01}, - {__LINE__, 53557.1629, 54321, 0.01}, - {__LINE__, 651662.6647, 654321, 0.01}, - - // Testing lookup at 99% confidence - {__LINE__, 0, 0, 0.99}, - {__LINE__, 6.635, 1, 0.99}, - {__LINE__, 20.090, 8, 0.99}, - {__LINE__, 32.000, 16, 0.99}, - {__LINE__, 249.4456, 200, 0.99}, - {__LINE__, 1131.1573, 1023, 0.99}, - {__LINE__, 1352.5038, 1234, 0.99}, - {__LINE__, 55090.7356, 54321, 0.99}, - {__LINE__, 656985.1514, 654321, 0.99}, - - // Testing lookup at 99.9% confidence - {__LINE__, 16.2659, 3, 0.999}, - {__LINE__, 22.4580, 6, 0.999}, - {__LINE__, 267.5409, 200, 0.999}, - {__LINE__, 1168.5033, 1023, 0.999}, - {__LINE__, 55345.1741, 54321, 0.999}, - {__LINE__, 657861.7284, 654321, 0.999}, - {__LINE__, 51.1772, 24, 0.999}, - {__LINE__, 59.7003, 30, 0.999}, - {__LINE__, 37.6984, 15, 0.999}, - {__LINE__, 29.5898, 10, 0.999}, - {__LINE__, 27.8776, 9, 0.999}, - - // Testing lookup at random confidences - {__LINE__, 0.000157088, 1, 0.01}, - {__LINE__, 5.31852, 2, 0.93}, - {__LINE__, 1.92256, 4, 0.25}, - {__LINE__, 10.7709, 13, 0.37}, - {__LINE__, 26.2514, 17, 0.93}, - {__LINE__, 36.4799, 29, 0.84}, - {__LINE__, 25.818, 31, 0.27}, - {__LINE__, 63.3346, 64, 0.50}, - {__LINE__, 196.211, 128, 0.9999}, - {__LINE__, 215.21, 243, 0.10}, - {__LINE__, 285.393, 256, 0.90}, - {__LINE__, 984.504, 1024, 0.1923}, - {__LINE__, 2043.85, 2048, 0.4783}, - {__LINE__, 48004.6, 48273, 0.194}, - }; - for (const auto& spec : specs) { - SCOPED_TRACE(spec.line); - // Verify all values are have at most a 1% relative error. - const double val = ChiSquareValue(spec.df, spec.confidence); - const double err = std::max(5e-6, spec.chi_square / 5e3); // 1 part in 5000 - EXPECT_NEAR(spec.chi_square, val, err) << spec.line; - } - - // Relaxed test for extreme values, from - // http://www.ciphersbyritter.com/JAVASCRP/NORMCHIK.HTM#ChiSquare - EXPECT_NEAR(49.2680, ChiSquareValue(100, 1e-6), 5); // 0.000'005 mark - EXPECT_NEAR(123.499, ChiSquareValue(200, 1e-6), 5); // 0.000'005 mark - - EXPECT_NEAR(149.449, ChiSquareValue(100, 0.999), 0.01); - EXPECT_NEAR(161.318, ChiSquareValue(100, 0.9999), 0.01); - EXPECT_NEAR(172.098, ChiSquareValue(100, 0.99999), 0.01); - - EXPECT_NEAR(381.426, ChiSquareValue(300, 0.999), 0.05); - EXPECT_NEAR(399.756, ChiSquareValue(300, 0.9999), 0.1); - EXPECT_NEAR(416.126, ChiSquareValue(300, 0.99999), 0.2); -} - -TEST(ChiSquareTest, PValue) { - struct { - int line; - double pval; - double chi_square; - int df; - } static const specs[] = { - {__LINE__, 1, 0, 0}, - {__LINE__, 0, 0.001, 0}, - {__LINE__, 1.000, 0, 453}, - {__LINE__, 0.134471, 7972.52, 7834}, - {__LINE__, 0.203922, 28.32, 23}, - {__LINE__, 0.737171, 48274, 48472}, - {__LINE__, 0.444146, 583.1234, 579}, - {__LINE__, 0.294814, 138.2, 130}, - {__LINE__, 0.0816532, 12.63, 7}, - {__LINE__, 0, 682.32, 67}, - {__LINE__, 0.49405, 999, 999}, - {__LINE__, 1.000, 0, 9999}, - {__LINE__, 0.997477, 0.00001, 1}, - {__LINE__, 0, 5823.21, 5040}, - }; - for (const auto& spec : specs) { - SCOPED_TRACE(spec.line); - const double pval = ChiSquarePValue(spec.chi_square, spec.df); - EXPECT_NEAR(spec.pval, pval, 1e-3); - } -} - -TEST(ChiSquareTest, CalcChiSquare) { - struct { - int line; - std::vector<int> expected; - std::vector<int> actual; - } const specs[] = { - {__LINE__, - {56, 234, 76, 1, 546, 1, 87, 345, 1, 234}, - {2, 132, 4, 43, 234, 8, 345, 8, 236, 56}}, - {__LINE__, - {123, 36, 234, 367, 345, 2, 456, 567, 234, 567}, - {123, 56, 2345, 8, 345, 8, 2345, 23, 48, 267}}, - {__LINE__, - {123, 234, 345, 456, 567, 678, 789, 890, 98, 76}, - {123, 234, 345, 456, 567, 678, 789, 890, 98, 76}}, - {__LINE__, {3, 675, 23, 86, 2, 8, 2}, {456, 675, 23, 86, 23, 65, 2}}, - {__LINE__, {1}, {23}}, - }; - for (const auto& spec : specs) { - SCOPED_TRACE(spec.line); - double chi_square = 0; - for (int i = 0; i < spec.expected.size(); ++i) { - const double diff = spec.actual[i] - spec.expected[i]; - chi_square += (diff * diff) / spec.expected[i]; - } - EXPECT_NEAR(chi_square, - ChiSquare(std::begin(spec.actual), std::end(spec.actual), - std::begin(spec.expected), std::end(spec.expected)), - 1e-5); - } -} - -TEST(ChiSquareTest, CalcChiSquareInt64) { - const int64_t data[3] = {910293487, 910292491, 910216780}; - // $ python -c "import scipy.stats - // > print scipy.stats.chisquare([910293487, 910292491, 910216780])[0]" - // 4.25410123524 - double sum = std::accumulate(std::begin(data), std::end(data), double{0}); - size_t n = std::distance(std::begin(data), std::end(data)); - double a = ChiSquareWithExpected(std::begin(data), std::end(data), sum / n); - EXPECT_NEAR(4.254101, a, 1e-6); - - // ... Or with known values. - double b = - ChiSquareWithExpected(std::begin(data), std::end(data), 910267586.0); - EXPECT_NEAR(4.254101, b, 1e-6); -} - -TEST(ChiSquareTest, TableData) { - // Test data from - // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm - // 0.90 0.95 0.975 0.99 0.999 - const double data[100][5] = { - /* 1*/ {2.706, 3.841, 5.024, 6.635, 10.828}, - /* 2*/ {4.605, 5.991, 7.378, 9.210, 13.816}, - /* 3*/ {6.251, 7.815, 9.348, 11.345, 16.266}, - /* 4*/ {7.779, 9.488, 11.143, 13.277, 18.467}, - /* 5*/ {9.236, 11.070, 12.833, 15.086, 20.515}, - /* 6*/ {10.645, 12.592, 14.449, 16.812, 22.458}, - /* 7*/ {12.017, 14.067, 16.013, 18.475, 24.322}, - /* 8*/ {13.362, 15.507, 17.535, 20.090, 26.125}, - /* 9*/ {14.684, 16.919, 19.023, 21.666, 27.877}, - /*10*/ {15.987, 18.307, 20.483, 23.209, 29.588}, - /*11*/ {17.275, 19.675, 21.920, 24.725, 31.264}, - /*12*/ {18.549, 21.026, 23.337, 26.217, 32.910}, - /*13*/ {19.812, 22.362, 24.736, 27.688, 34.528}, - /*14*/ {21.064, 23.685, 26.119, 29.141, 36.123}, - /*15*/ {22.307, 24.996, 27.488, 30.578, 37.697}, - /*16*/ {23.542, 26.296, 28.845, 32.000, 39.252}, - /*17*/ {24.769, 27.587, 30.191, 33.409, 40.790}, - /*18*/ {25.989, 28.869, 31.526, 34.805, 42.312}, - /*19*/ {27.204, 30.144, 32.852, 36.191, 43.820}, - /*20*/ {28.412, 31.410, 34.170, 37.566, 45.315}, - /*21*/ {29.615, 32.671, 35.479, 38.932, 46.797}, - /*22*/ {30.813, 33.924, 36.781, 40.289, 48.268}, - /*23*/ {32.007, 35.172, 38.076, 41.638, 49.728}, - /*24*/ {33.196, 36.415, 39.364, 42.980, 51.179}, - /*25*/ {34.382, 37.652, 40.646, 44.314, 52.620}, - /*26*/ {35.563, 38.885, 41.923, 45.642, 54.052}, - /*27*/ {36.741, 40.113, 43.195, 46.963, 55.476}, - /*28*/ {37.916, 41.337, 44.461, 48.278, 56.892}, - /*29*/ {39.087, 42.557, 45.722, 49.588, 58.301}, - /*30*/ {40.256, 43.773, 46.979, 50.892, 59.703}, - /*31*/ {41.422, 44.985, 48.232, 52.191, 61.098}, - /*32*/ {42.585, 46.194, 49.480, 53.486, 62.487}, - /*33*/ {43.745, 47.400, 50.725, 54.776, 63.870}, - /*34*/ {44.903, 48.602, 51.966, 56.061, 65.247}, - /*35*/ {46.059, 49.802, 53.203, 57.342, 66.619}, - /*36*/ {47.212, 50.998, 54.437, 58.619, 67.985}, - /*37*/ {48.363, 52.192, 55.668, 59.893, 69.347}, - /*38*/ {49.513, 53.384, 56.896, 61.162, 70.703}, - /*39*/ {50.660, 54.572, 58.120, 62.428, 72.055}, - /*40*/ {51.805, 55.758, 59.342, 63.691, 73.402}, - /*41*/ {52.949, 56.942, 60.561, 64.950, 74.745}, - /*42*/ {54.090, 58.124, 61.777, 66.206, 76.084}, - /*43*/ {55.230, 59.304, 62.990, 67.459, 77.419}, - /*44*/ {56.369, 60.481, 64.201, 68.710, 78.750}, - /*45*/ {57.505, 61.656, 65.410, 69.957, 80.077}, - /*46*/ {58.641, 62.830, 66.617, 71.201, 81.400}, - /*47*/ {59.774, 64.001, 67.821, 72.443, 82.720}, - /*48*/ {60.907, 65.171, 69.023, 73.683, 84.037}, - /*49*/ {62.038, 66.339, 70.222, 74.919, 85.351}, - /*50*/ {63.167, 67.505, 71.420, 76.154, 86.661}, - /*51*/ {64.295, 68.669, 72.616, 77.386, 87.968}, - /*52*/ {65.422, 69.832, 73.810, 78.616, 89.272}, - /*53*/ {66.548, 70.993, 75.002, 79.843, 90.573}, - /*54*/ {67.673, 72.153, 76.192, 81.069, 91.872}, - /*55*/ {68.796, 73.311, 77.380, 82.292, 93.168}, - /*56*/ {69.919, 74.468, 78.567, 83.513, 94.461}, - /*57*/ {71.040, 75.624, 79.752, 84.733, 95.751}, - /*58*/ {72.160, 76.778, 80.936, 85.950, 97.039}, - /*59*/ {73.279, 77.931, 82.117, 87.166, 98.324}, - /*60*/ {74.397, 79.082, 83.298, 88.379, 99.607}, - /*61*/ {75.514, 80.232, 84.476, 89.591, 100.888}, - /*62*/ {76.630, 81.381, 85.654, 90.802, 102.166}, - /*63*/ {77.745, 82.529, 86.830, 92.010, 103.442}, - /*64*/ {78.860, 83.675, 88.004, 93.217, 104.716}, - /*65*/ {79.973, 84.821, 89.177, 94.422, 105.988}, - /*66*/ {81.085, 85.965, 90.349, 95.626, 107.258}, - /*67*/ {82.197, 87.108, 91.519, 96.828, 108.526}, - /*68*/ {83.308, 88.250, 92.689, 98.028, 109.791}, - /*69*/ {84.418, 89.391, 93.856, 99.228, 111.055}, - /*70*/ {85.527, 90.531, 95.023, 100.425, 112.317}, - /*71*/ {86.635, 91.670, 96.189, 101.621, 113.577}, - /*72*/ {87.743, 92.808, 97.353, 102.816, 114.835}, - /*73*/ {88.850, 93.945, 98.516, 104.010, 116.092}, - /*74*/ {89.956, 95.081, 99.678, 105.202, 117.346}, - /*75*/ {91.061, 96.217, 100.839, 106.393, 118.599}, - /*76*/ {92.166, 97.351, 101.999, 107.583, 119.850}, - /*77*/ {93.270, 98.484, 103.158, 108.771, 121.100}, - /*78*/ {94.374, 99.617, 104.316, 109.958, 122.348}, - /*79*/ {95.476, 100.749, 105.473, 111.144, 123.594}, - /*80*/ {96.578, 101.879, 106.629, 112.329, 124.839}, - /*81*/ {97.680, 103.010, 107.783, 113.512, 126.083}, - /*82*/ {98.780, 104.139, 108.937, 114.695, 127.324}, - /*83*/ {99.880, 105.267, 110.090, 115.876, 128.565}, - /*84*/ {100.980, 106.395, 111.242, 117.057, 129.804}, - /*85*/ {102.079, 107.522, 112.393, 118.236, 131.041}, - /*86*/ {103.177, 108.648, 113.544, 119.414, 132.277}, - /*87*/ {104.275, 109.773, 114.693, 120.591, 133.512}, - /*88*/ {105.372, 110.898, 115.841, 121.767, 134.746}, - /*89*/ {106.469, 112.022, 116.989, 122.942, 135.978}, - /*90*/ {107.565, 113.145, 118.136, 124.116, 137.208}, - /*91*/ {108.661, 114.268, 119.282, 125.289, 138.438}, - /*92*/ {109.756, 115.390, 120.427, 126.462, 139.666}, - /*93*/ {110.850, 116.511, 121.571, 127.633, 140.893}, - /*94*/ {111.944, 117.632, 122.715, 128.803, 142.119}, - /*95*/ {113.038, 118.752, 123.858, 129.973, 143.344}, - /*96*/ {114.131, 119.871, 125.000, 131.141, 144.567}, - /*97*/ {115.223, 120.990, 126.141, 132.309, 145.789}, - /*98*/ {116.315, 122.108, 127.282, 133.476, 147.010}, - /*99*/ {117.407, 123.225, 128.422, 134.642, 148.230}, - /*100*/ {118.498, 124.342, 129.561, 135.807, 149.449} - /**/}; - - // 0.90 0.95 0.975 0.99 0.999 - for (int i = 0; i < ABSL_ARRAYSIZE(data); i++) { - const double E = 0.0001; - EXPECT_NEAR(ChiSquarePValue(data[i][0], i + 1), 0.10, E) - << i << " " << data[i][0]; - EXPECT_NEAR(ChiSquarePValue(data[i][1], i + 1), 0.05, E) - << i << " " << data[i][1]; - EXPECT_NEAR(ChiSquarePValue(data[i][2], i + 1), 0.025, E) - << i << " " << data[i][2]; - EXPECT_NEAR(ChiSquarePValue(data[i][3], i + 1), 0.01, E) - << i << " " << data[i][3]; - EXPECT_NEAR(ChiSquarePValue(data[i][4], i + 1), 0.001, E) - << i << " " << data[i][4]; - - const double F = 0.1; - EXPECT_NEAR(ChiSquareValue(i + 1, 0.90), data[i][0], F) << i; - EXPECT_NEAR(ChiSquareValue(i + 1, 0.95), data[i][1], F) << i; - EXPECT_NEAR(ChiSquareValue(i + 1, 0.975), data[i][2], F) << i; - EXPECT_NEAR(ChiSquareValue(i + 1, 0.99), data[i][3], F) << i; - EXPECT_NEAR(ChiSquareValue(i + 1, 0.999), data[i][4], F) << i; - } -} - -TEST(ChiSquareTest, ChiSquareTwoIterator) { - // Test data from http://www.stat.yale.edu/Courses/1997-98/101/chigf.htm - // Null-hypothesis: This data is normally distributed. - const int counts[10] = {6, 6, 18, 33, 38, 38, 28, 21, 9, 3}; - const double expected[10] = {4.6, 8.8, 18.4, 30.0, 38.2, - 38.2, 30.0, 18.4, 8.8, 4.6}; - double chi_square = ChiSquare(std::begin(counts), std::end(counts), - std::begin(expected), std::end(expected)); - EXPECT_NEAR(chi_square, 2.69, 0.001); - - // Degrees of freedom: 10 bins. two estimated parameters. = 10 - 2 - 1. - const int dof = 7; - // The critical value of 7, 95% => 14.067 (see above test) - double p_value_05 = ChiSquarePValue(14.067, dof); - EXPECT_NEAR(p_value_05, 0.05, 0.001); // 95%-ile p-value - - double p_actual = ChiSquarePValue(chi_square, dof); - EXPECT_GT(p_actual, 0.05); // Accept the null hypothesis. -} - -TEST(ChiSquareTest, DiceRolls) { - // Assume we are testing 102 fair dice rolls. - // Null-hypothesis: This data is fairly distributed. - // - // The dof value of 4, @95% = 9.488 (see above test) - // The dof value of 5, @95% = 11.070 - const int rolls[6] = {22, 11, 17, 14, 20, 18}; - double sum = std::accumulate(std::begin(rolls), std::end(rolls), double{0}); - size_t n = std::distance(std::begin(rolls), std::end(rolls)); - - double a = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), sum / n); - EXPECT_NEAR(a, 4.70588, 1e-5); - EXPECT_LT(a, ChiSquareValue(4, 0.95)); - - double p_a = ChiSquarePValue(a, 4); - EXPECT_NEAR(p_a, 0.318828, 1e-5); // Accept the null hypothesis. - - double b = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), 17.0); - EXPECT_NEAR(b, 4.70588, 1e-5); - EXPECT_LT(b, ChiSquareValue(5, 0.95)); - - double p_b = ChiSquarePValue(b, 5); - EXPECT_NEAR(p_b, 0.4528180, 1e-5); // Accept the null hypothesis. -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/distribution_caller.h b/third_party/abseil_cpp/absl/random/internal/distribution_caller.h deleted file mode 100644 index fc81b787ebe2..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/distribution_caller.h +++ /dev/null @@ -1,92 +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. -// - -#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ -#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ - -#include <utility> - -#include "absl/base/config.h" -#include "absl/base/internal/fast_type_id.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// DistributionCaller provides an opportunity to overload the general -// mechanism for calling a distribution, allowing for mock-RNG classes -// to intercept such calls. -template <typename URBG> -struct DistributionCaller { - // SFINAE to detect whether the URBG type includes a member matching - // bool InvokeMock(base_internal::FastTypeIdType, void*, void*). - // - // These live inside BitGenRef so that they have friend access - // to MockingBitGen. (see similar methods in DistributionCaller). - template <template <class...> class Trait, class AlwaysVoid, class... Args> - struct detector : std::false_type {}; - template <template <class...> class Trait, class... Args> - struct detector<Trait, absl::void_t<Trait<Args...>>, Args...> - : std::true_type {}; - - template <class T> - using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock( - std::declval<::absl::base_internal::FastTypeIdType>(), - std::declval<void*>(), std::declval<void*>())); - - using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type; - - // Default implementation of distribution caller. - template <typename DistrT, typename... Args> - static typename DistrT::result_type Impl(std::false_type, URBG* urbg, - Args&&... args) { - DistrT dist(std::forward<Args>(args)...); - return dist(*urbg); - } - - // Mock implementation of distribution caller. - // The underlying KeyT must match the KeyT constructed by MockOverloadSet. - template <typename DistrT, typename... Args> - static typename DistrT::result_type Impl(std::true_type, URBG* urbg, - Args&&... args) { - using ResultT = typename DistrT::result_type; - using ArgTupleT = std::tuple<absl::decay_t<Args>...>; - using KeyT = ResultT(DistrT, ArgTupleT); - - ArgTupleT arg_tuple(std::forward<Args>(args)...); - ResultT result; - if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple, - &result)) { - auto dist = absl::make_from_tuple<DistrT>(arg_tuple); - result = dist(*urbg); - } - return result; - } - - // Default implementation of distribution caller. - template <typename DistrT, typename... Args> - static typename DistrT::result_type Call(URBG* urbg, Args&&... args) { - return Impl<DistrT, Args...>(HasInvokeMock{}, urbg, - std::forward<Args>(args)...); - } -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/distribution_test_util.cc b/third_party/abseil_cpp/absl/random/internal/distribution_test_util.cc deleted file mode 100644 index e9005658c0a7..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/distribution_test_util.cc +++ /dev/null @@ -1,418 +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/distribution_test_util.h" - -#include <cassert> -#include <cmath> -#include <string> -#include <vector> - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -#if defined(__EMSCRIPTEN__) -// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found. -inline double fma(double x, double y, double z) { return (x * y) + z; } -#endif - -} // namespace - -DistributionMoments ComputeDistributionMoments( - absl::Span<const double> data_points) { - DistributionMoments result; - - // Compute m1 - for (double x : data_points) { - result.n++; - result.mean += x; - } - result.mean /= static_cast<double>(result.n); - - // Compute m2, m3, m4 - for (double x : data_points) { - double v = x - result.mean; - result.variance += v * v; - result.skewness += v * v * v; - result.kurtosis += v * v * v * v; - } - result.variance /= static_cast<double>(result.n - 1); - - result.skewness /= static_cast<double>(result.n); - result.skewness /= std::pow(result.variance, 1.5); - - result.kurtosis /= static_cast<double>(result.n); - result.kurtosis /= std::pow(result.variance, 2.0); - return result; - - // When validating the min/max count, the following confidence intervals may - // be of use: - // 3.291 * stddev = 99.9% CI - // 2.576 * stddev = 99% CI - // 1.96 * stddev = 95% CI - // 1.65 * stddev = 90% CI -} - -std::ostream& operator<<(std::ostream& os, const DistributionMoments& moments) { - return os << absl::StrFormat("mean=%f, stddev=%f, skewness=%f, kurtosis=%f", - moments.mean, std::sqrt(moments.variance), - moments.skewness, moments.kurtosis); -} - -double InverseNormalSurvival(double x) { - // inv_sf(u) = -sqrt(2) * erfinv(2u-1) - static constexpr double kSqrt2 = 1.4142135623730950488; - return -kSqrt2 * absl::random_internal::erfinv(2 * x - 1.0); -} - -bool Near(absl::string_view msg, double actual, double expected, double bound) { - assert(bound > 0.0); - double delta = fabs(expected - actual); - if (delta < bound) { - return true; - } - - std::string formatted = absl::StrCat( - msg, " actual=", actual, " expected=", expected, " err=", delta / bound); - ABSL_RAW_LOG(INFO, "%s", formatted.c_str()); - return false; -} - -// TODO(absl-team): Replace with an "ABSL_HAVE_SPECIAL_MATH" and try -// to use std::beta(). As of this writing P0226R1 is not implemented -// in libc++: http://libcxx.llvm.org/cxx1z_status.html -double beta(double p, double q) { - // Beta(x, y) = Gamma(x) * Gamma(y) / Gamma(x+y) - double lbeta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q); - return std::exp(lbeta); -} - -// Approximation to inverse of the Error Function in double precision. -// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf) -double erfinv(double x) { -#if !defined(__EMSCRIPTEN__) - using std::fma; -#endif - - double w = 0.0; - double p = 0.0; - w = -std::log((1.0 - x) * (1.0 + x)); - if (w < 6.250000) { - w = w - 3.125000; - p = -3.6444120640178196996e-21; - p = fma(p, w, -1.685059138182016589e-19); - p = fma(p, w, 1.2858480715256400167e-18); - p = fma(p, w, 1.115787767802518096e-17); - p = fma(p, w, -1.333171662854620906e-16); - p = fma(p, w, 2.0972767875968561637e-17); - p = fma(p, w, 6.6376381343583238325e-15); - p = fma(p, w, -4.0545662729752068639e-14); - p = fma(p, w, -8.1519341976054721522e-14); - p = fma(p, w, 2.6335093153082322977e-12); - p = fma(p, w, -1.2975133253453532498e-11); - p = fma(p, w, -5.4154120542946279317e-11); - p = fma(p, w, 1.051212273321532285e-09); - p = fma(p, w, -4.1126339803469836976e-09); - p = fma(p, w, -2.9070369957882005086e-08); - p = fma(p, w, 4.2347877827932403518e-07); - p = fma(p, w, -1.3654692000834678645e-06); - p = fma(p, w, -1.3882523362786468719e-05); - p = fma(p, w, 0.0001867342080340571352); - p = fma(p, w, -0.00074070253416626697512); - p = fma(p, w, -0.0060336708714301490533); - p = fma(p, w, 0.24015818242558961693); - p = fma(p, w, 1.6536545626831027356); - } else if (w < 16.000000) { - w = std::sqrt(w) - 3.250000; - p = 2.2137376921775787049e-09; - p = fma(p, w, 9.0756561938885390979e-08); - p = fma(p, w, -2.7517406297064545428e-07); - p = fma(p, w, 1.8239629214389227755e-08); - p = fma(p, w, 1.5027403968909827627e-06); - p = fma(p, w, -4.013867526981545969e-06); - p = fma(p, w, 2.9234449089955446044e-06); - p = fma(p, w, 1.2475304481671778723e-05); - p = fma(p, w, -4.7318229009055733981e-05); - p = fma(p, w, 6.8284851459573175448e-05); - p = fma(p, w, 2.4031110387097893999e-05); - p = fma(p, w, -0.0003550375203628474796); - p = fma(p, w, 0.00095328937973738049703); - p = fma(p, w, -0.0016882755560235047313); - p = fma(p, w, 0.0024914420961078508066); - p = fma(p, w, -0.0037512085075692412107); - p = fma(p, w, 0.005370914553590063617); - p = fma(p, w, 1.0052589676941592334); - p = fma(p, w, 3.0838856104922207635); - } else { - w = std::sqrt(w) - 5.000000; - p = -2.7109920616438573243e-11; - p = fma(p, w, -2.5556418169965252055e-10); - p = fma(p, w, 1.5076572693500548083e-09); - p = fma(p, w, -3.7894654401267369937e-09); - p = fma(p, w, 7.6157012080783393804e-09); - p = fma(p, w, -1.4960026627149240478e-08); - p = fma(p, w, 2.9147953450901080826e-08); - p = fma(p, w, -6.7711997758452339498e-08); - p = fma(p, w, 2.2900482228026654717e-07); - p = fma(p, w, -9.9298272942317002539e-07); - p = fma(p, w, 4.5260625972231537039e-06); - p = fma(p, w, -1.9681778105531670567e-05); - p = fma(p, w, 7.5995277030017761139e-05); - p = fma(p, w, -0.00021503011930044477347); - p = fma(p, w, -0.00013871931833623122026); - p = fma(p, w, 1.0103004648645343977); - p = fma(p, w, 4.8499064014085844221); - } - return p * x; -} - -namespace { - -// Direct implementation of AS63, BETAIN() -// https://www.jstor.org/stable/2346797?seq=3#page_scan_tab_contents. -// -// BETAIN(x, p, q, beta) -// x: the value of the upper limit x. -// p: the value of the parameter p. -// q: the value of the parameter q. -// beta: the value of ln B(p, q) -// -double BetaIncompleteImpl(const double x, const double p, const double q, - const double beta) { - if (p < (p + q) * x) { - // Incomplete beta function is symmetrical, so return the complement. - return 1. - BetaIncompleteImpl(1.0 - x, q, p, beta); - } - - double psq = p + q; - const double kErr = 1e-14; - const double xc = 1. - x; - const double pre = - std::exp(p * std::log(x) + (q - 1.) * std::log(xc) - beta) / p; - - double term = 1.; - double ai = 1.; - double result = 1.; - int ns = static_cast<int>(q + xc * psq); - - // Use the soper reduction forumla. - double rx = (ns == 0) ? x : x / xc; - double temp = q - ai; - for (;;) { - term = term * temp * rx / (p + ai); - result = result + term; - temp = std::fabs(term); - if (temp < kErr && temp < kErr * result) { - return result * pre; - } - ai = ai + 1.; - --ns; - if (ns >= 0) { - temp = q - ai; - if (ns == 0) { - rx = x; - } - } else { - temp = psq; - psq = psq + 1.; - } - } - - // NOTE: See also TOMS Alogrithm 708. - // http://www.netlib.org/toms/index.html - // - // NOTE: The NWSC library also includes BRATIO / ISUBX (p87) - // https://archive.org/details/DTIC_ADA261511/page/n75 -} - -// Direct implementation of AS109, XINBTA(p, q, beta, alpha) -// https://www.jstor.org/stable/2346798?read-now=1&seq=4#page_scan_tab_contents -// https://www.jstor.org/stable/2346887?seq=1#page_scan_tab_contents -// -// XINBTA(p, q, beta, alhpa) -// p: the value of the parameter p. -// q: the value of the parameter q. -// beta: the value of ln B(p, q) -// alpha: the value of the lower tail area. -// -double BetaIncompleteInvImpl(const double p, const double q, const double beta, - const double alpha) { - if (alpha < 0.5) { - // Inverse Incomplete beta function is symmetrical, return the complement. - return 1. - BetaIncompleteInvImpl(q, p, beta, 1. - alpha); - } - const double kErr = 1e-14; - double value = kErr; - - // Compute the initial estimate. - { - double r = std::sqrt(-std::log(alpha * alpha)); - double y = - r - fma(r, 0.27061, 2.30753) / fma(r, fma(r, 0.04481, 0.99229), 1.0); - if (p > 1. && q > 1.) { - r = (y * y - 3.) / 6.; - double s = 1. / (p + p - 1.); - double t = 1. / (q + q - 1.); - double h = 2. / s + t; - double w = - y * std::sqrt(h + r) / h - (t - s) * (r + 5. / 6. - t / (3. * h)); - value = p / (p + q * std::exp(w + w)); - } else { - r = q + q; - double t = 1.0 / (9. * q); - double u = 1.0 - t + y * std::sqrt(t); - t = r * (u * u * u); - if (t <= 0) { - value = 1.0 - std::exp((std::log((1.0 - alpha) * q) + beta) / q); - } else { - t = (4.0 * p + r - 2.0) / t; - if (t <= 1) { - value = std::exp((std::log(alpha * p) + beta) / p); - } else { - value = 1.0 - 2.0 / (t + 1.0); - } - } - } - } - - // Solve for x using a modified newton-raphson method using the function - // BetaIncomplete. - { - value = std::max(value, kErr); - value = std::min(value, 1.0 - kErr); - - const double r = 1.0 - p; - const double t = 1.0 - q; - double y; - double yprev = 0; - double sq = 1; - double prev = 1; - for (;;) { - if (value < 0 || value > 1.0) { - // Error case; value went infinite. - return std::numeric_limits<double>::infinity(); - } else if (value == 0 || value == 1) { - y = value; - } else { - y = BetaIncompleteImpl(value, p, q, beta); - if (!std::isfinite(y)) { - return y; - } - } - y = (y - alpha) * - std::exp(beta + r * std::log(value) + t * std::log(1.0 - value)); - if (y * yprev <= 0) { - prev = std::max(sq, std::numeric_limits<double>::min()); - } - double g = 1.0; - for (;;) { - const double adj = g * y; - const double adj_sq = adj * adj; - if (adj_sq >= prev) { - g = g / 3.0; - continue; - } - const double tx = value - adj; - if (tx < 0 || tx > 1) { - g = g / 3.0; - continue; - } - if (prev < kErr) { - return value; - } - if (y * y < kErr) { - return value; - } - if (tx == value) { - return value; - } - if (tx == 0 || tx == 1) { - g = g / 3.0; - continue; - } - value = tx; - yprev = y; - break; - } - } - } - - // NOTES: See also: Asymptotic inversion of the incomplete beta function. - // https://core.ac.uk/download/pdf/82140723.pdf - // - // NOTE: See the Boost library documentation as well: - // https://www.boost.org/doc/libs/1_52_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_beta/ibeta_function.html -} - -} // namespace - -double BetaIncomplete(const double x, const double p, const double q) { - // Error cases. - if (p < 0 || q < 0 || x < 0 || x > 1.0) { - return std::numeric_limits<double>::infinity(); - } - if (x == 0 || x == 1) { - return x; - } - // ln(Beta(p, q)) - double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q); - return BetaIncompleteImpl(x, p, q, beta); -} - -double BetaIncompleteInv(const double p, const double q, const double alpha) { - // Error cases. - if (p < 0 || q < 0 || alpha < 0 || alpha > 1.0) { - return std::numeric_limits<double>::infinity(); - } - if (alpha == 0 || alpha == 1) { - return alpha; - } - // ln(Beta(p, q)) - double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q); - return BetaIncompleteInvImpl(p, q, beta, alpha); -} - -// Given `num_trials` trials each with probability `p` of success, the -// probability of no failures is `p^k`. To ensure the probability of a failure -// is no more than `p_fail`, it must be that `p^k == 1 - p_fail`. This function -// computes `p` from that equation. -double RequiredSuccessProbability(const double p_fail, const int num_trials) { - double p = std::exp(std::log(1.0 - p_fail) / static_cast<double>(num_trials)); - ABSL_ASSERT(p > 0); - return p; -} - -double ZScore(double expected_mean, const DistributionMoments& moments) { - return (moments.mean - expected_mean) / - (std::sqrt(moments.variance) / - std::sqrt(static_cast<double>(moments.n))); -} - -double MaxErrorTolerance(double acceptance_probability) { - double one_sided_pvalue = 0.5 * (1.0 - acceptance_probability); - const double max_err = InverseNormalSurvival(one_sided_pvalue); - ABSL_ASSERT(max_err > 0); - return max_err; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/distribution_test_util.h b/third_party/abseil_cpp/absl/random/internal/distribution_test_util.h deleted file mode 100644 index 6d94cf6c97bf..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/distribution_test_util.h +++ /dev/null @@ -1,113 +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. - -#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_ -#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_ - -#include <cstddef> -#include <iostream> -#include <vector> - -#include "absl/strings/string_view.h" -#include "absl/types/span.h" - -// NOTE: The functions in this file are test only, and are should not be used in -// non-test code. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// http://webspace.ship.edu/pgmarr/Geo441/Lectures/Lec%205%20-%20Normality%20Testing.pdf - -// Compute the 1st to 4th standard moments: -// mean, variance, skewness, and kurtosis. -// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm -struct DistributionMoments { - size_t n = 0; - double mean = 0.0; - double variance = 0.0; - double skewness = 0.0; - double kurtosis = 0.0; -}; -DistributionMoments ComputeDistributionMoments( - absl::Span<const double> data_points); - -std::ostream& operator<<(std::ostream& os, const DistributionMoments& moments); - -// Computes the Z-score for a set of data with the given distribution moments -// compared against `expected_mean`. -double ZScore(double expected_mean, const DistributionMoments& moments); - -// Returns the probability of success required for a single trial to ensure that -// after `num_trials` trials, the probability of at least one failure is no more -// than `p_fail`. -double RequiredSuccessProbability(double p_fail, int num_trials); - -// Computes the maximum distance from the mean tolerable, for Z-Tests that are -// expected to pass with `acceptance_probability`. Will terminate if the -// resulting tolerance is zero (due to passing in 0.0 for -// `acceptance_probability` or rounding errors). -// -// For example, -// MaxErrorTolerance(0.001) = 0.0 -// MaxErrorTolerance(0.5) = ~0.47 -// MaxErrorTolerance(1.0) = inf -double MaxErrorTolerance(double acceptance_probability); - -// Approximation to inverse of the Error Function in double precision. -// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf) -double erfinv(double x); - -// Beta(p, q) = Gamma(p) * Gamma(q) / Gamma(p+q) -double beta(double p, double q); - -// The inverse of the normal survival function. -double InverseNormalSurvival(double x); - -// Returns whether actual is "near" expected, based on the bound. -bool Near(absl::string_view msg, double actual, double expected, double bound); - -// Implements the incomplete regularized beta function, AS63, BETAIN. -// https://www.jstor.org/stable/2346797 -// -// BetaIncomplete(x, p, q), where -// `x` is the value of the upper limit -// `p` is beta parameter p, `q` is beta parameter q. -// -// NOTE: This is a test-only function which is only accurate to within, at most, -// 1e-13 of the actual value. -// -double BetaIncomplete(double x, double p, double q); - -// Implements the inverse of the incomplete regularized beta function, AS109, -// XINBTA. -// https://www.jstor.org/stable/2346798 -// https://www.jstor.org/stable/2346887 -// -// BetaIncompleteInv(p, q, beta, alhpa) -// `p` is beta parameter p, `q` is beta parameter q. -// `alpha` is the value of the lower tail area. -// -// NOTE: This is a test-only function and, when successful, is only accurate to -// within ~1e-6 of the actual value; there are some cases where it diverges from -// the actual value by much more than that. The function uses Newton's method, -// and thus the runtime is highly variable. -double BetaIncompleteInv(double p, double q, double alpha); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/distribution_test_util_test.cc b/third_party/abseil_cpp/absl/random/internal/distribution_test_util_test.cc deleted file mode 100644 index c49d44fb4796..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/distribution_test_util_test.cc +++ /dev/null @@ -1,193 +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/distribution_test_util.h" - -#include "gtest/gtest.h" - -namespace { - -TEST(TestUtil, InverseErf) { - const struct { - const double z; - const double value; - } kErfInvTable[] = { - {0.0000001, 8.86227e-8}, - {0.00001, 8.86227e-6}, - {0.5, 0.4769362762044}, - {0.6, 0.5951160814499}, - {0.99999, 3.1234132743}, - {0.9999999, 3.7665625816}, - {0.999999944, 3.8403850690566985}, // = log((1-x) * (1+x)) =~ 16.004 - {0.999999999, 4.3200053849134452}, - }; - - for (const auto& data : kErfInvTable) { - auto value = absl::random_internal::erfinv(data.z); - - // Log using the Wolfram-alpha function name & parameters. - EXPECT_NEAR(value, data.value, 1e-8) - << " InverseErf[" << data.z << "] (expected=" << data.value << ") -> " - << value; - } -} - -const struct { - const double p; - const double q; - const double x; - const double alpha; -} kBetaTable[] = { - {0.5, 0.5, 0.01, 0.06376856085851985}, - {0.5, 0.5, 0.1, 0.2048327646991335}, - {0.5, 0.5, 1, 1}, - {1, 0.5, 0, 0}, - {1, 0.5, 0.01, 0.005012562893380045}, - {1, 0.5, 0.1, 0.0513167019494862}, - {1, 0.5, 0.5, 0.2928932188134525}, - {1, 1, 0.5, 0.5}, - {2, 2, 0.1, 0.028}, - {2, 2, 0.2, 0.104}, - {2, 2, 0.3, 0.216}, - {2, 2, 0.4, 0.352}, - {2, 2, 0.5, 0.5}, - {2, 2, 0.6, 0.648}, - {2, 2, 0.7, 0.784}, - {2, 2, 0.8, 0.896}, - {2, 2, 0.9, 0.972}, - {5.5, 5, 0.5, 0.4361908850559777}, - {10, 0.5, 0.9, 0.1516409096346979}, - {10, 5, 0.5, 0.08978271484375}, - {10, 5, 1, 1}, - {10, 10, 0.5, 0.5}, - {20, 5, 0.8, 0.4598773297575791}, - {20, 10, 0.6, 0.2146816102371739}, - {20, 10, 0.8, 0.9507364826957875}, - {20, 20, 0.5, 0.5}, - {20, 20, 0.6, 0.8979413687105918}, - {30, 10, 0.7, 0.2241297491808366}, - {30, 10, 0.8, 0.7586405487192086}, - {40, 20, 0.7, 0.7001783247477069}, - {1, 0.5, 0.1, 0.0513167019494862}, - {1, 0.5, 0.2, 0.1055728090000841}, - {1, 0.5, 0.3, 0.1633399734659245}, - {1, 0.5, 0.4, 0.2254033307585166}, - {1, 2, 0.2, 0.36}, - {1, 3, 0.2, 0.488}, - {1, 4, 0.2, 0.5904}, - {1, 5, 0.2, 0.67232}, - {2, 2, 0.3, 0.216}, - {3, 2, 0.3, 0.0837}, - {4, 2, 0.3, 0.03078}, - {5, 2, 0.3, 0.010935}, - - // These values test small & large points along the range of the Beta - // function. - // - // When selecting test points, remember that if BetaIncomplete(x, p, q) - // returns the same value to within the limits of precision over a large - // domain of the input, x, then BetaIncompleteInv(alpha, p, q) may return an - // essentially arbitrary value where BetaIncomplete(x, p, q) =~ alpha. - - // BetaRegularized[x, 0.00001, 0.00001], - // For x in {~0.001 ... ~0.999}, => ~0.5 - {1e-5, 1e-5, 1e-5, 0.4999424388184638311}, - {1e-5, 1e-5, (1.0 - 1e-8), 0.5000920948389232964}, - - // BetaRegularized[x, 0.00001, 10000]. - // For x in {~epsilon ... 1.0}, => ~1 - {1e-5, 1e5, 1e-6, 0.9999817708130066936}, - {1e-5, 1e5, (1.0 - 1e-7), 1.0}, - - // BetaRegularized[x, 10000, 0.00001]. - // For x in {0 .. 1-epsilon}, => ~0 - {1e5, 1e-5, 1e-6, 0}, - {1e5, 1e-5, (1.0 - 1e-6), 1.8229186993306369e-5}, -}; - -TEST(BetaTest, BetaIncomplete) { - for (const auto& data : kBetaTable) { - auto value = absl::random_internal::BetaIncomplete(data.x, data.p, data.q); - - // Log using the Wolfram-alpha function name & parameters. - EXPECT_NEAR(value, data.alpha, 1e-12) - << " BetaRegularized[" << data.x << ", " << data.p << ", " << data.q - << "] (expected=" << data.alpha << ") -> " << value; - } -} - -TEST(BetaTest, BetaIncompleteInv) { - for (const auto& data : kBetaTable) { - auto value = - absl::random_internal::BetaIncompleteInv(data.p, data.q, data.alpha); - - // Log using the Wolfram-alpha function name & parameters. - EXPECT_NEAR(value, data.x, 1e-6) - << " InverseBetaRegularized[" << data.alpha << ", " << data.p << ", " - << data.q << "] (expected=" << data.x << ") -> " << value; - } -} - -TEST(MaxErrorTolerance, MaxErrorTolerance) { - std::vector<std::pair<double, double>> cases = { - {0.0000001, 8.86227e-8 * 1.41421356237}, - {0.00001, 8.86227e-6 * 1.41421356237}, - {0.5, 0.4769362762044 * 1.41421356237}, - {0.6, 0.5951160814499 * 1.41421356237}, - {0.99999, 3.1234132743 * 1.41421356237}, - {0.9999999, 3.7665625816 * 1.41421356237}, - {0.999999944, 3.8403850690566985 * 1.41421356237}, - {0.999999999, 4.3200053849134452 * 1.41421356237}}; - for (auto entry : cases) { - EXPECT_NEAR(absl::random_internal::MaxErrorTolerance(entry.first), - entry.second, 1e-8); - } -} - -TEST(ZScore, WithSameMean) { - absl::random_internal::DistributionMoments m; - m.n = 100; - m.mean = 5; - m.variance = 1; - EXPECT_NEAR(absl::random_internal::ZScore(5, m), 0, 1e-12); - - m.n = 1; - m.mean = 0; - m.variance = 1; - EXPECT_NEAR(absl::random_internal::ZScore(0, m), 0, 1e-12); - - m.n = 10000; - m.mean = -5; - m.variance = 100; - EXPECT_NEAR(absl::random_internal::ZScore(-5, m), 0, 1e-12); -} - -TEST(ZScore, DifferentMean) { - absl::random_internal::DistributionMoments m; - m.n = 100; - m.mean = 5; - m.variance = 1; - EXPECT_NEAR(absl::random_internal::ZScore(4, m), 10, 1e-12); - - m.n = 1; - m.mean = 0; - m.variance = 1; - EXPECT_NEAR(absl::random_internal::ZScore(-1, m), 1, 1e-12); - - m.n = 10000; - m.mean = -5; - m.variance = 100; - EXPECT_NEAR(absl::random_internal::ZScore(-4, m), -10, 1e-12); -} -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/explicit_seed_seq.h b/third_party/abseil_cpp/absl/random/internal/explicit_seed_seq.h deleted file mode 100644 index 6a743eaf46cc..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/explicit_seed_seq.h +++ /dev/null @@ -1,91 +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. - -#ifndef ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_ -#define ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_ - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <initializer_list> -#include <iterator> -#include <vector> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// This class conforms to the C++ Standard "Seed Sequence" concept -// [rand.req.seedseq]. -// -// An "ExplicitSeedSeq" is meant to provide a conformant interface for -// forwarding pre-computed seed material to the constructor of a class -// conforming to the "Uniform Random Bit Generator" concept. This class makes no -// attempt to mutate the state provided by its constructor, and returns it -// directly via ExplicitSeedSeq::generate(). -// -// If this class is asked to generate more seed material than was provided to -// the constructor, then the remaining bytes will be filled with deterministic, -// nonrandom data. -class ExplicitSeedSeq { - public: - using result_type = uint32_t; - - ExplicitSeedSeq() : state_() {} - - // Copy and move both allowed. - ExplicitSeedSeq(const ExplicitSeedSeq& other) = default; - ExplicitSeedSeq& operator=(const ExplicitSeedSeq& other) = default; - ExplicitSeedSeq(ExplicitSeedSeq&& other) = default; - ExplicitSeedSeq& operator=(ExplicitSeedSeq&& other) = default; - - template <typename Iterator> - ExplicitSeedSeq(Iterator begin, Iterator end) { - for (auto it = begin; it != end; it++) { - state_.push_back(*it & 0xffffffff); - } - } - - template <typename T> - ExplicitSeedSeq(std::initializer_list<T> il) - : ExplicitSeedSeq(il.begin(), il.end()) {} - - size_t size() const { return state_.size(); } - - template <typename OutIterator> - void param(OutIterator out) const { - std::copy(std::begin(state_), std::end(state_), out); - } - - template <typename OutIterator> - void generate(OutIterator begin, OutIterator end) { - for (size_t index = 0; begin != end; begin++) { - *begin = state_.empty() ? 0 : state_[index++]; - if (index >= state_.size()) { - index = 0; - } - } - } - - protected: - std::vector<uint32_t> state_; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_ diff --git a/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 deleted file mode 100644 index a55ad73948b9..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/explicit_seed_seq_test.cc +++ /dev/null @@ -1,204 +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/explicit_seed_seq.h" - -#include <iterator> -#include <random> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/random/seed_sequences.h" - -namespace { - -template <typename Sseq> -bool ConformsToInterface() { - // Check that the SeedSequence can be default-constructed. - { Sseq default_constructed_seq; } - // Check that the SeedSequence can be constructed with two iterators. - { - uint32_t init_array[] = {1, 3, 5, 7, 9}; - Sseq iterator_constructed_seq(init_array, &init_array[5]); - } - // Check that the SeedSequence can be std::initializer_list-constructed. - { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; } - // Check that param() and size() return state provided to constructor. - { - uint32_t init_array[] = {1, 2, 3, 4, 5}; - Sseq seq(init_array, &init_array[ABSL_ARRAYSIZE(init_array)]); - EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array)); - - uint32_t state_array[ABSL_ARRAYSIZE(init_array)]; - seq.param(state_array); - - for (int i = 0; i < ABSL_ARRAYSIZE(state_array); i++) { - EXPECT_EQ(state_array[i], i + 1); - } - } - // Check for presence of generate() method. - { - Sseq seq; - uint32_t seeds[5]; - - seq.generate(seeds, &seeds[ABSL_ARRAYSIZE(seeds)]); - } - return true; -} -} // namespace - -TEST(SeedSequences, CheckInterfaces) { - // Control case - EXPECT_TRUE(ConformsToInterface<std::seed_seq>()); - - // Abseil classes - EXPECT_TRUE(ConformsToInterface<absl::random_internal::ExplicitSeedSeq>()); -} - -TEST(ExplicitSeedSeq, DefaultConstructorGeneratesZeros) { - const size_t kNumBlocks = 128; - - uint32_t outputs[kNumBlocks]; - absl::random_internal::ExplicitSeedSeq seq; - seq.generate(outputs, &outputs[kNumBlocks]); - - for (uint32_t& seed : outputs) { - EXPECT_EQ(seed, 0); - } -} - -TEST(ExplicitSeeqSeq, SeedMaterialIsForwardedIdentically) { - const size_t kNumBlocks = 128; - - uint32_t seed_material[kNumBlocks]; - std::random_device urandom{"/dev/urandom"}; - for (uint32_t& seed : seed_material) { - seed = urandom(); - } - absl::random_internal::ExplicitSeedSeq seq(seed_material, - &seed_material[kNumBlocks]); - - // Check that output is same as seed-material provided to constructor. - { - const size_t kNumGenerated = kNumBlocks / 2; - uint32_t outputs[kNumGenerated]; - seq.generate(outputs, &outputs[kNumGenerated]); - for (size_t i = 0; i < kNumGenerated; i++) { - EXPECT_EQ(outputs[i], seed_material[i]); - } - } - // Check that SeedSequence is stateless between invocations: Despite the last - // invocation of generate() only consuming half of the input-entropy, the same - // entropy will be recycled for the next invocation. - { - const size_t kNumGenerated = kNumBlocks; - uint32_t outputs[kNumGenerated]; - seq.generate(outputs, &outputs[kNumGenerated]); - for (size_t i = 0; i < kNumGenerated; i++) { - EXPECT_EQ(outputs[i], seed_material[i]); - } - } - // Check that when more seed-material is asked for than is provided, nonzero - // values are still written. - { - const size_t kNumGenerated = kNumBlocks * 2; - uint32_t outputs[kNumGenerated]; - seq.generate(outputs, &outputs[kNumGenerated]); - for (size_t i = 0; i < kNumGenerated; i++) { - EXPECT_EQ(outputs[i], seed_material[i % kNumBlocks]); - } - } -} - -TEST(ExplicitSeedSeq, CopyAndMoveConstructors) { - using testing::Each; - using testing::Eq; - using testing::Not; - using testing::Pointwise; - - uint32_t entropy[4]; - std::random_device urandom("/dev/urandom"); - for (uint32_t& entry : entropy) { - entry = urandom(); - } - absl::random_internal::ExplicitSeedSeq seq_from_entropy(std::begin(entropy), - std::end(entropy)); - // Copy constructor. - { - absl::random_internal::ExplicitSeedSeq seq_copy(seq_from_entropy); - EXPECT_EQ(seq_copy.size(), seq_from_entropy.size()); - - std::vector<uint32_t> seeds_1; - seeds_1.resize(1000, 0); - std::vector<uint32_t> seeds_2; - seeds_2.resize(1000, 1); - - seq_from_entropy.generate(seeds_1.begin(), seeds_1.end()); - seq_copy.generate(seeds_2.begin(), seeds_2.end()); - - EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2)); - } - // Assignment operator. - { - for (uint32_t& entry : entropy) { - entry = urandom(); - } - absl::random_internal::ExplicitSeedSeq another_seq(std::begin(entropy), - std::end(entropy)); - - std::vector<uint32_t> seeds_1; - seeds_1.resize(1000, 0); - std::vector<uint32_t> seeds_2; - seeds_2.resize(1000, 0); - - seq_from_entropy.generate(seeds_1.begin(), seeds_1.end()); - another_seq.generate(seeds_2.begin(), seeds_2.end()); - - // Assert precondition: Sequences generated by seed-sequences are not equal. - EXPECT_THAT(seeds_1, Not(Pointwise(Eq(), seeds_2))); - - // Apply the assignment-operator. - another_seq = seq_from_entropy; - - // Re-generate seeds. - seq_from_entropy.generate(seeds_1.begin(), seeds_1.end()); - another_seq.generate(seeds_2.begin(), seeds_2.end()); - - // Seeds generated by seed-sequences should now be equal. - EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2)); - } - // Move constructor. - { - // Get seeds from seed-sequence constructed from entropy. - std::vector<uint32_t> seeds_1; - seeds_1.resize(1000, 0); - seq_from_entropy.generate(seeds_1.begin(), seeds_1.end()); - - // Apply move-constructor move the sequence to another instance. - absl::random_internal::ExplicitSeedSeq moved_seq( - std::move(seq_from_entropy)); - std::vector<uint32_t> seeds_2; - seeds_2.resize(1000, 1); - moved_seq.generate(seeds_2.begin(), seeds_2.end()); - // Verify that seeds produced by moved-instance are the same as original. - EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2)); - - // Verify that the moved-from instance now behaves like a - // default-constructed instance. - EXPECT_EQ(seq_from_entropy.size(), 0); - seq_from_entropy.generate(seeds_1.begin(), seeds_1.end()); - EXPECT_THAT(seeds_1, Each(Eq(0))); - } -} diff --git a/third_party/abseil_cpp/absl/random/internal/fast_uniform_bits.h b/third_party/abseil_cpp/absl/random/internal/fast_uniform_bits.h deleted file mode 100644 index 425aaf7d830c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/fast_uniform_bits.h +++ /dev/null @@ -1,268 +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. - -#ifndef ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_ -#define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_ - -#include <cstddef> -#include <cstdint> -#include <limits> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -// Returns true if the input value is zero or a power of two. Useful for -// determining if the range of output values in a URBG -template <typename UIntType> -constexpr bool IsPowerOfTwoOrZero(UIntType n) { - return (n == 0) || ((n & (n - 1)) == 0); -} - -// Computes the length of the range of values producible by the URBG, or returns -// zero if that would encompass the entire range of representable values in -// URBG::result_type. -template <typename URBG> -constexpr typename URBG::result_type RangeSize() { - using result_type = typename URBG::result_type; - static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0."); - return ((URBG::max)() == (std::numeric_limits<result_type>::max)() && - (URBG::min)() == std::numeric_limits<result_type>::lowest()) - ? result_type{0} - : ((URBG::max)() - (URBG::min)() + result_type{1}); -} - -// Computes the floor of the log. (i.e., std::floor(std::log2(N)); -template <typename UIntType> -constexpr UIntType IntegerLog2(UIntType n) { - return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1); -} - -// Returns the number of bits of randomness returned through -// `PowerOfTwoVariate(urbg)`. -template <typename URBG> -constexpr size_t NumBits() { - return RangeSize<URBG>() == 0 - ? std::numeric_limits<typename URBG::result_type>::digits - : IntegerLog2(RangeSize<URBG>()); -} - -// Given a shift value `n`, constructs a mask with exactly the low `n` bits set. -// If `n == 0`, all bits are set. -template <typename UIntType> -constexpr UIntType MaskFromShift(size_t n) { - return ((n % std::numeric_limits<UIntType>::digits) == 0) - ? ~UIntType{0} - : (UIntType{1} << n) - UIntType{1}; -} - -// Tags used to dispatch FastUniformBits::generate to the simple or more complex -// entropy extraction algorithm. -struct SimplifiedLoopTag {}; -struct RejectionLoopTag {}; - -// FastUniformBits implements a fast path to acquire uniform independent bits -// from a type which conforms to the [rand.req.urbg] concept. -// Parameterized by: -// `UIntType`: the result (output) type -// -// The std::independent_bits_engine [rand.adapt.ibits] adaptor can be -// instantiated from an existing generator through a copy or a move. It does -// not, however, facilitate the production of pseudorandom bits from an un-owned -// generator that will outlive the std::independent_bits_engine instance. -template <typename UIntType = uint64_t> -class FastUniformBits { - public: - using result_type = UIntType; - - static constexpr result_type(min)() { return 0; } - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - template <typename URBG> - result_type operator()(URBG& g); // NOLINT(runtime/references) - - private: - static_assert(std::is_unsigned<UIntType>::value, - "Class-template FastUniformBits<> must be parameterized using " - "an unsigned type."); - - // Generate() generates a random value, dispatched on whether - // the underlying URBG must use rejection sampling to generate a value, - // or whether a simplified loop will suffice. - template <typename URBG> - result_type Generate(URBG& g, // NOLINT(runtime/references) - SimplifiedLoopTag); - - template <typename URBG> - result_type Generate(URBG& g, // NOLINT(runtime/references) - RejectionLoopTag); -}; - -template <typename UIntType> -template <typename URBG> -typename FastUniformBits<UIntType>::result_type -FastUniformBits<UIntType>::operator()(URBG& g) { // NOLINT(runtime/references) - // kRangeMask is the mask used when sampling variates from the URBG when the - // width of the URBG range is not a power of 2. - // Y = (2 ^ kRange) - 1 - static_assert((URBG::max)() > (URBG::min)(), - "URBG::max and URBG::min may not be equal."); - - using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()), - SimplifiedLoopTag, RejectionLoopTag>; - return Generate(g, tag{}); -} - -template <typename UIntType> -template <typename URBG> -typename FastUniformBits<UIntType>::result_type -FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references) - SimplifiedLoopTag) { - // The simplified version of FastUniformBits works only on URBGs that have - // a range that is a power of 2. In this case we simply loop and shift without - // attempting to balance the bits across calls. - static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()), - "incorrect Generate tag for URBG instance"); - - static constexpr size_t kResultBits = - std::numeric_limits<result_type>::digits; - static constexpr size_t kUrbgBits = NumBits<URBG>(); - static constexpr size_t kIters = - (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0); - static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits; - static constexpr auto kMin = (URBG::min)(); - - result_type r = static_cast<result_type>(g() - kMin); - for (size_t n = 1; n < kIters; ++n) { - r = (r << kShift) + static_cast<result_type>(g() - kMin); - } - return r; -} - -template <typename UIntType> -template <typename URBG> -typename FastUniformBits<UIntType>::result_type -FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references) - RejectionLoopTag) { - static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()), - "incorrect Generate tag for URBG instance"); - using urbg_result_type = typename URBG::result_type; - - // See [rand.adapt.ibits] for more details on the constants calculated below. - // - // It is preferable to use roughly the same number of bits from each generator - // call, however this is only possible when the number of bits provided by the - // URBG is a divisor of the number of bits in `result_type`. In all other - // cases, the number of bits used cannot always be the same, but it can be - // guaranteed to be off by at most 1. Thus we run two loops, one with a - // smaller bit-width size (`kSmallWidth`) and one with a larger width size - // (satisfying `kLargeWidth == kSmallWidth + 1`). The loops are run - // `kSmallIters` and `kLargeIters` times respectively such - // that - // - // `kResultBits == kSmallIters * kSmallBits - // + kLargeIters * kLargeBits` - // - // where `kResultBits` is the total number of bits in `result_type`. - // - static constexpr size_t kResultBits = - std::numeric_limits<result_type>::digits; // w - static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>(); // R - static constexpr size_t kUrbgBits = NumBits<URBG>(); // m - - // compute the initial estimate of the bits used. - // [rand.adapt.ibits] 2 (c) - static constexpr size_t kA = // ceil(w/m) - (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0); // n' - - static constexpr size_t kABits = kResultBits / kA; // w0' - static constexpr urbg_result_type kARejection = - ((kUrbgRange >> kABits) << kABits); // y0' - - // refine the selection to reduce the rejection frequency. - static constexpr size_t kTotalIters = - ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1); // n - - // [rand.adapt.ibits] 2 (b) - static constexpr size_t kSmallIters = - kTotalIters - (kResultBits % kTotalIters); // n0 - static constexpr size_t kSmallBits = kResultBits / kTotalIters; // w0 - static constexpr urbg_result_type kSmallRejection = - ((kUrbgRange >> kSmallBits) << kSmallBits); // y0 - - static constexpr size_t kLargeBits = kSmallBits + 1; // w0+1 - static constexpr urbg_result_type kLargeRejection = - ((kUrbgRange >> kLargeBits) << kLargeBits); // y1 - - // - // Because `kLargeBits == kSmallBits + 1`, it follows that - // - // `kResultBits == kSmallIters * kSmallBits + kLargeIters` - // - // and therefore - // - // `kLargeIters == kTotalWidth % kSmallWidth` - // - // Intuitively, each iteration with the large width accounts for one unit - // of the remainder when `kTotalWidth` is divided by `kSmallWidth`. As - // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then - // there would be no need for any large iterations (i.e., one loop would - // suffice), and indeed, in this case, `kLargeIters` would be zero. - static_assert(kResultBits == kSmallIters * kSmallBits + - (kTotalIters - kSmallIters) * kLargeBits, - "Error in looping constant calculations."); - - // The small shift is essentially small bits, but due to the potential - // of generating a smaller result_type from a larger urbg type, the actual - // shift might be 0. - static constexpr size_t kSmallShift = kSmallBits % kResultBits; - static constexpr auto kSmallMask = - MaskFromShift<urbg_result_type>(kSmallShift); - static constexpr size_t kLargeShift = kLargeBits % kResultBits; - static constexpr auto kLargeMask = - MaskFromShift<urbg_result_type>(kLargeShift); - - static constexpr auto kMin = (URBG::min)(); - - result_type s = 0; - for (size_t n = 0; n < kSmallIters; ++n) { - urbg_result_type v; - do { - v = g() - kMin; - } while (v >= kSmallRejection); - - s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask); - } - - for (size_t n = kSmallIters; n < kTotalIters; ++n) { - urbg_result_type v; - do { - v = g() - kMin; - } while (v >= kLargeRejection); - - s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask); - } - return s; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_ diff --git a/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 deleted file mode 100644 index cee702df852d..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/fast_uniform_bits_test.cc +++ /dev/null @@ -1,336 +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/fast_uniform_bits.h" - -#include <random> - -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -template <typename IntType> -class FastUniformBitsTypedTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>; - -TYPED_TEST_SUITE(FastUniformBitsTypedTest, IntTypes); - -TYPED_TEST(FastUniformBitsTypedTest, BasicTest) { - using Limits = std::numeric_limits<TypeParam>; - using FastBits = FastUniformBits<TypeParam>; - - EXPECT_EQ(0, (FastBits::min)()); - EXPECT_EQ((Limits::max)(), (FastBits::max)()); - - constexpr int kIters = 10000; - std::random_device rd; - std::mt19937 gen(rd()); - FastBits fast; - for (int i = 0; i < kIters; i++) { - const auto v = fast(gen); - EXPECT_LE(v, (FastBits::max)()); - EXPECT_GE(v, (FastBits::min)()); - } -} - -template <typename UIntType, UIntType Lo, UIntType Hi, UIntType Val = Lo> -struct FakeUrbg { - using result_type = UIntType; - - FakeUrbg() = default; - explicit FakeUrbg(bool r) : reject(r) {} - - static constexpr result_type(max)() { return Hi; } - static constexpr result_type(min)() { return Lo; } - result_type operator()() { - // when reject is set, return Hi half the time. - return ((++calls % 2) == 1 && reject) ? Hi : Val; - } - - bool reject = false; - size_t calls = 0; -}; - -TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) { - EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17})); - EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint8_t>::max)())); - - EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{0})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17})); - EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint16_t>::max)())); - - EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{0})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{1})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{2})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{3})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{32})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{17})); - EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint32_t>::max)())); - - EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{0})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4})); - EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64})); - EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17})); - EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint64_t>::max)())); -} - -TEST(FastUniformBitsTest, IntegerLog2) { - EXPECT_EQ(0, IntegerLog2(uint16_t{0})); - EXPECT_EQ(0, IntegerLog2(uint16_t{1})); - EXPECT_EQ(1, IntegerLog2(uint16_t{2})); - EXPECT_EQ(1, IntegerLog2(uint16_t{3})); - EXPECT_EQ(2, IntegerLog2(uint16_t{4})); - EXPECT_EQ(2, IntegerLog2(uint16_t{5})); - EXPECT_EQ(2, IntegerLog2(uint16_t{7})); - EXPECT_EQ(3, IntegerLog2(uint16_t{8})); - EXPECT_EQ(63, IntegerLog2((std::numeric_limits<uint64_t>::max)())); -} - -TEST(FastUniformBitsTest, RangeSize) { - EXPECT_EQ(2, (RangeSize<FakeUrbg<uint8_t, 0, 1>>())); - EXPECT_EQ(3, (RangeSize<FakeUrbg<uint8_t, 0, 2>>())); - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 0, 3>>())); - // EXPECT_EQ(0, (RangeSize<FakeUrbg<uint8_t, 2, 2>>())); - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 2, 5>>())); - EXPECT_EQ(5, (RangeSize<FakeUrbg<uint8_t, 2, 6>>())); - EXPECT_EQ(9, (RangeSize<FakeUrbg<uint8_t, 2, 10>>())); - EXPECT_EQ( - 0, (RangeSize< - FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>())); - - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 0, 3>>())); - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 2, 5>>())); - EXPECT_EQ(5, (RangeSize<FakeUrbg<uint16_t, 2, 6>>())); - EXPECT_EQ(18, (RangeSize<FakeUrbg<uint16_t, 1000, 1017>>())); - EXPECT_EQ( - 0, (RangeSize< - FakeUrbg<uint16_t, 0, (std::numeric_limits<uint16_t>::max)()>>())); - - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 0, 3>>())); - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 2, 5>>())); - EXPECT_EQ(5, (RangeSize<FakeUrbg<uint32_t, 2, 6>>())); - EXPECT_EQ(18, (RangeSize<FakeUrbg<uint32_t, 1000, 1017>>())); - EXPECT_EQ(0, (RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>())); - EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>())); - EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>())); - EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>())); - EXPECT_EQ( - 0, (RangeSize< - FakeUrbg<uint32_t, 0, (std::numeric_limits<uint32_t>::max)()>>())); - - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 0, 3>>())); - EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 2, 5>>())); - EXPECT_EQ(5, (RangeSize<FakeUrbg<uint64_t, 2, 6>>())); - EXPECT_EQ(18, (RangeSize<FakeUrbg<uint64_t, 1000, 1017>>())); - EXPECT_EQ(0x100000000, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>())); - EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>())); - EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>())); - EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>())); - EXPECT_EQ(0, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffff>>())); - EXPECT_EQ(0xffffffffffffffff, - (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffff>>())); - EXPECT_EQ(0xfffffffffffffffe, - (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffe>>())); - EXPECT_EQ(0xfffffffffffffffd, - (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffe>>())); - EXPECT_EQ( - 0, (RangeSize< - FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>())); -} - -// The constants need to be choosen so that an infinite rejection loop doesn't -// happen... -using Urng1_5bit = FakeUrbg<uint8_t, 0, 2, 0>; // ~1.5 bits (range 3) -using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>; -using Urng22bits = FakeUrbg<uint32_t, 0, 0x3fffff, 0x301020>; -using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>; // ~31.9 bits -using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>; -using Urng33bits = - FakeUrbg<uint64_t, 1, 0x1ffffffff, 0x013301033>; // ~32.9 bits -using Urng63bits = FakeUrbg<uint64_t, 1, 0xfffffffffffffffe, - 0xfedcba9012345678>; // ~63.9 bits -using Urng64bits = - FakeUrbg<uint64_t, 0, 0xffffffffffffffff, 0x123456780fedcba9>; - -TEST(FastUniformBitsTest, OutputsUpTo32Bits) { - // Tests that how values are composed; the single-bit deltas should be spread - // across each invocation. - Urng1_5bit urng1_5; - Urng4bits urng4; - Urng22bits urng22; - Urng31bits urng31; - Urng32bits urng32; - Urng33bits urng33; - Urng63bits urng63; - Urng64bits urng64; - - // 8-bit types - { - FastUniformBits<uint8_t> fast8; - EXPECT_EQ(0x0, fast8(urng1_5)); - EXPECT_EQ(0x11, fast8(urng4)); - EXPECT_EQ(0x20, fast8(urng22)); - EXPECT_EQ(0x2, fast8(urng31)); - EXPECT_EQ(0x1, fast8(urng32)); - EXPECT_EQ(0x32, fast8(urng33)); - EXPECT_EQ(0x77, fast8(urng63)); - EXPECT_EQ(0xa9, fast8(urng64)); - } - - // 16-bit types - { - FastUniformBits<uint16_t> fast16; - EXPECT_EQ(0x0, fast16(urng1_5)); - EXPECT_EQ(0x1111, fast16(urng4)); - EXPECT_EQ(0x1020, fast16(urng22)); - EXPECT_EQ(0x0f02, fast16(urng31)); - EXPECT_EQ(0x0f01, fast16(urng32)); - EXPECT_EQ(0x1032, fast16(urng33)); - EXPECT_EQ(0x5677, fast16(urng63)); - EXPECT_EQ(0xcba9, fast16(urng64)); - } - - // 32-bit types - { - FastUniformBits<uint32_t> fast32; - EXPECT_EQ(0x0, fast32(urng1_5)); - EXPECT_EQ(0x11111111, fast32(urng4)); - EXPECT_EQ(0x08301020, fast32(urng22)); - EXPECT_EQ(0x0f020f02, fast32(urng31)); - EXPECT_EQ(0x74010f01, fast32(urng32)); - EXPECT_EQ(0x13301032, fast32(urng33)); - EXPECT_EQ(0x12345677, fast32(urng63)); - EXPECT_EQ(0x0fedcba9, fast32(urng64)); - } -} - -TEST(FastUniformBitsTest, Outputs64Bits) { - // Tests that how values are composed; the single-bit deltas should be spread - // across each invocation. - FastUniformBits<uint64_t> fast64; - - { - FakeUrbg<uint8_t, 0, 1, 0> urng0; - FakeUrbg<uint8_t, 0, 1, 1> urng1; - Urng4bits urng4; - Urng22bits urng22; - Urng31bits urng31; - Urng32bits urng32; - Urng33bits urng33; - Urng63bits urng63; - Urng64bits urng64; - - // somewhat degenerate cases only create a single bit. - EXPECT_EQ(0x0, fast64(urng0)); - EXPECT_EQ(64, urng0.calls); - EXPECT_EQ(0xffffffffffffffff, fast64(urng1)); - EXPECT_EQ(64, urng1.calls); - - // less degenerate cases. - EXPECT_EQ(0x1111111111111111, fast64(urng4)); - EXPECT_EQ(16, urng4.calls); - EXPECT_EQ(0x01020c0408301020, fast64(urng22)); - EXPECT_EQ(3, urng22.calls); - EXPECT_EQ(0x387811c3c0870f02, fast64(urng31)); - EXPECT_EQ(3, urng31.calls); - EXPECT_EQ(0x74010f0174010f01, fast64(urng32)); - EXPECT_EQ(2, urng32.calls); - EXPECT_EQ(0x808194040cb01032, fast64(urng33)); - EXPECT_EQ(3, urng33.calls); - EXPECT_EQ(0x1234567712345677, fast64(urng63)); - EXPECT_EQ(2, urng63.calls); - EXPECT_EQ(0x123456780fedcba9, fast64(urng64)); - EXPECT_EQ(1, urng64.calls); - } - - // The 1.5 bit case is somewhat interesting in that the algorithm refinement - // causes one extra small sample. Comments here reference the names used in - // [rand.adapt.ibits] that correspond to this case. - { - Urng1_5bit urng1_5; - - // w = 64 - // R = 3 - // m = 1 - // n' = 64 - // w0' = 1 - // y0' = 2 - // n = (1 <= 0) > 64 : 65 = 65 - // n0 = 65 - (64%65) = 1 - // n1 = 64 - // w0 = 0 - // y0 = 3 - // w1 = 1 - // y1 = 2 - EXPECT_EQ(0x0, fast64(urng1_5)); - EXPECT_EQ(65, urng1_5.calls); - } - - // Validate rejections for non-power-of-2 cases. - { - Urng1_5bit urng1_5(true); - Urng31bits urng31(true); - Urng33bits urng33(true); - Urng63bits urng63(true); - - // For 1.5 bits, there would be 1+2*64, except the first - // value was accepted and shifted off the end. - EXPECT_EQ(0, fast64(urng1_5)); - EXPECT_EQ(128, urng1_5.calls); - EXPECT_EQ(0x387811c3c0870f02, fast64(urng31)); - EXPECT_EQ(6, urng31.calls); - EXPECT_EQ(0x808194040cb01032, fast64(urng33)); - EXPECT_EQ(6, urng33.calls); - EXPECT_EQ(0x1234567712345677, fast64(urng63)); - EXPECT_EQ(4, urng63.calls); - } -} - -TEST(FastUniformBitsTest, URBG32bitRegression) { - // Validate with deterministic 32-bit std::minstd_rand - // to ensure that operator() performs as expected. - - EXPECT_EQ(2147483646, RangeSize<std::minstd_rand>()); - EXPECT_EQ(30, IntegerLog2(RangeSize<std::minstd_rand>())); - - std::minstd_rand gen(1); - FastUniformBits<uint64_t> fast64; - - EXPECT_EQ(0x05e47095f8791f45, fast64(gen)); - EXPECT_EQ(0x028be17e3c07c122, fast64(gen)); - EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen)); -} - -} // namespace -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/fastmath.h b/third_party/abseil_cpp/absl/random/internal/fastmath.h deleted file mode 100644 index 6baeb5a7c917..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/fastmath.h +++ /dev/null @@ -1,74 +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. - -#ifndef ABSL_RANDOM_INTERNAL_FASTMATH_H_ -#define ABSL_RANDOM_INTERNAL_FASTMATH_H_ - -// This file contains fast math functions (bitwise ops as well as some others) -// which are implementation details of various absl random number distributions. - -#include <cassert> -#include <cmath> -#include <cstdint> - -#include "absl/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 - base_internal::CountLeadingZeros64(n)); -} -inline int IntLog2Ceil(uint64_t n) { - return (n <= 1) ? 0 : (64 - base_internal::CountLeadingZeros64(n - 1)); -} - -inline double StirlingLogFactorial(double n) { - assert(n >= 1); - // Using Stirling's approximation. - constexpr double kLog2PI = 1.83787706640934548356; - const double logn = std::log(n); - const double ninv = 1.0 / static_cast<double>(n); - return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv - - (1.0 / 360.0) * ninv * ninv * ninv; -} - -// 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 - -#endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/fastmath_test.cc b/third_party/abseil_cpp/absl/random/internal/fastmath_test.cc deleted file mode 100644 index 65859c25de4c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/fastmath_test.cc +++ /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. - -#include "absl/random/internal/fastmath.h" - -#include "gtest/gtest.h" - -#if defined(__native_client__) || defined(__EMSCRIPTEN__) -// NACL has a less accurate implementation of std::log2 than most of -// the other platforms. For some values which should have integral results, -// sometimes NACL returns slightly larger values. -// -// The MUSL libc used by emscripten also has a similar bug. -#define ABSL_RANDOM_INACCURATE_LOG2 -#endif - -namespace { - -TEST(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; - EXPECT_EQ(0, IntLog2Floor(0)); // boundary. return 0. - EXPECT_EQ(0, IntLog2Floor(1)); - EXPECT_EQ(1, IntLog2Floor(2)); - EXPECT_EQ(63, IntLog2Floor(~kZero)); - - // A boundary case: Converting 0xffffffffffffffff requires > 53 - // bits of precision, so the conversion to double rounds up, - // and the result of std::log2(x) > IntLog2Floor(x). - EXPECT_LT(IntLog2Floor(~kZero), static_cast<int>(std::log2(~kZero))); - - for (int i = 0; i < 64; i++) { - const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i; - EXPECT_EQ(i, IntLog2Floor(i_pow_2)); - EXPECT_EQ(i, static_cast<int>(std::log2(i_pow_2))); - - uint64_t y = i_pow_2; - for (int j = i - 1; j > 0; --j) { - y = y | (i_pow_2 >> j); - EXPECT_EQ(i, IntLog2Floor(y)); - } - } -} - -TEST(FastMathTest, IntLog2CeilTest) { - using absl::random_internal::IntLog2Ceil; - constexpr uint64_t kZero = 0; - EXPECT_EQ(0, IntLog2Ceil(0)); // boundary. return 0. - EXPECT_EQ(0, IntLog2Ceil(1)); - EXPECT_EQ(1, IntLog2Ceil(2)); - EXPECT_EQ(64, IntLog2Ceil(~kZero)); - - // A boundary case: Converting 0xffffffffffffffff requires > 53 - // bits of precision, so the conversion to double rounds up, - // and the result of std::log2(x) > IntLog2Floor(x). - EXPECT_LE(IntLog2Ceil(~kZero), static_cast<int>(std::log2(~kZero))); - - for (int i = 0; i < 64; i++) { - const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i; - EXPECT_EQ(i, IntLog2Ceil(i_pow_2)); -#ifndef ABSL_RANDOM_INACCURATE_LOG2 - EXPECT_EQ(i, static_cast<int>(std::ceil(std::log2(i_pow_2)))); -#endif - - uint64_t y = i_pow_2; - for (int j = i - 1; j > 0; --j) { - y = y | (i_pow_2 >> j); - EXPECT_EQ(i + 1, IntLog2Ceil(y)); - } - } -} - -TEST(FastMathTest, StirlingLogFactorial) { - using absl::random_internal::StirlingLogFactorial; - - EXPECT_NEAR(StirlingLogFactorial(1.0), 0, 1e-3); - EXPECT_NEAR(StirlingLogFactorial(1.50), 0.284683, 1e-3); - EXPECT_NEAR(StirlingLogFactorial(2.0), 0.69314718056, 1e-4); - - for (int i = 2; i < 50; i++) { - double d = static_cast<double>(i); - EXPECT_NEAR(StirlingLogFactorial(d), std::lgamma(d + 1), 3e-5); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/gaussian_distribution_gentables.cc b/third_party/abseil_cpp/absl/random/internal/gaussian_distribution_gentables.cc deleted file mode 100644 index a95333d55f55..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/gaussian_distribution_gentables.cc +++ /dev/null @@ -1,143 +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. - -// Generates gaussian_distribution.cc -// -// $ blaze run :gaussian_distribution_gentables > gaussian_distribution.cc -// -#include "absl/random/gaussian_distribution.h" - -#include <cmath> -#include <cstddef> -#include <iostream> -#include <limits> -#include <string> - -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -template <typename T, size_t N> -void FormatArrayContents(std::ostream* os, T (&data)[N]) { - if (!std::numeric_limits<T>::is_exact) { - // Note: T is either an integer or a float. - // float requires higher precision to ensure that values are - // reproduced exactly. - // Trivia: C99 has hexadecimal floating point literals, but C++11 does not. - // Using them would remove all concern of precision loss. - os->precision(std::numeric_limits<T>::max_digits10 + 2); - } - *os << " {"; - std::string separator = ""; - for (size_t i = 0; i < N; ++i) { - *os << separator << data[i]; - if ((i + 1) % 3 != 0) { - separator = ", "; - } else { - separator = ",\n "; - } - } - *os << "}"; -} - -} // namespace - -class TableGenerator : public gaussian_distribution_base { - public: - TableGenerator(); - void Print(std::ostream* os); - - using gaussian_distribution_base::kMask; - using gaussian_distribution_base::kR; - using gaussian_distribution_base::kV; - - private: - Tables tables_; -}; - -// Ziggurat gaussian initialization. For an explanation of the algorithm, see -// the Marsaglia paper, "The Ziggurat Method for Generating Random Variables". -// http://www.jstatsoft.org/v05/i08/ -// -// Further details are available in the Doornik paper -// https://www.doornik.com/research/ziggurat.pdf -// -TableGenerator::TableGenerator() { - // The constants here should match the values in gaussian_distribution.h - static constexpr int kC = kMask + 1; - - static_assert((ABSL_ARRAYSIZE(tables_.x) == kC + 1), - "xArray must be length kMask + 2"); - - static_assert((ABSL_ARRAYSIZE(tables_.x) == ABSL_ARRAYSIZE(tables_.f)), - "fx and x arrays must be identical length"); - - auto f = [](double x) { return std::exp(-0.5 * x * x); }; - auto f_inv = [](double x) { return std::sqrt(-2.0 * std::log(x)); }; - - tables_.x[0] = kV / f(kR); - tables_.f[0] = f(tables_.x[0]); - - tables_.x[1] = kR; - tables_.f[1] = f(tables_.x[1]); - - tables_.x[kC] = 0.0; - tables_.f[kC] = f(tables_.x[kC]); // 1.0 - - for (int i = 2; i < kC; i++) { - double v = (kV / tables_.x[i - 1]) + tables_.f[i - 1]; - tables_.x[i] = f_inv(v); - tables_.f[i] = v; - } -} - -void TableGenerator::Print(std::ostream* os) { - *os << "// BEGIN GENERATED CODE; DO NOT EDIT\n" - "// clang-format off\n" - "\n" - "#include \"absl/random/gaussian_distribution.h\"\n" - "\n" - "namespace absl {\n" - "ABSL_NAMESPACE_BEGIN\n" - "namespace random_internal {\n" - "\n" - "const gaussian_distribution_base::Tables\n" - " gaussian_distribution_base::zg_ = {\n"; - FormatArrayContents(os, tables_.x); - *os << ",\n"; - FormatArrayContents(os, tables_.f); - *os << "};\n" - "\n" - "} // namespace random_internal\n" - "ABSL_NAMESPACE_END\n" - "} // namespace absl\n" - "\n" - "// clang-format on\n" - "// END GENERATED CODE"; - *os << std::endl; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -int main(int, char**) { - std::cerr << "\nCopy the output to gaussian_distribution.cc" << std::endl; - absl::random_internal::TableGenerator generator; - generator.Print(&std::cout); - return 0; -} diff --git a/third_party/abseil_cpp/absl/random/internal/generate_real.h b/third_party/abseil_cpp/absl/random/internal/generate_real.h deleted file mode 100644 index 20f6d20807d5..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/generate_real.h +++ /dev/null @@ -1,146 +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. - -#ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ -#define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ - -// This file contains some implementation details which are used by one or more -// of the absl random number distributions. - -#include <cstdint> -#include <cstring> -#include <limits> -#include <type_traits> - -#include "absl/base/internal/bits.h" -#include "absl/meta/type_traits.h" -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Tristate tag types controlling the output of GenerateRealFromBits. -struct GeneratePositiveTag {}; -struct GenerateNegativeTag {}; -struct GenerateSignedTag {}; - -// GenerateRealFromBits generates a single real value from a single 64-bit -// `bits` with template fields controlling the output. -// -// The `SignedTag` parameter controls whether positive, negative, -// or either signed/unsigned may be returned. -// When SignedTag == GeneratePositiveTag, range is U(0, 1) -// When SignedTag == GenerateNegativeTag, range is U(-1, 0) -// When SignedTag == GenerateSignedTag, range is U(-1, 1) -// -// When the `IncludeZero` parameter is true, the function may return 0 for some -// inputs, otherwise it never returns 0. -// -// When a value in U(0,1) is required, use: -// Uniform64ToReal<double, PositiveValueT, true>; -// -// When a value in U(-1,1) is required, use: -// Uniform64ToReal<double, SignedValueT, false>; -// -// This generates more distinct values than the mathematical equivalent -// `U(0, 1) * 2.0 - 1.0`. -// -// Scaling the result by powers of 2 (and avoiding a multiply) is also possible: -// GenerateRealFromBits<double>(..., -1); => U(0, 0.5) -// GenerateRealFromBits<double>(..., 1); => U(0, 2) -// -template <typename RealType, // Real type, either float or double. - typename SignedTag = GeneratePositiveTag, // Whether a positive, - // negative, or signed - // value is generated. - bool IncludeZero = true> -inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) { - using real_type = RealType; - using uint_type = absl::conditional_t<std::is_same<real_type, float>::value, - uint32_t, uint64_t>; - - static_assert( - (std::is_same<double, real_type>::value || - std::is_same<float, real_type>::value), - "GenerateRealFromBits must be parameterized by either float or double."); - - static_assert(sizeof(uint_type) == sizeof(real_type), - "Mismatched unsinged and real types."); - - static_assert((std::numeric_limits<real_type>::is_iec559 && - std::numeric_limits<real_type>::radix == 2), - "RealType representation is not IEEE 754 binary."); - - static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value || - std::is_same<SignedTag, GenerateNegativeTag>::value || - std::is_same<SignedTag, GenerateSignedTag>::value), - ""); - - static constexpr int kExp = std::numeric_limits<real_type>::digits - 1; - static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u; - static constexpr int kUintBits = sizeof(uint_type) * 8; - - int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2}; - - // Determine the sign bit. - // Depending on the SignedTag, this may use the left-most bit - // or it may be a constant value. - uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value - ? (static_cast<uint_type>(1) << (kUintBits - 1)) - : 0; - if (std::is_same<SignedTag, GenerateSignedTag>::value) { - if (std::is_same<uint_type, uint64_t>::value) { - sign = bits & uint64_t{0x8000000000000000}; - } - if (std::is_same<uint_type, uint32_t>::value) { - const uint64_t tmp = bits & uint64_t{0x8000000000000000}; - sign = static_cast<uint32_t>(tmp >> 32); - } - // adjust the bits and the exponent to account for removing - // the leading bit. - bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF}; - exp++; - } - if (IncludeZero) { - if (bits == 0u) return 0; - } - - // Number of leading zeros is mapped to the exponent: 2^-clz - // bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0 - int clz = 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 = - (std::is_same<SignedTag, GeneratePositiveTag>::value ? 0u : sign) | - (static_cast<uint_type>(exp) << kExp) | - (static_cast<uint_type>(bits) & kMask); - - // bit_cast to the output-type - real_type result; - memcpy(static_cast<void*>(&result), static_cast<const void*>(&val), - sizeof(result)); - return result; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/generate_real_test.cc b/third_party/abseil_cpp/absl/random/internal/generate_real_test.cc deleted file mode 100644 index 4bdc453483e4..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/generate_real_test.cc +++ /dev/null @@ -1,497 +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/generate_real.h" - -#include <cfloat> -#include <cstddef> -#include <cstdint> -#include <string> - -#include "gtest/gtest.h" -#include "absl/base/internal/bits.h" -#include "absl/flags/flag.h" - -ABSL_FLAG(int64_t, absl_random_test_trials, 50000, - "Number of trials for the probability tests."); - -using absl::random_internal::GenerateNegativeTag; -using absl::random_internal::GeneratePositiveTag; -using absl::random_internal::GenerateRealFromBits; -using absl::random_internal::GenerateSignedTag; - -namespace { - -TEST(GenerateRealTest, U64ToFloat_Positive_NoZero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GeneratePositiveTag, false>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 2.710505431e-20f); - EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f); - EXPECT_EQ(ToFloat(0x8000000000000000), 0.5); - EXPECT_EQ(ToFloat(0x8000000000000001), 0.5); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Positive_Zero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GeneratePositiveTag, true>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 0.0); - EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f); - EXPECT_EQ(ToFloat(0x8000000000000000), 0.5); - EXPECT_EQ(ToFloat(0x8000000000000001), 0.5); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Negative_NoZero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GenerateNegativeTag, false>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), -2.710505431e-20f); - EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f); - EXPECT_EQ(ToFloat(0x8000000000000000), -0.5); - EXPECT_EQ(ToFloat(0x8000000000000001), -0.5); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Negative_Zero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GenerateNegativeTag, true>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 0.0); - EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f); - EXPECT_EQ(ToFloat(0x8000000000000000), -0.5); - EXPECT_EQ(ToFloat(0x8000000000000001), -0.5); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Signed_NoZero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GenerateSignedTag, false>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 5.421010862e-20f); - EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f); - EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f); - EXPECT_EQ(ToFloat(0x8000000000000000), -5.421010862e-20f); - EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Signed_Zero_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GenerateSignedTag, true>(a); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 0); - EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f); - EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f); - EXPECT_EQ(ToFloat(0x8000000000000000), 0); - EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloat_Signed_Bias_Test) { - auto ToFloat = [](uint64_t a) { - return GenerateRealFromBits<float, GenerateSignedTag, true>(a, 1); - }; - EXPECT_EQ(ToFloat(0x0000000000000000), 0); - EXPECT_EQ(ToFloat(0x0000000000000001), 2 * 1.084202172e-19f); - EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 2 * 0.9999999404f); - EXPECT_EQ(ToFloat(0x8000000000000000), 0); - EXPECT_EQ(ToFloat(0x8000000000000001), 2 * -1.084202172e-19f); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 2 * -0.9999999404f); -} - -TEST(GenerateRealTest, U64ToFloatTest) { - auto ToFloat = [](uint64_t a) -> float { - return GenerateRealFromBits<float, GeneratePositiveTag, true>(a); - }; - - EXPECT_EQ(ToFloat(0x0000000000000000), 0.0f); - - EXPECT_EQ(ToFloat(0x8000000000000000), 0.5f); - EXPECT_EQ(ToFloat(0x8000000000000001), 0.5f); - EXPECT_EQ(ToFloat(0x800000FFFFFFFFFF), 0.5f); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f); - - EXPECT_GT(ToFloat(0x0000000000000001), 0.0f); - - EXPECT_NE(ToFloat(0x7FFFFF0000000000), ToFloat(0x7FFFFEFFFFFFFFFF)); - - EXPECT_LT(ToFloat(0xFFFFFFFFFFFFFFFF), 1.0f); - int32_t two_to_24 = 1 << 24; - EXPECT_EQ(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24), - two_to_24 - 1); - EXPECT_NE(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24 * 2), - two_to_24 * 2 - 1); - EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFF0000000000)); - EXPECT_NE(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFEFFFFFFFFFF)); - EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF8000000000)); - EXPECT_NE(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF7FFFFFFFFF)); - EXPECT_EQ(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFC000000000)); - EXPECT_NE(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFBFFFFFFFFF)); - - // For values where every bit counts, the values scale as multiples of the - // input. - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(i * ToFloat(0x0000000000000001), ToFloat(i)); - } - - // For each i: value generated from (1 << i). - float exp_values[64]; - exp_values[63] = 0.5f; - for (int i = 62; i >= 0; --i) exp_values[i] = 0.5f * exp_values[i + 1]; - constexpr uint64_t one = 1; - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(ToFloat(one << i), exp_values[i]); - for (int j = 1; j < FLT_MANT_DIG && i - j >= 0; ++j) { - EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]); - EXPECT_EQ(ToFloat((one << i) + (one << (i - j))), - exp_values[i] + exp_values[i - j]); - } - for (int j = FLT_MANT_DIG; i - j >= 0; ++j) { - EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]); - EXPECT_EQ(ToFloat((one << i) + (one << (i - j))), exp_values[i]); - } - } -} - -TEST(GenerateRealTest, U64ToDouble_Positive_NoZero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GeneratePositiveTag, false>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 2.710505431213761085e-20); - EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x0000000000000002), 1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0x8000000000000000), 0.5); - EXPECT_EQ(ToDouble(0x8000000000000001), 0.5); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_Positive_Zero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GeneratePositiveTag, true>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 0.0); - EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x8000000000000000), 0.5); - EXPECT_EQ(ToDouble(0x8000000000000001), 0.5); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_Negative_NoZero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateNegativeTag, false>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), -2.710505431213761085e-20); - EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0x8000000000000000), -0.5); - EXPECT_EQ(ToDouble(0x8000000000000001), -0.5); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_Negative_Zero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateNegativeTag, true>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 0.0); - EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0x8000000000000000), -0.5); - EXPECT_EQ(ToDouble(0x8000000000000001), -0.5); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_Signed_NoZero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateSignedTag, false>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978); - EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_Signed_Zero_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateSignedTag, true>(a); - }; - EXPECT_EQ(ToDouble(0x0000000000000000), 0); - EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978); - EXPECT_EQ(ToDouble(0x8000000000000000), 0); - EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978); -} - -TEST(GenerateRealTest, U64ToDouble_GenerateSignedTag_Bias_Test) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateSignedTag, true>(a, -1); - }; - EXPECT_EQ(ToDouble(0x0000000000000000), 0); - EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19 / 2); - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978 / 2); - EXPECT_EQ(ToDouble(0x8000000000000000), 0); - EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19 / 2); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978 / 2); -} - -TEST(GenerateRealTest, U64ToDoubleTest) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GeneratePositiveTag, true>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 0.0); - EXPECT_EQ(ToDouble(0x0000000000000000), 0.0); - - EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x7fffffffffffffef), 0.499999999999999944489); - EXPECT_EQ(ToDouble(0x8000000000000000), 0.5); - - // For values > 0.5, RandU64ToDouble discards up to 11 bits. (64-53). - EXPECT_EQ(ToDouble(0x8000000000000001), 0.5); - EXPECT_EQ(ToDouble(0x80000000000007FF), 0.5); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978); - EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF)); - - EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFF), 1.0); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF800)); - EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF7FF)); - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00)); - EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFBFF)); - EXPECT_EQ(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFE00)); - EXPECT_NE(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFDFF)); - - EXPECT_EQ(ToDouble(0x1000000000000001), 0.0625); - EXPECT_EQ(ToDouble(0x2000000000000001), 0.125); - EXPECT_EQ(ToDouble(0x3000000000000001), 0.1875); - EXPECT_EQ(ToDouble(0x4000000000000001), 0.25); - EXPECT_EQ(ToDouble(0x5000000000000001), 0.3125); - EXPECT_EQ(ToDouble(0x6000000000000001), 0.375); - EXPECT_EQ(ToDouble(0x7000000000000001), 0.4375); - EXPECT_EQ(ToDouble(0x8000000000000001), 0.5); - EXPECT_EQ(ToDouble(0x9000000000000001), 0.5625); - EXPECT_EQ(ToDouble(0xa000000000000001), 0.625); - EXPECT_EQ(ToDouble(0xb000000000000001), 0.6875); - EXPECT_EQ(ToDouble(0xc000000000000001), 0.75); - EXPECT_EQ(ToDouble(0xd000000000000001), 0.8125); - EXPECT_EQ(ToDouble(0xe000000000000001), 0.875); - EXPECT_EQ(ToDouble(0xf000000000000001), 0.9375); - - // Large powers of 2. - int64_t two_to_53 = int64_t{1} << 53; - EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53), - two_to_53 - 1); - EXPECT_NE(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53 * 2), - two_to_53 * 2 - 1); - - // For values where every bit counts, the values scale as multiples of the - // input. - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(i * ToDouble(0x0000000000000001), ToDouble(i)); - } - - // For each i: value generated from (1 << i). - double exp_values[64]; - exp_values[63] = 0.5; - for (int i = 62; i >= 0; --i) exp_values[i] = 0.5 * exp_values[i + 1]; - constexpr uint64_t one = 1; - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(ToDouble(one << i), exp_values[i]); - for (int j = 1; j < DBL_MANT_DIG && i - j >= 0; ++j) { - EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]); - EXPECT_EQ(ToDouble((one << i) + (one << (i - j))), - exp_values[i] + exp_values[i - j]); - } - for (int j = DBL_MANT_DIG; i - j >= 0; ++j) { - EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]); - EXPECT_EQ(ToDouble((one << i) + (one << (i - j))), exp_values[i]); - } - } -} - -TEST(GenerateRealTest, U64ToDoubleSignedTest) { - auto ToDouble = [](uint64_t a) { - return GenerateRealFromBits<double, GenerateSignedTag, false>(a); - }; - - EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19); - - EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20); - EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19); - - const double e_plus = ToDouble(0x0000000000000001); - const double e_minus = ToDouble(0x8000000000000001); - EXPECT_EQ(e_plus, 1.084202172485504434e-19); - EXPECT_EQ(e_minus, -1.084202172485504434e-19); - - EXPECT_EQ(ToDouble(0x3fffffffffffffef), 0.499999999999999944489); - EXPECT_EQ(ToDouble(0xbfffffffffffffef), -0.499999999999999944489); - - // For values > 0.5, RandU64ToDouble discards up to 10 bits. (63-53). - EXPECT_EQ(ToDouble(0x4000000000000000), 0.5); - EXPECT_EQ(ToDouble(0x4000000000000001), 0.5); - EXPECT_EQ(ToDouble(0x40000000000003FF), 0.5); - - EXPECT_EQ(ToDouble(0xC000000000000000), -0.5); - EXPECT_EQ(ToDouble(0xC000000000000001), -0.5); - EXPECT_EQ(ToDouble(0xC0000000000003FF), -0.5); - - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFe), 0.999999999999999888978); - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999999999888978); - - EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF)); - - EXPECT_LT(ToDouble(0x7FFFFFFFFFFFFFFF), 1.0); - EXPECT_GT(ToDouble(0x7FFFFFFFFFFFFFFF), 0.9999999999); - - EXPECT_GT(ToDouble(0xFFFFFFFFFFFFFFFe), -1.0); - EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999); - - EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFFC00)); - EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00)); - EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFF3FF)); - EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFF3FF)); - - EXPECT_EQ(ToDouble(0x1000000000000001), 0.125); - EXPECT_EQ(ToDouble(0x2000000000000001), 0.25); - EXPECT_EQ(ToDouble(0x3000000000000001), 0.375); - EXPECT_EQ(ToDouble(0x4000000000000001), 0.5); - EXPECT_EQ(ToDouble(0x5000000000000001), 0.625); - EXPECT_EQ(ToDouble(0x6000000000000001), 0.75); - EXPECT_EQ(ToDouble(0x7000000000000001), 0.875); - EXPECT_EQ(ToDouble(0x7800000000000001), 0.9375); - EXPECT_EQ(ToDouble(0x7c00000000000001), 0.96875); - EXPECT_EQ(ToDouble(0x7e00000000000001), 0.984375); - EXPECT_EQ(ToDouble(0x7f00000000000001), 0.9921875); - - // 0x8000000000000000 ~= 0 - EXPECT_EQ(ToDouble(0x9000000000000001), -0.125); - EXPECT_EQ(ToDouble(0xa000000000000001), -0.25); - EXPECT_EQ(ToDouble(0xb000000000000001), -0.375); - EXPECT_EQ(ToDouble(0xc000000000000001), -0.5); - EXPECT_EQ(ToDouble(0xd000000000000001), -0.625); - EXPECT_EQ(ToDouble(0xe000000000000001), -0.75); - EXPECT_EQ(ToDouble(0xf000000000000001), -0.875); - - // Large powers of 2. - int64_t two_to_53 = int64_t{1} << 53; - EXPECT_EQ(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53), - two_to_53 - 1); - EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53), - -(two_to_53 - 1)); - - EXPECT_NE(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53 * 2), - two_to_53 * 2 - 1); - - // For values where every bit counts, the values scale as multiples of the - // input. - for (int i = 1; i < 100; ++i) { - EXPECT_EQ(i * e_plus, ToDouble(i)) << i; - EXPECT_EQ(i * e_minus, ToDouble(0x8000000000000000 | i)) << i; - } -} - -TEST(GenerateRealTest, ExhaustiveFloat) { - 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 - // greater than or equal to the previous value, then there is a collision in - // the generation algorithm. - // - // Use the computation below to convert the random value into a result: - // double res = a() * (1.0f - sample) + b() * sample; - float last_f = 1.0, last_g = 2.0; - uint64_t f_collisions = 0, g_collisions = 0; - uint64_t f_unique = 0, g_unique = 0; - uint64_t total = 0; - auto count = [&](const float r) { - total++; - // `f` is mapped to the range [0, 1) (default) - const float f = 0.0f * (1.0f - r) + 1.0f * r; - if (f >= last_f) { - f_collisions++; - } else { - f_unique++; - last_f = f; - } - // `g` is mapped to the range [1, 2) - const float g = 1.0f * (1.0f - r) + 2.0f * r; - if (g >= last_g) { - g_collisions++; - } else { - g_unique++; - last_g = g; - } - }; - - size_t limit = absl::GetFlag(FLAGS_absl_random_test_trials); - - // Generate all uint64_t which have unique floating point values. - // Counting down from 0xFFFFFFFFFFFFFFFFu ... 0x0u - uint64_t x = ~uint64_t(0); - for (; x != 0 && limit > 0;) { - constexpr int kDig = (64 - FLT_MANT_DIG); - // Set a decrement value & the next point at which to change - // the decrement value. By default these are 1, 0. - uint64_t dec = 1; - uint64_t chk = 0; - - // Adjust decrement and check value based on how many leading 0 - // bits are set in the current value. - const int clz = CountLeadingZeros64(x); - if (clz < kDig) { - dec <<= (kDig - clz); - chk = (~uint64_t(0)) >> (clz + 1); - } - for (; x > chk && limit > 0; x -= dec) { - count(ToFloat(x)); - --limit; - } - } - - static_assert(FLT_MANT_DIG == 24, - "The float type is expected to have a 24 bit mantissa."); - - if (limit != 0) { - // There are between 2^28 and 2^29 unique values in the range [0, 1). For - // the low values of x, there are 2^24 -1 unique values. Once x > 2^24, - // there are 40 * 2^24 unique values. Thus: - // (2 + 4 + 8 ... + 2^23) + 40 * 2^23 - EXPECT_LT(1 << 28, f_unique); - EXPECT_EQ((1 << 24) + 40 * (1 << 23) - 1, f_unique); - EXPECT_EQ(total, f_unique); - EXPECT_EQ(0, f_collisions); - - // Expect at least 2^23 unique values for the range [1, 2) - EXPECT_LE(1 << 23, g_unique); - EXPECT_EQ(total - g_unique, g_collisions); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/iostream_state_saver.h b/third_party/abseil_cpp/absl/random/internal/iostream_state_saver.h deleted file mode 100644 index e6e242ee1e66..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/iostream_state_saver.h +++ /dev/null @@ -1,245 +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. - -#ifndef ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_ -#define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_ - -#include <cmath> -#include <iostream> -#include <limits> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/numeric/int128.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// The null_state_saver does nothing. -template <typename T> -class null_state_saver { - public: - using stream_type = T; - using flags_type = std::ios_base::fmtflags; - - null_state_saver(T&, flags_type) {} - ~null_state_saver() {} -}; - -// ostream_state_saver is a RAII object to save and restore the common -// basic_ostream flags used when implementing `operator <<()` on any of -// the absl random distributions. -template <typename OStream> -class ostream_state_saver { - public: - using ostream_type = OStream; - using flags_type = std::ios_base::fmtflags; - using fill_type = typename ostream_type::char_type; - using precision_type = std::streamsize; - - ostream_state_saver(ostream_type& os, // NOLINT(runtime/references) - flags_type flags, fill_type fill) - : os_(os), - flags_(os.flags(flags)), - fill_(os.fill(fill)), - precision_(os.precision()) { - // Save state in initialized variables. - } - - ~ostream_state_saver() { - // Restore saved state. - os_.precision(precision_); - os_.fill(fill_); - os_.flags(flags_); - } - - private: - ostream_type& os_; - const flags_type flags_; - const fill_type fill_; - const precision_type precision_; -}; - -#if defined(__NDK_MAJOR__) && __NDK_MAJOR__ < 16 -#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 1 -#else -#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 0 -#endif - -template <typename CharT, typename Traits> -ostream_state_saver<std::basic_ostream<CharT, Traits>> make_ostream_state_saver( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - std::ios_base::fmtflags flags = std::ios_base::dec | std::ios_base::left | -#if ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT - std::ios_base::fixed | -#endif - std::ios_base::scientific) { - using result_type = ostream_state_saver<std::basic_ostream<CharT, Traits>>; - return result_type(os, flags, os.widen(' ')); -} - -template <typename T> -typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value, - null_state_saver<T>> -make_ostream_state_saver(T& is, // NOLINT(runtime/references) - std::ios_base::fmtflags flags = std::ios_base::dec) { - std::cerr << "null_state_saver"; - using result_type = null_state_saver<T>; - return result_type(is, flags); -} - -// stream_precision_helper<type>::kPrecision returns the base 10 precision -// required to stream and reconstruct a real type exact binary value through -// a binary->decimal->binary transition. -template <typename T> -struct stream_precision_helper { - // max_digits10 may be 0 on MSVC; if so, use digits10 + 3. - static constexpr int kPrecision = - (std::numeric_limits<T>::max_digits10 > std::numeric_limits<T>::digits10) - ? std::numeric_limits<T>::max_digits10 - : (std::numeric_limits<T>::digits10 + 3); -}; - -template <> -struct stream_precision_helper<float> { - static constexpr int kPrecision = 9; -}; -template <> -struct stream_precision_helper<double> { - static constexpr int kPrecision = 17; -}; -template <> -struct stream_precision_helper<long double> { - static constexpr int kPrecision = 36; // assuming fp128 -}; - -// istream_state_saver is a RAII object to save and restore the common -// std::basic_istream<> flags used when implementing `operator >>()` on any of -// the absl random distributions. -template <typename IStream> -class istream_state_saver { - public: - using istream_type = IStream; - using flags_type = std::ios_base::fmtflags; - - istream_state_saver(istream_type& is, // NOLINT(runtime/references) - flags_type flags) - : is_(is), flags_(is.flags(flags)) {} - - ~istream_state_saver() { is_.flags(flags_); } - - private: - istream_type& is_; - flags_type flags_; -}; - -template <typename CharT, typename Traits> -istream_state_saver<std::basic_istream<CharT, Traits>> make_istream_state_saver( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - std::ios_base::fmtflags flags = std::ios_base::dec | - std::ios_base::scientific | - std::ios_base::skipws) { - using result_type = istream_state_saver<std::basic_istream<CharT, Traits>>; - return result_type(is, flags); -} - -template <typename T> -typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value, - null_state_saver<T>> -make_istream_state_saver(T& is, // NOLINT(runtime/references) - std::ios_base::fmtflags flags = std::ios_base::dec) { - using result_type = null_state_saver<T>; - return result_type(is, flags); -} - -// stream_format_type<T> is a helper struct to convert types which -// basic_iostream cannot output as decimal numbers into types which -// basic_iostream can output as decimal numbers. Specifically: -// * signed/unsigned char-width types are converted to int. -// * TODO(lar): __int128 => uint128, except there is no operator << yet. -// -template <typename T> -struct stream_format_type - : public std::conditional<(sizeof(T) == sizeof(char)), int, T> {}; - -// stream_u128_helper allows us to write out either absl::uint128 or -// __uint128_t types in the same way, which enables their use as internal -// state of PRNG engines. -template <typename T> -struct stream_u128_helper; - -template <> -struct stream_u128_helper<absl::uint128> { - template <typename IStream> - inline absl::uint128 read(IStream& in) { - uint64_t h = 0; - uint64_t l = 0; - in >> h >> l; - return absl::MakeUint128(h, l); - } - - template <typename OStream> - inline void write(absl::uint128 val, OStream& out) { - uint64_t h = absl::Uint128High64(val); - uint64_t l = absl::Uint128Low64(val); - out << h << out.fill() << l; - } -}; - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -template <> -struct stream_u128_helper<__uint128_t> { - template <typename IStream> - inline __uint128_t read(IStream& in) { - uint64_t h = 0; - uint64_t l = 0; - in >> h >> l; - return (static_cast<__uint128_t>(h) << 64) | l; - } - - template <typename OStream> - inline void write(__uint128_t val, OStream& out) { - uint64_t h = static_cast<uint64_t>(val >> 64u); - uint64_t l = static_cast<uint64_t>(val); - out << h << out.fill() << l; - } -}; -#endif - -template <typename FloatType, typename IStream> -inline FloatType read_floating_point(IStream& is) { - static_assert(std::is_floating_point<FloatType>::value, ""); - FloatType dest; - is >> dest; - // Parsing a double value may report a subnormal value as an error - // despite being able to represent it. - // See https://stackoverflow.com/q/52410931/3286653 - // It may also report an underflow when parsing DOUBLE_MIN as an - // ERANGE error, as the parsed value may be smaller than DOUBLE_MIN - // and rounded up. - // See: https://stackoverflow.com/q/42005462 - if (is.fail() && - (std::fabs(dest) == (std::numeric_limits<FloatType>::min)() || - std::fpclassify(dest) == FP_SUBNORMAL)) { - is.clear(is.rdstate() & (~std::ios_base::failbit)); - } - return dest; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_ diff --git a/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 deleted file mode 100644 index 7bb8ad959cf6..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/iostream_state_saver_test.cc +++ /dev/null @@ -1,371 +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/iostream_state_saver.h" - -#include <sstream> -#include <string> - -#include "gtest/gtest.h" - -namespace { - -using absl::random_internal::make_istream_state_saver; -using absl::random_internal::make_ostream_state_saver; -using absl::random_internal::stream_precision_helper; - -template <typename T> -typename absl::enable_if_t<std::is_integral<T>::value, T> // -StreamRoundTrip(T t) { - std::stringstream ss; - { - auto saver = make_ostream_state_saver(ss); - ss.precision(stream_precision_helper<T>::kPrecision); - ss << t; - } - T result = 0; - { - auto saver = make_istream_state_saver(ss); - ss >> result; - } - EXPECT_FALSE(ss.fail()) // - << ss.str() << " " // - << (ss.good() ? "good " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - - return result; -} - -template <typename T> -typename absl::enable_if_t<std::is_floating_point<T>::value, T> // -StreamRoundTrip(T t) { - std::stringstream ss; - { - auto saver = make_ostream_state_saver(ss); - ss.precision(stream_precision_helper<T>::kPrecision); - ss << t; - } - T result = 0; - { - auto saver = make_istream_state_saver(ss); - result = absl::random_internal::read_floating_point<T>(ss); - } - EXPECT_FALSE(ss.fail()) // - << ss.str() << " " // - << (ss.good() ? "good " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - - return result; -} - -TEST(IOStreamStateSaver, BasicSaverState) { - std::stringstream ss; - ss.precision(2); - ss.fill('x'); - ss.flags(std::ios_base::dec | std::ios_base::right); - - { - auto saver = make_ostream_state_saver(ss); - ss.precision(10); - EXPECT_NE('x', ss.fill()); - EXPECT_EQ(10, ss.precision()); - EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags()); - - ss << 1.23; - } - - EXPECT_EQ('x', ss.fill()); - EXPECT_EQ(2, ss.precision()); - EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags()); -} - -TEST(IOStreamStateSaver, RoundTripInts) { - const uint64_t kUintValues[] = { - 0, - 1, - static_cast<uint64_t>(-1), - 2, - static_cast<uint64_t>(-2), - - 1 << 7, - 1 << 8, - 1 << 16, - 1ull << 32, - 1ull << 50, - 1ull << 62, - 1ull << 63, - - (1 << 7) - 1, - (1 << 8) - 1, - (1 << 16) - 1, - (1ull << 32) - 1, - (1ull << 50) - 1, - (1ull << 62) - 1, - (1ull << 63) - 1, - - static_cast<uint64_t>(-(1 << 8)), - static_cast<uint64_t>(-(1 << 16)), - static_cast<uint64_t>(-(1ll << 32)), - static_cast<uint64_t>(-(1ll << 50)), - static_cast<uint64_t>(-(1ll << 62)), - - static_cast<uint64_t>(-(1 << 8) - 1), - static_cast<uint64_t>(-(1 << 16) - 1), - static_cast<uint64_t>(-(1ll << 32) - 1), - static_cast<uint64_t>(-(1ll << 50) - 1), - static_cast<uint64_t>(-(1ll << 62) - 1), - }; - - for (const uint64_t u : kUintValues) { - EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u)); - - int64_t x = static_cast<int64_t>(u); - EXPECT_EQ(x, StreamRoundTrip<int64_t>(x)); - - double d = static_cast<double>(x); - EXPECT_EQ(d, StreamRoundTrip<double>(d)); - - float f = d; - EXPECT_EQ(f, StreamRoundTrip<float>(f)); - } -} - -TEST(IOStreamStateSaver, RoundTripFloats) { - static_assert( - stream_precision_helper<float>::kPrecision >= 9, - "stream_precision_helper<float>::kPrecision should be at least 9"); - - const float kValues[] = { - 1, - std::nextafter(1.0f, 0.0f), // 1 - epsilon - std::nextafter(1.0f, 2.0f), // 1 + epsilon - - 1.0e+1f, - 1.0e-1f, - 1.0e+2f, - 1.0e-2f, - 1.0e+10f, - 1.0e-10f, - - 0.00000051110000111311111111f, - -0.00000051110000111211111111f, - - 1.234678912345678912345e+6f, - 1.234678912345678912345e-6f, - 1.234678912345678912345e+30f, - 1.234678912345678912345e-30f, - 1.234678912345678912345e+38f, - 1.0234678912345678912345e-38f, - - // Boundary cases. - std::numeric_limits<float>::max(), - std::numeric_limits<float>::lowest(), - std::numeric_limits<float>::epsilon(), - std::nextafter(std::numeric_limits<float>::min(), - 1.0f), // min + epsilon - std::numeric_limits<float>::min(), // smallest normal - // There are some errors dealing with denorms on apple platforms. - std::numeric_limits<float>::denorm_min(), // smallest denorm - std::numeric_limits<float>::min() / 2, - std::nextafter(std::numeric_limits<float>::min(), - 0.0f), // denorm_max - std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f), - }; - - for (const float f : kValues) { - EXPECT_EQ(f, StreamRoundTrip<float>(f)); - EXPECT_EQ(-f, StreamRoundTrip<float>(-f)); - - double d = f; - EXPECT_EQ(d, StreamRoundTrip<double>(d)); - EXPECT_EQ(-d, StreamRoundTrip<double>(-d)); - - // Avoid undefined behavior (overflow/underflow). - if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) && - f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) { - int64_t x = static_cast<int64_t>(f); - EXPECT_EQ(x, StreamRoundTrip<int64_t>(x)); - } - } -} - -TEST(IOStreamStateSaver, RoundTripDoubles) { - static_assert( - stream_precision_helper<double>::kPrecision >= 17, - "stream_precision_helper<double>::kPrecision should be at least 17"); - - const double kValues[] = { - 1, - std::nextafter(1.0, 0.0), // 1 - epsilon - std::nextafter(1.0, 2.0), // 1 + epsilon - - 1.0e+1, - 1.0e-1, - 1.0e+2, - 1.0e-2, - 1.0e+10, - 1.0e-10, - - 0.00000051110000111311111111, - -0.00000051110000111211111111, - - 1.234678912345678912345e+6, - 1.234678912345678912345e-6, - 1.234678912345678912345e+30, - 1.234678912345678912345e-30, - 1.234678912345678912345e+38, - 1.0234678912345678912345e-38, - - 1.0e+100, - 1.0e-100, - 1.234678912345678912345e+308, - 1.0234678912345678912345e-308, - 2.22507385850720138e-308, - - // Boundary cases. - std::numeric_limits<double>::max(), - std::numeric_limits<double>::lowest(), - std::numeric_limits<double>::epsilon(), - std::nextafter(std::numeric_limits<double>::min(), - 1.0), // min + epsilon - std::numeric_limits<double>::min(), // smallest normal - // There are some errors dealing with denorms on apple platforms. - std::numeric_limits<double>::denorm_min(), // smallest denorm - std::numeric_limits<double>::min() / 2, - std::nextafter(std::numeric_limits<double>::min(), - 0.0), // denorm_max - std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f), - }; - - for (const double d : kValues) { - EXPECT_EQ(d, StreamRoundTrip<double>(d)); - EXPECT_EQ(-d, StreamRoundTrip<double>(-d)); - - // Avoid undefined behavior (overflow/underflow). - if (d <= std::numeric_limits<float>::max() && - d >= std::numeric_limits<float>::lowest()) { - float f = static_cast<float>(d); - EXPECT_EQ(f, StreamRoundTrip<float>(f)); - } - - // Avoid undefined behavior (overflow/underflow). - if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) && - d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) { - int64_t x = static_cast<int64_t>(d); - EXPECT_EQ(x, StreamRoundTrip<int64_t>(x)); - } - } -} - -#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. - // - // So it is best to consider long double a best-effort extended precision - // type. - - static_assert( - stream_precision_helper<long double>::kPrecision >= 36, - "stream_precision_helper<long double>::kPrecision should be at least 36"); - - using real_type = long double; - const real_type kValues[] = { - 1, - std::nextafter(1.0, 0.0), // 1 - epsilon - std::nextafter(1.0, 2.0), // 1 + epsilon - - 1.0e+1, - 1.0e-1, - 1.0e+2, - 1.0e-2, - 1.0e+10, - 1.0e-10, - - 0.00000051110000111311111111, - -0.00000051110000111211111111, - - 1.2346789123456789123456789123456789e+6, - 1.2346789123456789123456789123456789e-6, - 1.2346789123456789123456789123456789e+30, - 1.2346789123456789123456789123456789e-30, - 1.2346789123456789123456789123456789e+38, - 1.2346789123456789123456789123456789e-38, - 1.2346789123456789123456789123456789e+308, - 1.2346789123456789123456789123456789e-308, - - 1.0e+100, - 1.0e-100, - 1.234678912345678912345e+308, - 1.0234678912345678912345e-308, - - // Boundary cases. - std::numeric_limits<real_type>::max(), - std::numeric_limits<real_type>::lowest(), - std::numeric_limits<real_type>::epsilon(), - std::nextafter(std::numeric_limits<real_type>::min(), - real_type(1)), // min + epsilon - std::numeric_limits<real_type>::min(), // smallest normal - // There are some errors dealing with denorms on apple platforms. - std::numeric_limits<real_type>::denorm_min(), // smallest denorm - std::numeric_limits<real_type>::min() / 2, - std::nextafter(std::numeric_limits<real_type>::min(), - 0.0), // denorm_max - std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f), - }; - - int index = -1; - for (const long double dd : kValues) { - index++; - EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index; - EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index; - - // Avoid undefined behavior (overflow/underflow). - if (dd <= std::numeric_limits<double>::max() && - dd >= std::numeric_limits<double>::lowest()) { - double d = static_cast<double>(dd); - EXPECT_EQ(d, StreamRoundTrip<double>(d)); - } - - // Avoid undefined behavior (overflow/underflow). - if (dd <= std::numeric_limits<int64_t>::max() && - dd >= std::numeric_limits<int64_t>::lowest()) { - int64_t x = static_cast<int64_t>(dd); - EXPECT_EQ(x, StreamRoundTrip<int64_t>(x)); - } - } -} -#endif // !defined(__EMSCRIPTEN__) - -TEST(StrToDTest, DoubleMin) { - const char kV[] = "2.22507385850720138e-308"; - char* end; - double x = std::strtod(kV, &end); - EXPECT_EQ(std::numeric_limits<double>::min(), x); - // errno may equal ERANGE. -} - -TEST(StrToDTest, DoubleDenormMin) { - const char kV[] = "4.94065645841246544e-324"; - char* end; - double x = std::strtod(kV, &end); - EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x); - // errno may equal ERANGE. -} - -} // namespace diff --git a/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 9af27ab3a210..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/mock_helpers.h +++ /dev/null @@ -1,127 +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: - // 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( - std::declval<MockURBG>() - .template RegisterMock<typename KeySignature<KeyT>::result_type, - typename KeySignature<KeyT>::arg_tuple_type>( - std::declval<IdType>())) { - return m.template RegisterMock<typename KeySignature<KeyT>::result_type, - typename KeySignature<KeyT>::arg_tuple_type>( - ::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 deleted file mode 100644 index dccc6cee679c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/mock_overload_set.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. - -#ifndef ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_ -#define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_ - -#include <type_traits> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/random/internal/mock_helpers.h" -#include "absl/random/mocking_bit_gen.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -template <typename DistrT, typename Fn> -struct MockSingleOverload; - -// MockSingleOverload -// -// MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros. -// EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to -// `mock_single_overload.gmock_Call(...)`. Because expectations are stored on -// the MockingBitGen (an argument passed inside `Call(...)`), this forwards to -// arguments to MockingBitGen::Register. -// -// The underlying KeyT must match the KeyT constructed by DistributionCaller. -template <typename DistrT, typename Ret, typename... Args> -struct MockSingleOverload<DistrT, Ret(MockingBitGen&, Args...)> { - static_assert(std::is_same<typename DistrT::result_type, Ret>::value, - "Overload signature must have return type matching the " - "distribution result_type."); - using KeyT = Ret(DistrT, std::tuple<Args...>); - auto gmock_Call( - absl::MockingBitGen& gen, // NOLINT(google-runtime-references) - const ::testing::Matcher<Args>&... matchers) - -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...)) { - return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...); - } -}; - -template <typename DistrT, typename Ret, typename Arg, typename... Args> -struct MockSingleOverload<DistrT, Ret(Arg, MockingBitGen&, Args...)> { - static_assert(std::is_same<typename DistrT::result_type, Ret>::value, - "Overload signature must have return type matching the " - "distribution result_type."); - using KeyT = Ret(DistrT, std::tuple<Arg, Args...>); - auto gmock_Call( - const ::testing::Matcher<Arg>& matcher, - absl::MockingBitGen& gen, // NOLINT(google-runtime-references) - const ::testing::Matcher<Args>&... matchers) - -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, - matchers...)) { - return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, matchers...); - } -}; - -// MockOverloadSet -// -// MockOverloadSet takes a distribution and a collection of signatures and -// performs overload resolution amongst all the overloads. This makes -// `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution -// correctly. -template <typename DistrT, typename... Signatures> -struct MockOverloadSet; - -template <typename DistrT, typename Sig> -struct MockOverloadSet<DistrT, Sig> : public MockSingleOverload<DistrT, Sig> { - using MockSingleOverload<DistrT, Sig>::gmock_Call; -}; - -template <typename DistrT, typename FirstSig, typename... Rest> -struct MockOverloadSet<DistrT, FirstSig, Rest...> - : public MockSingleOverload<DistrT, FirstSig>, - public MockOverloadSet<DistrT, Rest...> { - using MockSingleOverload<DistrT, FirstSig>::gmock_Call; - using MockOverloadSet<DistrT, Rest...>::gmock_Call; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/nanobenchmark.cc b/third_party/abseil_cpp/absl/random/internal/nanobenchmark.cc deleted file mode 100644 index c9181813f7f0..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/nanobenchmark.cc +++ /dev/null @@ -1,804 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/random/internal/nanobenchmark.h" - -#include <sys/types.h> - -#include <algorithm> // sort -#include <atomic> -#include <cstddef> -#include <cstdint> -#include <cstdlib> -#include <cstring> // memcpy -#include <limits> -#include <string> -#include <utility> -#include <vector> - -#include "absl/base/attributes.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_engine.h" - -// OS -#if defined(_WIN32) || defined(_WIN64) -#define ABSL_OS_WIN -#include <windows.h> // NOLINT - -#elif defined(__ANDROID__) -#define ABSL_OS_ANDROID - -#elif defined(__linux__) -#define ABSL_OS_LINUX -#include <sched.h> // NOLINT -#include <sys/syscall.h> // NOLINT -#endif - -#if defined(ABSL_ARCH_X86_64) && !defined(ABSL_OS_WIN) -#include <cpuid.h> // NOLINT -#endif - -// __ppc_get_timebase_freq -#if defined(ABSL_ARCH_PPC) -#include <sys/platform/ppc.h> // NOLINT -#endif - -// clock_gettime -#if defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64) -#include <time.h> // NOLINT -#endif - -// ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method. -#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __declspec(noinline) -#else -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal_nanobenchmark { -namespace { - -// For code folding. -namespace platform { -#if defined(ABSL_ARCH_X86_64) - -// TODO(janwas): Merge with the one in randen_hwaes.cc? -void Cpuid(const uint32_t level, const uint32_t count, - uint32_t* ABSL_RANDOM_INTERNAL_RESTRICT abcd) { -#if defined(ABSL_OS_WIN) - int regs[4]; - __cpuidex(regs, level, count); - for (int i = 0; i < 4; ++i) { - abcd[i] = regs[i]; - } -#else - uint32_t a, b, c, d; - __cpuid_count(level, count, a, b, c, d); - abcd[0] = a; - abcd[1] = b; - abcd[2] = c; - abcd[3] = d; -#endif -} - -std::string BrandString() { - char brand_string[49]; - uint32_t abcd[4]; - - // Check if brand string is supported (it is on all reasonable Intel/AMD) - Cpuid(0x80000000U, 0, abcd); - if (abcd[0] < 0x80000004U) { - return std::string(); - } - - for (int i = 0; i < 3; ++i) { - Cpuid(0x80000002U + i, 0, abcd); - memcpy(brand_string + i * 16, &abcd, sizeof(abcd)); - } - brand_string[48] = 0; - return brand_string; -} - -// Returns the frequency quoted inside the brand string. This does not -// account for throttling nor Turbo Boost. -double NominalClockRate() { - const std::string& brand_string = BrandString(); - // Brand strings include the maximum configured frequency. These prefixes are - // defined by Intel CPUID documentation. - const char* prefixes[3] = {"MHz", "GHz", "THz"}; - const double multipliers[3] = {1E6, 1E9, 1E12}; - for (size_t i = 0; i < 3; ++i) { - const size_t pos_prefix = brand_string.find(prefixes[i]); - if (pos_prefix != std::string::npos) { - const size_t pos_space = brand_string.rfind(' ', pos_prefix - 1); - if (pos_space != std::string::npos) { - const std::string digits = - brand_string.substr(pos_space + 1, pos_prefix - pos_space - 1); - return std::stod(digits) * multipliers[i]; - } - } - } - - return 0.0; -} - -#endif // ABSL_ARCH_X86_64 -} // namespace platform - -// Prevents the compiler from eliding the computations that led to "output". -template <class T> -inline void PreventElision(T&& output) { -#ifndef ABSL_OS_WIN - // Works by indicating to the compiler that "output" is being read and - // modified. The +r constraint avoids unnecessary writes to memory, but only - // works for built-in types (typically FuncOutput). - asm volatile("" : "+r"(output) : : "memory"); -#else - // MSVC does not support inline assembly anymore (and never supported GCC's - // RTL constraints). Self-assignment with #pragma optimize("off") might be - // expected to prevent elision, but it does not with MSVC 2015. Type-punning - // with volatile pointers generates inefficient code on MSVC 2017. - static std::atomic<T> dummy(T{}); - dummy.store(output, std::memory_order_relaxed); -#endif -} - -namespace timer { - -// Start/Stop return absolute timestamps and must be placed immediately before -// and after the region to measure. We provide separate Start/Stop functions -// because they use different fences. -// -// Background: RDTSC is not 'serializing'; earlier instructions may complete -// after it, and/or later instructions may complete before it. 'Fences' ensure -// regions' elapsed times are independent of such reordering. The only -// documented unprivileged serializing instruction is CPUID, which acts as a -// full fence (no reordering across it in either direction). Unfortunately -// the latency of CPUID varies wildly (perhaps made worse by not initializing -// its EAX input). Because it cannot reliably be deducted from the region's -// elapsed time, it must not be included in the region to measure (i.e. -// between the two RDTSC). -// -// The newer RDTSCP is sometimes described as serializing, but it actually -// only serves as a half-fence with release semantics. Although all -// instructions in the region will complete before the final timestamp is -// captured, subsequent instructions may leak into the region and increase the -// elapsed time. Inserting another fence after the final RDTSCP would prevent -// such reordering without affecting the measured region. -// -// Fortunately, such a fence exists. The LFENCE instruction is only documented -// to delay later loads until earlier loads are visible. However, Intel's -// reference manual says it acts as a full fence (waiting until all earlier -// instructions have completed, and delaying later instructions until it -// completes). AMD assigns the same behavior to MFENCE. -// -// We need a fence before the initial RDTSC to prevent earlier instructions -// from leaking into the region, and arguably another after RDTSC to avoid -// region instructions from completing before the timestamp is recorded. -// When surrounded by fences, the additional RDTSCP half-fence provides no -// benefit, so the initial timestamp can be recorded via RDTSC, which has -// lower overhead than RDTSCP because it does not read TSC_AUX. In summary, -// we define Start = LFENCE/RDTSC/LFENCE; Stop = RDTSCP/LFENCE. -// -// Using Start+Start leads to higher variance and overhead than Stop+Stop. -// However, Stop+Stop includes an LFENCE in the region measurements, which -// adds a delay dependent on earlier loads. The combination of Start+Stop -// is faster than Start+Start and more consistent than Stop+Stop because -// the first LFENCE already delayed subsequent loads before the measured -// region. This combination seems not to have been considered in prior work: -// http://akaros.cs.berkeley.edu/lxr/akaros/kern/arch/x86/rdtsc_test.c -// -// Note: performance counters can measure 'exact' instructions-retired or -// (unhalted) cycle counts. The RDPMC instruction is not serializing and also -// requires fences. Unfortunately, it is not accessible on all OSes and we -// prefer to avoid kernel-mode drivers. Performance counters are also affected -// by several under/over-count errata, so we use the TSC instead. - -// Returns a 64-bit timestamp in unit of 'ticks'; to convert to seconds, -// divide by InvariantTicksPerSecond. -inline uint64_t Start64() { - uint64_t t; -#if defined(ABSL_ARCH_PPC) - asm volatile("mfspr %0, %1" : "=r"(t) : "i"(268)); -#elif defined(ABSL_ARCH_X86_64) -#if defined(ABSL_OS_WIN) - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); - t = __rdtsc(); - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); -#else - asm volatile( - "lfence\n\t" - "rdtsc\n\t" - "shl $32, %%rdx\n\t" - "or %%rdx, %0\n\t" - "lfence" - : "=a"(t) - : - // "memory" avoids reordering. rdx = TSC >> 32. - // "cc" = flags modified by SHL. - : "rdx", "memory", "cc"); -#endif -#else - // Fall back to OS - unsure how to reliably query cntvct_el0 frequency. - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - t = ts.tv_sec * 1000000000LL + ts.tv_nsec; -#endif - return t; -} - -inline uint64_t Stop64() { - uint64_t t; -#if defined(ABSL_ARCH_X86_64) -#if defined(ABSL_OS_WIN) - _ReadWriteBarrier(); - unsigned aux; - t = __rdtscp(&aux); - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); -#else - // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx). - asm volatile( - "rdtscp\n\t" - "shl $32, %%rdx\n\t" - "or %%rdx, %0\n\t" - "lfence" - : "=a"(t) - : - // "memory" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32. - // "cc" = flags modified by SHL. - : "rcx", "rdx", "memory", "cc"); -#endif -#else - t = Start64(); -#endif - return t; -} - -// Returns a 32-bit timestamp with about 4 cycles less overhead than -// Start64. Only suitable for measuring very short regions because the -// timestamp overflows about once a second. -inline uint32_t Start32() { - uint32_t t; -#if defined(ABSL_ARCH_X86_64) -#if defined(ABSL_OS_WIN) - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); - t = static_cast<uint32_t>(__rdtsc()); - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); -#else - asm volatile( - "lfence\n\t" - "rdtsc\n\t" - "lfence" - : "=a"(t) - : - // "memory" avoids reordering. rdx = TSC >> 32. - : "rdx", "memory"); -#endif -#else - t = static_cast<uint32_t>(Start64()); -#endif - return t; -} - -inline uint32_t Stop32() { - uint32_t t; -#if defined(ABSL_ARCH_X86_64) -#if defined(ABSL_OS_WIN) - _ReadWriteBarrier(); - unsigned aux; - t = static_cast<uint32_t>(__rdtscp(&aux)); - _ReadWriteBarrier(); - _mm_lfence(); - _ReadWriteBarrier(); -#else - // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx). - asm volatile( - "rdtscp\n\t" - "lfence" - : "=a"(t) - : - // "memory" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32. - : "rcx", "rdx", "memory"); -#endif -#else - t = static_cast<uint32_t>(Stop64()); -#endif - return t; -} - -} // namespace timer - -namespace robust_statistics { - -// Sorts integral values in ascending order (e.g. for Mode). About 3x faster -// than std::sort for input distributions with very few unique values. -template <class T> -void CountingSort(T* values, size_t num_values) { - // Unique values and their frequency (similar to flat_map). - using Unique = std::pair<T, int>; - std::vector<Unique> unique; - for (size_t i = 0; i < num_values; ++i) { - const T value = values[i]; - const auto pos = - std::find_if(unique.begin(), unique.end(), - [value](const Unique u) { return u.first == value; }); - if (pos == unique.end()) { - unique.push_back(std::make_pair(value, 1)); - } else { - ++pos->second; - } - } - - // Sort in ascending order of value (pair.first). - std::sort(unique.begin(), unique.end()); - - // Write that many copies of each unique value to the array. - T* ABSL_RANDOM_INTERNAL_RESTRICT p = values; - for (const auto& value_count : unique) { - std::fill(p, p + value_count.second, value_count.first); - p += value_count.second; - } - ABSL_RAW_CHECK(p == values + num_values, "Did not produce enough output"); -} - -// @return i in [idx_begin, idx_begin + half_count) that minimizes -// sorted[i + half_count] - sorted[i]. -template <typename T> -size_t MinRange(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted, - const size_t idx_begin, const size_t half_count) { - T min_range = (std::numeric_limits<T>::max)(); - size_t min_idx = 0; - - for (size_t idx = idx_begin; idx < idx_begin + half_count; ++idx) { - ABSL_RAW_CHECK(sorted[idx] <= sorted[idx + half_count], "Not sorted"); - const T range = sorted[idx + half_count] - sorted[idx]; - if (range < min_range) { - min_range = range; - min_idx = idx; - } - } - - return min_idx; -} - -// Returns an estimate of the mode by calling MinRange on successively -// halved intervals. "sorted" must be in ascending order. This is the -// Half Sample Mode estimator proposed by Bickel in "On a fast, robust -// estimator of the mode", with complexity O(N log N). The mode is less -// affected by outliers in highly-skewed distributions than the median. -// The averaging operation below assumes "T" is an unsigned integer type. -template <typename T> -T ModeOfSorted(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted, - const size_t num_values) { - size_t idx_begin = 0; - size_t half_count = num_values / 2; - while (half_count > 1) { - idx_begin = MinRange(sorted, idx_begin, half_count); - half_count >>= 1; - } - - const T x = sorted[idx_begin + 0]; - if (half_count == 0) { - return x; - } - ABSL_RAW_CHECK(half_count == 1, "Should stop at half_count=1"); - const T average = (x + sorted[idx_begin + 1] + 1) / 2; - return average; -} - -// Returns the mode. Side effect: sorts "values". -template <typename T> -T Mode(T* values, const size_t num_values) { - CountingSort(values, num_values); - return ModeOfSorted(values, num_values); -} - -template <typename T, size_t N> -T Mode(T (&values)[N]) { - return Mode(&values[0], N); -} - -// Returns the median value. Side effect: sorts "values". -template <typename T> -T Median(T* values, const size_t num_values) { - ABSL_RAW_CHECK(num_values != 0, "Empty input"); - std::sort(values, values + num_values); - const size_t half = num_values / 2; - // Odd count: return middle - if (num_values % 2) { - return values[half]; - } - // Even count: return average of middle two. - return (values[half] + values[half - 1] + 1) / 2; -} - -// Returns a robust measure of variability. -template <typename T> -T MedianAbsoluteDeviation(const T* values, const size_t num_values, - const T median) { - ABSL_RAW_CHECK(num_values != 0, "Empty input"); - std::vector<T> abs_deviations; - abs_deviations.reserve(num_values); - for (size_t i = 0; i < num_values; ++i) { - const int64_t abs = std::abs(int64_t(values[i]) - int64_t(median)); - abs_deviations.push_back(static_cast<T>(abs)); - } - return Median(abs_deviations.data(), num_values); -} - -} // namespace robust_statistics - -// Ticks := platform-specific timer values (CPU cycles on x86). Must be -// unsigned to guarantee wraparound on overflow. 32 bit timers are faster to -// read than 64 bit. -using Ticks = uint32_t; - -// Returns timer overhead / minimum measurable difference. -Ticks TimerResolution() { - // Nested loop avoids exceeding stack/L1 capacity. - Ticks repetitions[Params::kTimerSamples]; - for (size_t rep = 0; rep < Params::kTimerSamples; ++rep) { - Ticks samples[Params::kTimerSamples]; - for (size_t i = 0; i < Params::kTimerSamples; ++i) { - const Ticks t0 = timer::Start32(); - const Ticks t1 = timer::Stop32(); - samples[i] = t1 - t0; - } - repetitions[rep] = robust_statistics::Mode(samples); - } - return robust_statistics::Mode(repetitions); -} - -static const Ticks timer_resolution = TimerResolution(); - -// Estimates the expected value of "lambda" values with a variable number of -// samples until the variability "rel_mad" is less than "max_rel_mad". -template <class Lambda> -Ticks SampleUntilStable(const double max_rel_mad, double* rel_mad, - const Params& p, const Lambda& lambda) { - auto measure_duration = [&lambda]() -> Ticks { - const Ticks t0 = timer::Start32(); - lambda(); - const Ticks t1 = timer::Stop32(); - return t1 - t0; - }; - - // Choose initial samples_per_eval based on a single estimated duration. - Ticks est = measure_duration(); - static const double ticks_per_second = InvariantTicksPerSecond(); - const size_t ticks_per_eval = ticks_per_second * p.seconds_per_eval; - size_t samples_per_eval = ticks_per_eval / est; - samples_per_eval = (std::max)(samples_per_eval, p.min_samples_per_eval); - - std::vector<Ticks> samples; - samples.reserve(1 + samples_per_eval); - samples.push_back(est); - - // Percentage is too strict for tiny differences, so also allow a small - // absolute "median absolute deviation". - const Ticks max_abs_mad = (timer_resolution + 99) / 100; - *rel_mad = 0.0; // ensure initialized - - for (size_t eval = 0; eval < p.max_evals; ++eval, samples_per_eval *= 2) { - samples.reserve(samples.size() + samples_per_eval); - for (size_t i = 0; i < samples_per_eval; ++i) { - const Ticks r = measure_duration(); - samples.push_back(r); - } - - if (samples.size() >= p.min_mode_samples) { - est = robust_statistics::Mode(samples.data(), samples.size()); - } else { - // For "few" (depends also on the variance) samples, Median is safer. - est = robust_statistics::Median(samples.data(), samples.size()); - } - ABSL_RAW_CHECK(est != 0, "Estimator returned zero duration"); - - // Median absolute deviation (mad) is a robust measure of 'variability'. - const Ticks abs_mad = robust_statistics::MedianAbsoluteDeviation( - samples.data(), samples.size(), est); - *rel_mad = static_cast<double>(static_cast<int>(abs_mad)) / est; - - if (*rel_mad <= max_rel_mad || abs_mad <= max_abs_mad) { - if (p.verbose) { - ABSL_RAW_LOG(INFO, - "%6zu samples => %5u (abs_mad=%4u, rel_mad=%4.2f%%)\n", - samples.size(), est, abs_mad, *rel_mad * 100.0); - } - return est; - } - } - - if (p.verbose) { - ABSL_RAW_LOG(WARNING, - "rel_mad=%4.2f%% still exceeds %4.2f%% after %6zu samples.\n", - *rel_mad * 100.0, max_rel_mad * 100.0, samples.size()); - } - return est; -} - -using InputVec = std::vector<FuncInput>; - -// Returns vector of unique input values. -InputVec UniqueInputs(const FuncInput* inputs, const size_t num_inputs) { - InputVec unique(inputs, inputs + num_inputs); - std::sort(unique.begin(), unique.end()); - unique.erase(std::unique(unique.begin(), unique.end()), unique.end()); - return unique; -} - -// Returns how often we need to call func for sufficient precision, or zero -// on failure (e.g. the elapsed time is too long for a 32-bit tick count). -size_t NumSkip(const Func func, const void* arg, const InputVec& unique, - const Params& p) { - // Min elapsed ticks for any input. - Ticks min_duration = ~0u; - - for (const FuncInput input : unique) { - // Make sure a 32-bit timer is sufficient. - const uint64_t t0 = timer::Start64(); - PreventElision(func(arg, input)); - const uint64_t t1 = timer::Stop64(); - const uint64_t elapsed = t1 - t0; - if (elapsed >= (1ULL << 30)) { - ABSL_RAW_LOG(WARNING, - "Measurement failed: need 64-bit timer for input=%zu\n", - static_cast<size_t>(input)); - return 0; - } - - double rel_mad; - const Ticks total = SampleUntilStable( - p.target_rel_mad, &rel_mad, p, - [func, arg, input]() { PreventElision(func(arg, input)); }); - min_duration = (std::min)(min_duration, total - timer_resolution); - } - - // Number of repetitions required to reach the target resolution. - const size_t max_skip = p.precision_divisor; - // Number of repetitions given the estimated duration. - const size_t num_skip = - min_duration == 0 ? 0 : (max_skip + min_duration - 1) / min_duration; - if (p.verbose) { - ABSL_RAW_LOG(INFO, "res=%u max_skip=%zu min_dur=%u num_skip=%zu\n", - timer_resolution, max_skip, min_duration, num_skip); - } - return num_skip; -} - -// Replicates inputs until we can omit "num_skip" occurrences of an input. -InputVec ReplicateInputs(const FuncInput* inputs, const size_t num_inputs, - const size_t num_unique, const size_t num_skip, - const Params& p) { - InputVec full; - if (num_unique == 1) { - full.assign(p.subset_ratio * num_skip, inputs[0]); - return full; - } - - full.reserve(p.subset_ratio * num_skip * num_inputs); - for (size_t i = 0; i < p.subset_ratio * num_skip; ++i) { - full.insert(full.end(), inputs, inputs + num_inputs); - } - absl::random_internal::randen_engine<uint32_t> rng; - std::shuffle(full.begin(), full.end(), rng); - return full; -} - -// Copies the "full" to "subset" in the same order, but with "num_skip" -// randomly selected occurrences of "input_to_skip" removed. -void FillSubset(const InputVec& full, const FuncInput input_to_skip, - const size_t num_skip, InputVec* subset) { - const size_t count = std::count(full.begin(), full.end(), input_to_skip); - // Generate num_skip random indices: which occurrence to skip. - std::vector<uint32_t> omit; - // Replacement for std::iota, not yet available in MSVC builds. - omit.reserve(count); - for (size_t i = 0; i < count; ++i) { - omit.push_back(i); - } - // omit[] is the same on every call, but that's OK because they identify the - // Nth instance of input_to_skip, so the position within full[] differs. - absl::random_internal::randen_engine<uint32_t> rng; - std::shuffle(omit.begin(), omit.end(), rng); - omit.resize(num_skip); - std::sort(omit.begin(), omit.end()); - - uint32_t occurrence = ~0u; // 0 after preincrement - size_t idx_omit = 0; // cursor within omit[] - size_t idx_subset = 0; // cursor within *subset - for (const FuncInput next : full) { - if (next == input_to_skip) { - ++occurrence; - // Haven't removed enough already - if (idx_omit < num_skip) { - // This one is up for removal - if (occurrence == omit[idx_omit]) { - ++idx_omit; - continue; - } - } - } - if (idx_subset < subset->size()) { - (*subset)[idx_subset++] = next; - } - } - ABSL_RAW_CHECK(idx_subset == subset->size(), "idx_subset not at end"); - ABSL_RAW_CHECK(idx_omit == omit.size(), "idx_omit not at end"); - ABSL_RAW_CHECK(occurrence == count - 1, "occurrence not at end"); -} - -// Returns total ticks elapsed for all inputs. -Ticks TotalDuration(const Func func, const void* arg, const InputVec* inputs, - const Params& p, double* max_rel_mad) { - double rel_mad; - const Ticks duration = - SampleUntilStable(p.target_rel_mad, &rel_mad, p, [func, arg, inputs]() { - for (const FuncInput input : *inputs) { - PreventElision(func(arg, input)); - } - }); - *max_rel_mad = (std::max)(*max_rel_mad, rel_mad); - return duration; -} - -// (Nearly) empty Func for measuring timer overhead/resolution. -ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE FuncOutput -EmptyFunc(const void* arg, const FuncInput input) { - return input; -} - -// Returns overhead of accessing inputs[] and calling a function; this will -// be deducted from future TotalDuration return values. -Ticks Overhead(const void* arg, const InputVec* inputs, const Params& p) { - double rel_mad; - // Zero tolerance because repeatability is crucial and EmptyFunc is fast. - return SampleUntilStable(0.0, &rel_mad, p, [arg, inputs]() { - for (const FuncInput input : *inputs) { - PreventElision(EmptyFunc(arg, input)); - } - }); -} - -} // namespace - -void PinThreadToCPU(int cpu) { - // We might migrate to another CPU before pinning below, but at least cpu - // will be one of the CPUs on which this thread ran. -#if defined(ABSL_OS_WIN) - if (cpu < 0) { - cpu = static_cast<int>(GetCurrentProcessorNumber()); - ABSL_RAW_CHECK(cpu >= 0, "PinThreadToCPU detect failed"); - if (cpu >= 64) { - // NOTE: On wine, at least, GetCurrentProcessorNumber() sometimes returns - // a value > 64, which is out of range. When this happens, log a message - // and don't set a cpu affinity. - ABSL_RAW_LOG(ERROR, "Invalid CPU number: %d", cpu); - return; - } - } else if (cpu >= 64) { - // User specified an explicit CPU affinity > the valid range. - ABSL_RAW_LOG(FATAL, "Invalid CPU number: %d", cpu); - } - const DWORD_PTR prev = SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu); - ABSL_RAW_CHECK(prev != 0, "SetAffinity failed"); -#elif defined(ABSL_OS_LINUX) && !defined(ABSL_OS_ANDROID) - if (cpu < 0) { - cpu = sched_getcpu(); - ABSL_RAW_CHECK(cpu >= 0, "PinThreadToCPU detect failed"); - } - const pid_t pid = 0; // current thread - cpu_set_t set; - CPU_ZERO(&set); - CPU_SET(cpu, &set); - const int err = sched_setaffinity(pid, sizeof(set), &set); - ABSL_RAW_CHECK(err == 0, "SetAffinity failed"); -#endif -} - -// Returns tick rate. Invariant means the tick counter frequency is independent -// of CPU throttling or sleep. May be expensive, caller should cache the result. -double InvariantTicksPerSecond() { -#if defined(ABSL_ARCH_PPC) - return __ppc_get_timebase_freq(); -#elif defined(ABSL_ARCH_X86_64) - // We assume the TSC is invariant; it is on all recent Intel/AMD CPUs. - return platform::NominalClockRate(); -#else - // Fall back to clock_gettime nanoseconds. - return 1E9; -#endif -} - -size_t MeasureImpl(const Func func, const void* arg, const size_t num_skip, - const InputVec& unique, const InputVec& full, - const Params& p, Result* results) { - const float mul = 1.0f / static_cast<int>(num_skip); - - InputVec subset(full.size() - num_skip); - const Ticks overhead = Overhead(arg, &full, p); - const Ticks overhead_skip = Overhead(arg, &subset, p); - if (overhead < overhead_skip) { - ABSL_RAW_LOG(WARNING, "Measurement failed: overhead %u < %u\n", overhead, - overhead_skip); - return 0; - } - - if (p.verbose) { - ABSL_RAW_LOG(INFO, "#inputs=%5zu,%5zu overhead=%5u,%5u\n", full.size(), - subset.size(), overhead, overhead_skip); - } - - double max_rel_mad = 0.0; - const Ticks total = TotalDuration(func, arg, &full, p, &max_rel_mad); - - for (size_t i = 0; i < unique.size(); ++i) { - FillSubset(full, unique[i], num_skip, &subset); - const Ticks total_skip = TotalDuration(func, arg, &subset, p, &max_rel_mad); - - if (total < total_skip) { - ABSL_RAW_LOG(WARNING, "Measurement failed: total %u < %u\n", total, - total_skip); - return 0; - } - - const Ticks duration = (total - overhead) - (total_skip - overhead_skip); - results[i].input = unique[i]; - results[i].ticks = duration * mul; - results[i].variability = max_rel_mad; - } - - return unique.size(); -} - -size_t Measure(const Func func, const void* arg, const FuncInput* inputs, - const size_t num_inputs, Result* results, const Params& p) { - ABSL_RAW_CHECK(num_inputs != 0, "No inputs"); - - const InputVec unique = UniqueInputs(inputs, num_inputs); - const size_t num_skip = NumSkip(func, arg, unique, p); // never 0 - if (num_skip == 0) return 0; // NumSkip already printed error message - - const InputVec full = - ReplicateInputs(inputs, num_inputs, unique.size(), num_skip, p); - - // MeasureImpl may fail up to p.max_measure_retries times. - for (size_t i = 0; i < p.max_measure_retries; i++) { - auto result = MeasureImpl(func, arg, num_skip, unique, full, p, results); - if (result != 0) { - return result; - } - } - // All retries failed. (Unusual) - return 0; -} - -} // namespace random_internal_nanobenchmark -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/nanobenchmark.h b/third_party/abseil_cpp/absl/random/internal/nanobenchmark.h deleted file mode 100644 index a5097ba27b0f..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/nanobenchmark.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_ -#define ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_ - -// Benchmarks functions of a single integer argument with realistic branch -// prediction hit rates. Uses a robust estimator to summarize the measurements. -// The precision is about 0.2%. -// -// Examples: see nanobenchmark_test.cc. -// -// Background: Microbenchmarks such as http://github.com/google/benchmark -// can measure elapsed times on the order of a microsecond. Shorter functions -// are typically measured by repeating them thousands of times and dividing -// the total elapsed time by this count. Unfortunately, repetition (especially -// with the same input parameter!) influences the runtime. In time-critical -// code, it is reasonable to expect warm instruction/data caches and TLBs, -// but a perfect record of which branches will be taken is unrealistic. -// Unless the application also repeatedly invokes the measured function with -// the same parameter, the benchmark is measuring something very different - -// a best-case result, almost as if the parameter were made a compile-time -// constant. This may lead to erroneous conclusions about branch-heavy -// algorithms outperforming branch-free alternatives. -// -// Our approach differs in three ways. Adding fences to the timer functions -// reduces variability due to instruction reordering, improving the timer -// resolution to about 40 CPU cycles. However, shorter functions must still -// be invoked repeatedly. For more realistic branch prediction performance, -// we vary the input parameter according to a user-specified distribution. -// Thus, instead of VaryInputs(Measure(Repeat(func))), we change the -// loop nesting to Measure(Repeat(VaryInputs(func))). We also estimate the -// central tendency of the measurement samples with the "half sample mode", -// which is more robust to outliers and skewed data than the mean or median. - -// NOTE: for compatibility with multiple translation units compiled with -// distinct flags, avoid #including headers that define functions. - -#include <stddef.h> -#include <stdint.h> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal_nanobenchmark { - -// Input influencing the function being measured (e.g. number of bytes to copy). -using FuncInput = size_t; - -// "Proof of work" returned by Func to ensure the compiler does not elide it. -using FuncOutput = uint64_t; - -// Function to measure: either 1) a captureless lambda or function with two -// arguments or 2) a lambda with capture, in which case the first argument -// is reserved for use by MeasureClosure. -using Func = FuncOutput (*)(const void*, FuncInput); - -// Internal parameters that determine precision/resolution/measuring time. -struct Params { - // For measuring timer overhead/resolution. Used in a nested loop => - // quadratic time, acceptable because we know timer overhead is "low". - // constexpr because this is used to define array bounds. - static constexpr size_t kTimerSamples = 256; - - // Best-case precision, expressed as a divisor of the timer resolution. - // Larger => more calls to Func and higher precision. - size_t precision_divisor = 1024; - - // Ratio between full and subset input distribution sizes. Cannot be less - // than 2; larger values increase measurement time but more faithfully - // model the given input distribution. - size_t subset_ratio = 2; - - // Together with the estimated Func duration, determines how many times to - // call Func before checking the sample variability. Larger values increase - // measurement time, memory/cache use and precision. - double seconds_per_eval = 4E-3; - - // The minimum number of samples before estimating the central tendency. - size_t min_samples_per_eval = 7; - - // The mode is better than median for estimating the central tendency of - // skewed/fat-tailed distributions, but it requires sufficient samples - // relative to the width of half-ranges. - size_t min_mode_samples = 64; - - // Maximum permissible variability (= median absolute deviation / center). - double target_rel_mad = 0.002; - - // Abort after this many evals without reaching target_rel_mad. This - // prevents infinite loops. - size_t max_evals = 9; - - // Retry the measure loop up to this many times. - size_t max_measure_retries = 2; - - // Whether to print additional statistics to stdout. - bool verbose = true; -}; - -// Measurement result for each unique input. -struct Result { - FuncInput input; - - // Robust estimate (mode or median) of duration. - float ticks; - - // Measure of variability (median absolute deviation relative to "ticks"). - float variability; -}; - -// Ensures the thread is running on the specified cpu, and no others. -// Reduces noise due to desynchronized socket RDTSC and context switches. -// If "cpu" is negative, pin to the currently running core. -void PinThreadToCPU(const int cpu = -1); - -// Returns tick rate, useful for converting measurements to seconds. Invariant -// means the tick counter frequency is independent of CPU throttling or sleep. -// This call may be expensive, callers should cache the result. -double InvariantTicksPerSecond(); - -// Precisely measures the number of ticks elapsed when calling "func" with the -// given inputs, shuffled to ensure realistic branch prediction hit rates. -// -// "func" returns a 'proof of work' to ensure its computations are not elided. -// "arg" is passed to Func, or reserved for internal use by MeasureClosure. -// "inputs" is an array of "num_inputs" (not necessarily unique) arguments to -// "func". The values should be chosen to maximize coverage of "func". This -// represents a distribution, so a value's frequency should reflect its -// probability in the real application. Order does not matter; for example, a -// uniform distribution over [0, 4) could be represented as {3,0,2,1}. -// Returns how many Result were written to "results": one per unique input, or -// zero if the measurement failed (an error message goes to stderr). -size_t Measure(const Func func, const void* arg, const FuncInput* inputs, - const size_t num_inputs, Result* results, - const Params& p = Params()); - -// Calls operator() of the given closure (lambda function). -template <class Closure> -static FuncOutput CallClosure(const void* f, const FuncInput input) { - return (*reinterpret_cast<const Closure*>(f))(input); -} - -// Same as Measure, except "closure" is typically a lambda function of -// FuncInput -> FuncOutput with a capture list. -template <class Closure> -static inline size_t MeasureClosure(const Closure& closure, - const FuncInput* inputs, - const size_t num_inputs, Result* results, - const Params& p = Params()) { - return Measure(reinterpret_cast<Func>(&CallClosure<Closure>), - reinterpret_cast<const void*>(&closure), inputs, num_inputs, - results, p); -} - -} // namespace random_internal_nanobenchmark -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/nanobenchmark_test.cc b/third_party/abseil_cpp/absl/random/internal/nanobenchmark_test.cc deleted file mode 100644 index f1571e269ff5..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/nanobenchmark_test.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/random/internal/nanobenchmark.h" - -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/numbers.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal_nanobenchmark { -namespace { - -uint64_t Div(const void*, FuncInput in) { - // Here we're measuring the throughput because benchmark invocations are - // independent. - const int64_t d1 = 0xFFFFFFFFFFll / int64_t(in); // IDIV - return d1; -} - -template <size_t N> -void MeasureDiv(const FuncInput (&inputs)[N]) { - Result results[N]; - Params params; - params.max_evals = 6; // avoid test timeout - const size_t num_results = Measure(&Div, nullptr, inputs, N, results, params); - if (num_results == 0) { - ABSL_RAW_LOG( - WARNING, - "WARNING: Measurement failed, should not happen when using " - "PinThreadToCPU unless the region to measure takes > 1 second.\n"); - return; - } - for (size_t i = 0; i < num_results; ++i) { - ABSL_RAW_LOG(INFO, "%5zu: %6.2f ticks; MAD=%4.2f%%\n", results[i].input, - results[i].ticks, results[i].variability * 100.0); - ABSL_RAW_CHECK(results[i].ticks != 0.0f, "Zero duration"); - } -} - -void RunAll(const int argc, char* argv[]) { - // Avoid migrating between cores - important on multi-socket systems. - int cpu = -1; - if (argc == 2) { - if (!absl::SimpleAtoi(argv[1], &cpu)) { - ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n"); - } - } - PinThreadToCPU(cpu); - - // unpredictable == 1 but the compiler doesn't know that. - const FuncInput unpredictable = argc != 999; - static const FuncInput inputs[] = {unpredictable * 10, unpredictable * 100}; - - MeasureDiv(inputs); -} - -} // namespace -} // namespace random_internal_nanobenchmark -ABSL_NAMESPACE_END -} // namespace absl - -int main(int argc, char* argv[]) { - absl::random_internal_nanobenchmark::RunAll(argc, argv); - return 0; -} diff --git a/third_party/abseil_cpp/absl/random/internal/nonsecure_base.h b/third_party/abseil_cpp/absl/random/internal/nonsecure_base.h deleted file mode 100644 index 730fa2ea12d2..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/nonsecure_base.h +++ /dev/null @@ -1,150 +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. - -#ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ -#define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ - -#include <algorithm> -#include <cstdint> -#include <iostream> -#include <iterator> -#include <random> -#include <string> -#include <type_traits> -#include <vector> - -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" -#include "absl/random/internal/pool_urbg.h" -#include "absl/random/internal/salted_seed_seq.h" -#include "absl/random/internal/seed_material.h" -#include "absl/types/optional.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced -// by a thread-unique URBG-instance. -template <typename URBG> -class NonsecureURBGBase { - public: - using result_type = typename URBG::result_type; - - // Default constructor - NonsecureURBGBase() : urbg_(ConstructURBG()) {} - - // Copy disallowed, move allowed. - NonsecureURBGBase(const NonsecureURBGBase&) = delete; - NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete; - NonsecureURBGBase(NonsecureURBGBase&&) = default; - NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default; - - // Constructor using a seed - template <class SSeq, typename = typename absl::enable_if_t< - !std::is_same<SSeq, NonsecureURBGBase>::value>> - explicit NonsecureURBGBase(SSeq&& seq) - : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {} - - // Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we - // enclose min() or max() in parens as (min)() and (max)(). - // Additionally, clang-format requires no space before this construction. - - // NonsecureURBGBase::min() - static constexpr result_type(min)() { return (URBG::min)(); } - - // NonsecureURBGBase::max() - static constexpr result_type(max)() { return (URBG::max)(); } - - // NonsecureURBGBase::operator()() - result_type operator()() { return urbg_(); } - - // NonsecureURBGBase::discard() - void discard(unsigned long long values) { // NOLINT(runtime/int) - urbg_.discard(values); - } - - bool operator==(const NonsecureURBGBase& other) const { - return urbg_ == other.urbg_; - } - - bool operator!=(const NonsecureURBGBase& other) const { - return !(urbg_ == other.urbg_); - } - - private: - // Seeder is a custom seed sequence type where generate() fills the provided - // buffer via the RandenPool entropy source. - struct Seeder { - using result_type = uint32_t; - - size_t size() { return 0; } - - template <typename OutIterator> - void param(OutIterator) const {} - - template <typename RandomAccessIterator> - void generate(RandomAccessIterator begin, RandomAccessIterator end) { - if (begin != end) { - // begin, end must be random access iterators assignable from uint32_t. - generate_impl( - std::integral_constant<bool, sizeof(*begin) == sizeof(uint32_t)>{}, - begin, end); - } - } - - // Commonly, generate is invoked with a pointer to a buffer which - // can be cast to a uint32_t. - template <typename RandomAccessIterator> - void generate_impl(std::integral_constant<bool, true>, - RandomAccessIterator begin, RandomAccessIterator end) { - auto buffer = absl::MakeSpan(begin, end); - auto target = absl::MakeSpan(reinterpret_cast<uint32_t*>(buffer.data()), - buffer.size()); - RandenPool<uint32_t>::Fill(target); - } - - // The non-uint32_t case should be uncommon, and involves an extra copy, - // filling the uint32_t buffer and then mixing into the output. - template <typename RandomAccessIterator> - void generate_impl(std::integral_constant<bool, false>, - RandomAccessIterator begin, RandomAccessIterator end) { - const size_t n = std::distance(begin, end); - absl::InlinedVector<uint32_t, 8> data(n, 0); - RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end())); - std::copy(std::begin(data), std::end(data), begin); - } - }; - - static URBG ConstructURBG() { - Seeder seeder; - return URBG(seeder); - } - - template <typename SSeq> - static URBG ConstructURBG(SSeq&& seq) { // NOLINT(runtime/references) - auto salted_seq = - random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq)); - return URBG(salted_seq); - } - - URBG urbg_; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/nonsecure_base_test.cc b/third_party/abseil_cpp/absl/random/internal/nonsecure_base_test.cc deleted file mode 100644 index 698027fc6e0d..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/nonsecure_base_test.cc +++ /dev/null @@ -1,245 +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/nonsecure_base.h" - -#include <algorithm> -#include <iostream> -#include <memory> -#include <random> -#include <sstream> - -#include "gtest/gtest.h" -#include "absl/random/distributions.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" - -namespace { - -using ExampleNonsecureURBG = - absl::random_internal::NonsecureURBGBase<std::mt19937>; - -template <typename T> -void Use(const T&) {} - -} // namespace - -TEST(NonsecureURBGBase, DefaultConstructorIsValid) { - ExampleNonsecureURBG urbg; -} - -// Ensure that the recommended template-instantiations are valid. -TEST(RecommendedTemplates, CanBeConstructed) { - absl::BitGen default_generator; - absl::InsecureBitGen insecure_generator; -} - -TEST(RecommendedTemplates, CanDiscardValues) { - absl::BitGen default_generator; - absl::InsecureBitGen insecure_generator; - - default_generator.discard(5); - insecure_generator.discard(5); -} - -TEST(NonsecureURBGBase, StandardInterface) { - // Names after definition of [rand.req.urbg] in C++ standard. - // e us a value of E - // v is a lvalue of E - // x, y are possibly const values of E - // s is a value of T - // q is a value satisfying requirements of seed_sequence - // z is a value of type unsigned long long - // os is a some specialization of basic_ostream - // is is a some specialization of basic_istream - - using E = absl::random_internal::NonsecureURBGBase<std::minstd_rand>; - - using T = typename E::result_type; - - static_assert(!std::is_copy_constructible<E>::value, - "NonsecureURBGBase should not be copy constructible"); - - static_assert(!absl::is_copy_assignable<E>::value, - "NonsecureURBGBase should not be copy assignable"); - - static_assert(std::is_move_constructible<E>::value, - "NonsecureURBGBase should be move constructible"); - - static_assert(absl::is_move_assignable<E>::value, - "NonsecureURBGBase should be move assignable"); - - static_assert(std::is_same<decltype(std::declval<E>()()), T>::value, - "return type of operator() must be result_type"); - - { - const E x, y; - Use(x); - Use(y); - - static_assert(std::is_same<decltype(x == y), bool>::value, - "return type of operator== must be bool"); - - static_assert(std::is_same<decltype(x != y), bool>::value, - "return type of operator== must be bool"); - } - - E e; - std::seed_seq q{1, 2, 3}; - - E{}; - E{q}; - - // Copy constructor not supported. - // E{x}; - - // result_type seed constructor not supported. - // E{T{1}}; - - // Move constructors are supported. - { - E tmp(q); - E m = std::move(tmp); - E n(std::move(m)); - EXPECT_TRUE(e != n); - } - - // Comparisons work. - { - // MSVC emits error 2718 when using EXPECT_EQ(e, x) - // * actual parameter with __declspec(align('#')) won't be aligned - E a(q); - E b(q); - - EXPECT_TRUE(a != e); - EXPECT_TRUE(a == b); - - a(); - EXPECT_TRUE(a != b); - } - - // e.seed(s) not supported. - - // [rand.req.eng] specifies the parameter as 'unsigned long long' - // e.discard(unsigned long long) is supported. - unsigned long long z = 1; // NOLINT(runtime/int) - e.discard(z); -} - -TEST(NonsecureURBGBase, SeedSeqConstructorIsValid) { - std::seed_seq seq; - ExampleNonsecureURBG rbg(seq); -} - -TEST(NonsecureURBGBase, CompatibleWithDistributionUtils) { - ExampleNonsecureURBG rbg; - - absl::Uniform(rbg, 0, 100); - absl::Uniform(rbg, 0.5, 0.7); - absl::Poisson<uint32_t>(rbg); - absl::Exponential<float>(rbg); -} - -TEST(NonsecureURBGBase, CompatibleWithStdDistributions) { - ExampleNonsecureURBG rbg; - - // Cast to void to suppress [[nodiscard]] warnings - static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg)); - static_cast<void>(std::uniform_real_distribution<float>()(rbg)); - static_cast<void>(std::bernoulli_distribution(0.2)(rbg)); -} - -TEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) { - const size_t kNumSamples = 128; - - ExampleNonsecureURBG rbg1; - ExampleNonsecureURBG rbg2; - - for (size_t i = 0; i < kNumSamples; i++) { - EXPECT_NE(rbg1(), rbg2()); - } -} - -TEST(NonsecureURBGBase, EqualSeedSequencesYieldEqualVariates) { - std::seed_seq seq; - - ExampleNonsecureURBG rbg1(seq); - ExampleNonsecureURBG rbg2(seq); - - // ExampleNonsecureURBG rbg3({1, 2, 3}); // Should not compile. - - for (uint32_t i = 0; i < 1000; i++) { - EXPECT_EQ(rbg1(), rbg2()); - } - - rbg1.discard(100); - rbg2.discard(100); - - // The sequences should continue after discarding - for (uint32_t i = 0; i < 1000; i++) { - EXPECT_EQ(rbg1(), rbg2()); - } -} - -// This is a PRNG-compatible type specifically designed to test -// that NonsecureURBGBase::Seeder can correctly handle iterators -// to arbitrary non-uint32_t size types. -template <typename T> -struct SeederTestEngine { - using result_type = T; - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - template <class SeedSequence, - typename = typename absl::enable_if_t< - !std::is_same<SeedSequence, SeederTestEngine>::value>> - explicit SeederTestEngine(SeedSequence&& seq) { - seed(seq); - } - - SeederTestEngine(const SeederTestEngine&) = default; - SeederTestEngine& operator=(const SeederTestEngine&) = default; - SeederTestEngine(SeederTestEngine&&) = default; - SeederTestEngine& operator=(SeederTestEngine&&) = default; - - result_type operator()() { return state[0]; } - - template <class SeedSequence> - void seed(SeedSequence&& seq) { - std::fill(std::begin(state), std::end(state), T(0)); - seq.generate(std::begin(state), std::end(state)); - } - - T state[2]; -}; - -TEST(NonsecureURBGBase, SeederWorksForU32) { - using U32 = - absl::random_internal::NonsecureURBGBase<SeederTestEngine<uint32_t>>; - U32 x; - EXPECT_NE(0, x()); -} - -TEST(NonsecureURBGBase, SeederWorksForU64) { - using U64 = - absl::random_internal::NonsecureURBGBase<SeederTestEngine<uint64_t>>; - - U64 x; - EXPECT_NE(0, x()); -} diff --git a/third_party/abseil_cpp/absl/random/internal/pcg_engine.h b/third_party/abseil_cpp/absl/random/internal/pcg_engine.h deleted file mode 100644 index 53c23fe1b492..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/pcg_engine.h +++ /dev/null @@ -1,307 +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. - -#ifndef ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ -#define ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ - -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" -#include "absl/numeric/int128.h" -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in -// C++. PCG combines a linear congruential generator (LCG) with output state -// mixing functions to generate each random variate. pcg_engine supports only a -// single sequence (oneseq), and does not support streams. -// -// pcg_engine is parameterized by two types: -// Params, which provides the multiplier and increment values; -// Mix, which mixes the state into the result. -// -template <typename Params, typename Mix> -class pcg_engine { - static_assert(std::is_same<typename Params::state_type, - typename Mix::state_type>::value, - "Class-template absl::pcg_engine must be parameterized by " - "Params and Mix with identical state_type"); - - static_assert(std::is_unsigned<typename Mix::result_type>::value, - "Class-template absl::pcg_engine must be parameterized by " - "an unsigned Mix::result_type"); - - using params_type = Params; - using mix_type = Mix; - using state_type = typename Mix::state_type; - - public: - // C++11 URBG interface: - using result_type = typename Mix::result_type; - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); } - - template <class SeedSequence, - typename = typename absl::enable_if_t< - !std::is_same<SeedSequence, pcg_engine>::value>> - explicit pcg_engine(SeedSequence&& seq) { - seed(seq); - } - - pcg_engine(const pcg_engine&) = default; - pcg_engine& operator=(const pcg_engine&) = default; - pcg_engine(pcg_engine&&) = default; - pcg_engine& operator=(pcg_engine&&) = default; - - result_type operator()() { - // Advance the LCG state, always using the new value to generate the output. - state_ = lcg(state_); - return Mix{}(state_); - } - - void seed(uint64_t seed_value = 0) { - state_type tmp = seed_value; - state_ = lcg(tmp + Params::increment()); - } - - template <class SeedSequence> - typename absl::enable_if_t< - !std::is_convertible<SeedSequence, uint64_t>::value, void> - seed(SeedSequence&& seq) { - reseed(seq); - } - - void discard(uint64_t count) { state_ = advance(state_, count); } - - bool operator==(const pcg_engine& other) const { - return state_ == other.state_; - } - - bool operator!=(const pcg_engine& other) const { return !(*this == other); } - - template <class CharT, class Traits> - friend typename absl::enable_if_t<(sizeof(state_type) == 16), - std::basic_ostream<CharT, Traits>&> - operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const pcg_engine& engine) { - auto saver = random_internal::make_ostream_state_saver(os); - random_internal::stream_u128_helper<state_type> helper; - helper.write(pcg_engine::params_type::multiplier(), os); - os << os.fill(); - helper.write(pcg_engine::params_type::increment(), os); - os << os.fill(); - helper.write(engine.state_, os); - return os; - } - - template <class CharT, class Traits> - friend typename absl::enable_if_t<(sizeof(state_type) <= 8), - std::basic_ostream<CharT, Traits>&> - operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const pcg_engine& engine) { - auto saver = random_internal::make_ostream_state_saver(os); - os << pcg_engine::params_type::multiplier() << os.fill(); - os << pcg_engine::params_type::increment() << os.fill(); - os << engine.state_; - return os; - } - - template <class CharT, class Traits> - friend typename absl::enable_if_t<(sizeof(state_type) == 16), - std::basic_istream<CharT, Traits>&> - operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - pcg_engine& engine) { // NOLINT(runtime/references) - random_internal::stream_u128_helper<state_type> helper; - auto mult = helper.read(is); - auto inc = helper.read(is); - auto tmp = helper.read(is); - if (mult != pcg_engine::params_type::multiplier() || - inc != pcg_engine::params_type::increment()) { - // signal failure by setting the failbit. - is.setstate(is.rdstate() | std::ios_base::failbit); - } - if (!is.fail()) { - engine.state_ = tmp; - } - return is; - } - - template <class CharT, class Traits> - friend typename absl::enable_if_t<(sizeof(state_type) <= 8), - std::basic_istream<CharT, Traits>&> - operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - pcg_engine& engine) { // NOLINT(runtime/references) - state_type mult{}, inc{}, tmp{}; - is >> mult >> inc >> tmp; - if (mult != pcg_engine::params_type::multiplier() || - inc != pcg_engine::params_type::increment()) { - // signal failure by setting the failbit. - is.setstate(is.rdstate() | std::ios_base::failbit); - } - if (!is.fail()) { - engine.state_ = tmp; - } - return is; - } - - private: - state_type state_; - - // Returns the linear-congruential generator next state. - static inline constexpr state_type lcg(state_type s) { - return s * Params::multiplier() + Params::increment(); - } - - // Returns the linear-congruential arbitrary seek state. - inline state_type advance(state_type s, uint64_t n) const { - state_type mult = Params::multiplier(); - state_type inc = Params::increment(); - state_type m = 1; - state_type i = 0; - while (n > 0) { - if (n & 1) { - m *= mult; - i = i * mult + inc; - } - inc = (mult + 1) * inc; - mult *= mult; - n >>= 1; - } - return m * s + i; - } - - template <class SeedSequence> - void reseed(SeedSequence& seq) { - using sequence_result_type = typename SeedSequence::result_type; - constexpr size_t kBufferSize = - sizeof(state_type) / sizeof(sequence_result_type); - sequence_result_type buffer[kBufferSize]; - seq.generate(std::begin(buffer), std::end(buffer)); - // Convert the seed output to a single state value. - state_type tmp = buffer[0]; - for (size_t i = 1; i < kBufferSize; i++) { - tmp <<= (sizeof(sequence_result_type) * 8); - tmp |= buffer[i]; - } - state_ = lcg(tmp + params_type::increment()); - } -}; - -// Parameterized implementation of the PCG 128-bit oneseq state. -// This provides state_type, multiplier, and increment for pcg_engine. -template <uint64_t kMultA, uint64_t kMultB, uint64_t kIncA, uint64_t kIncB> -class pcg128_params { - public: -#if ABSL_HAVE_INTRINSIC_INT128 - using state_type = __uint128_t; - static inline constexpr state_type make_u128(uint64_t a, uint64_t b) { - return (static_cast<__uint128_t>(a) << 64) | b; - } -#else - using state_type = absl::uint128; - static inline constexpr state_type make_u128(uint64_t a, uint64_t b) { - return absl::MakeUint128(a, b); - } -#endif - - static inline constexpr state_type multiplier() { - return make_u128(kMultA, kMultB); - } - static inline constexpr state_type increment() { - return make_u128(kIncA, kIncB); - } -}; - -// Implementation of the PCG xsl_rr_128_64 128-bit mixing function, which -// accepts an input of state_type and mixes it into an output of result_type. -struct pcg_xsl_rr_128_64 { -#if ABSL_HAVE_INTRINSIC_INT128 - using state_type = __uint128_t; -#else - using state_type = absl::uint128; -#endif - using result_type = uint64_t; - - inline uint64_t operator()(state_type state) { - // This is equivalent to the xsl_rr_128_64 mixing function. -#if ABSL_HAVE_INTRINSIC_INT128 - uint64_t rotate = static_cast<uint64_t>(state >> 122u); - state ^= state >> 64; - uint64_t s = static_cast<uint64_t>(state); -#else - uint64_t h = Uint128High64(state); - uint64_t rotate = h >> 58u; - uint64_t s = Uint128Low64(state) ^ h; -#endif - return random_internal::rotr(s, rotate); - } -}; - -// Parameterized implementation of the PCG 64-bit oneseq state. -// This provides state_type, multiplier, and increment for pcg_engine. -template <uint64_t kMult, uint64_t kInc> -class pcg64_params { - public: - using state_type = uint64_t; - static inline constexpr state_type multiplier() { return kMult; } - static inline constexpr state_type increment() { return kInc; } -}; - -// Implementation of the PCG xsh_rr_64_32 64-bit mixing function, which accepts -// an input of state_type and mixes it into an output of result_type. -struct pcg_xsh_rr_64_32 { - using state_type = uint64_t; - using result_type = uint32_t; - inline uint32_t operator()(uint64_t state) { - return random_internal::rotr( - static_cast<uint32_t>(((state >> 18) ^ state) >> 27), state >> 59); - } -}; - -// Stable pcg_engine implementations: -// This is a 64-bit generator using 128-bits of state. -// The output sequence is equivalent to Melissa O'Neil's pcg64_oneseq. -using pcg64_2018_engine = pcg_engine< - random_internal::pcg128_params<0x2360ed051fc65da4ull, 0x4385df649fccf645ull, - 0x5851f42d4c957f2d, 0x14057b7ef767814f>, - random_internal::pcg_xsl_rr_128_64>; - -// This is a 32-bit generator using 64-bits of state. -// This is equivalent to Melissa O'Neil's pcg32_oneseq. -using pcg32_2018_engine = pcg_engine< - random_internal::pcg64_params<0x5851f42d4c957f2dull, 0x14057b7ef767814full>, - random_internal::pcg_xsh_rr_64_32>; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/pcg_engine_test.cc b/third_party/abseil_cpp/absl/random/internal/pcg_engine_test.cc deleted file mode 100644 index 4d763e89eb58..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/pcg_engine_test.cc +++ /dev/null @@ -1,638 +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/random/internal/pcg_engine.h" - -#include <algorithm> -#include <bitset> -#include <random> -#include <sstream> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/random/internal/explicit_seed_seq.h" -#include "absl/time/clock.h" - -#define UPDATE_GOLDEN 0 - -namespace { - -using absl::random_internal::ExplicitSeedSeq; -using absl::random_internal::pcg32_2018_engine; -using absl::random_internal::pcg64_2018_engine; - -template <typename EngineType> -class PCGEngineTest : public ::testing::Test {}; - -using EngineTypes = ::testing::Types<pcg64_2018_engine, pcg32_2018_engine>; - -TYPED_TEST_SUITE(PCGEngineTest, EngineTypes); - -TYPED_TEST(PCGEngineTest, VerifyReseedChangesAllValues) { - using engine_type = TypeParam; - using result_type = typename engine_type::result_type; - - const size_t kNumOutputs = 16; - engine_type engine; - - // MSVC emits error 2719 without the use of std::ref below. - // * formal parameter with __declspec(align('#')) won't be aligned - - { - std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7}; - engine.seed(seq1); - } - result_type a[kNumOutputs]; - std::generate(std::begin(a), std::end(a), std::ref(engine)); - - { - std::random_device rd; - std::seed_seq seq2{rd(), rd(), rd()}; - engine.seed(seq2); - } - result_type b[kNumOutputs]; - std::generate(std::begin(b), std::end(b), std::ref(engine)); - - // Verify that two uncorrelated values have ~50% of there bits in common. Use - // a 10% margin-of-error to reduce flakiness. - size_t changed_bits = 0; - size_t unchanged_bits = 0; - size_t total_set = 0; - size_t total_bits = 0; - size_t equal_count = 0; - for (size_t i = 0; i < kNumOutputs; ++i) { - equal_count += (a[i] == b[i]) ? 1 : 0; - std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]); - changed_bits += bitset.count(); - unchanged_bits += bitset.size() - bitset.count(); - - std::bitset<sizeof(result_type) * 8> a_set(a[i]); - std::bitset<sizeof(result_type) * 8> b_set(b[i]); - total_set += a_set.count() + b_set.count(); - total_bits += 2 * 8 * sizeof(result_type); - } - // On average, half the bits are changed between two calls. - EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits)); - EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits)); - - // verify using a quick normal-approximation to the binomial. - EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits)) - << "@" << total_set / static_cast<double>(total_bits); - - // Also, A[i] == B[i] with probability (1/range) * N. - // Give this a pretty wide latitude, though. - const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8); - EXPECT_LE(equal_count, 1.0 + kExpected); -} - -// Number of values that needs to be consumed to clean two sizes of buffer -// and trigger third refresh. (slightly overestimates the actual state size). -constexpr size_t kTwoBufferValues = 16; - -TYPED_TEST(PCGEngineTest, VerifyDiscard) { - using engine_type = TypeParam; - - for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) { - engine_type engine_used; - for (size_t i = 0; i < num_used; ++i) { - engine_used(); - } - - for (size_t num_discard = 0; num_discard < kTwoBufferValues; - ++num_discard) { - engine_type engine1 = engine_used; - engine_type engine2 = engine_used; - for (size_t i = 0; i < num_discard; ++i) { - engine1(); - } - engine2.discard(num_discard); - for (size_t i = 0; i < kTwoBufferValues; ++i) { - const auto r1 = engine1(); - const auto r2 = engine2(); - ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard; - } - } - } -} - -TYPED_TEST(PCGEngineTest, StreamOperatorsResult) { - using engine_type = TypeParam; - - std::wostringstream os; - std::wistringstream is; - engine_type engine; - - EXPECT_EQ(&(os << engine), &os); - EXPECT_EQ(&(is >> engine), &is); -} - -TYPED_TEST(PCGEngineTest, StreamSerialization) { - using engine_type = TypeParam; - - for (size_t discard = 0; discard < kTwoBufferValues; ++discard) { - ExplicitSeedSeq seed_sequence{12, 34, 56}; - engine_type engine(seed_sequence); - engine.discard(discard); - - std::stringstream stream; - stream << engine; - - engine_type new_engine; - stream >> new_engine; - for (size_t i = 0; i < 64; ++i) { - EXPECT_EQ(engine(), new_engine()) << " " << i; - } - } -} - -constexpr size_t kNumGoldenOutputs = 127; - -// This test is checking if randen_engine is meets interface requirements -// defined in [rand.req.urbg]. -TYPED_TEST(PCGEngineTest, RandomNumberEngineInterface) { - using engine_type = TypeParam; - - using E = engine_type; - using T = typename E::result_type; - - static_assert(std::is_copy_constructible<E>::value, - "engine_type must be copy constructible"); - - static_assert(absl::is_copy_assignable<E>::value, - "engine_type must be copy assignable"); - - static_assert(std::is_move_constructible<E>::value, - "engine_type must be move constructible"); - - static_assert(absl::is_move_assignable<E>::value, - "engine_type must be move assignable"); - - static_assert(std::is_same<decltype(std::declval<E>()()), T>::value, - "return type of operator() must be result_type"); - - // Names after definition of [rand.req.urbg] in C++ standard. - // e us a value of E - // v is a lvalue of E - // x, y are possibly const values of E - // s is a value of T - // q is a value satisfying requirements of seed_sequence - // z is a value of type unsigned long long - // os is a some specialization of basic_ostream - // is is a some specialization of basic_istream - - E e, v; - const E x, y; - T s = 1; - std::seed_seq q{1, 2, 3}; - unsigned long long z = 1; // NOLINT(runtime/int) - std::wostringstream os; - std::wistringstream is; - - E{}; - E{x}; - E{s}; - E{q}; - - e.seed(); - - // MSVC emits error 2718 when using EXPECT_EQ(e, x) - // * actual parameter with __declspec(align('#')) won't be aligned - EXPECT_TRUE(e == x); - - e.seed(q); - { - E tmp(q); - EXPECT_TRUE(e == tmp); - } - - e(); - { - E tmp(q); - EXPECT_TRUE(e != tmp); - } - - e.discard(z); - - static_assert(std::is_same<decltype(x == y), bool>::value, - "return type of operator== must be bool"); - - static_assert(std::is_same<decltype(x != y), bool>::value, - "return type of operator== must be bool"); -} - -TYPED_TEST(PCGEngineTest, RandenEngineSFINAETest) { - using engine_type = TypeParam; - using result_type = typename engine_type::result_type; - - { - engine_type engine(result_type(1)); - engine.seed(result_type(1)); - } - - { - result_type n = 1; - engine_type engine(n); - engine.seed(n); - } - - { - engine_type engine(1); - engine.seed(1); - } - - { - int n = 1; - engine_type engine(n); - engine.seed(n); - } - - { - std::seed_seq seed_seq; - engine_type engine(seed_seq); - engine.seed(seed_seq); - } - - { - engine_type engine{std::seed_seq()}; - engine.seed(std::seed_seq()); - } -} - -// ------------------------------------------------------------------ -// Stability tests for pcg64_2018_engine -// ------------------------------------------------------------------ -TEST(PCG642018EngineTest, VerifyGolden) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0x01070196e695f8f1, 0x703ec840c59f4493, 0xe54954914b3a44fa, - 0x96130ff204b9285e, 0x7d9fdef535ceb21a, 0x666feed42e1219a0, - 0x981f685721c8326f, 0xad80710d6eab4dda, 0xe202c480b037a029, - 0x5d3390eaedd907e2, 0x0756befb39c6b8aa, 0x1fb44ba6634d62a3, - 0x8d20423662426642, 0x34ea910167a39fb4, 0x93010b43a80d0ab6, - 0x663db08a98fc568a, 0x720b0a1335956fae, 0x2c35483e31e1d3ba, - 0x429f39776337409d, 0xb46d99e638687344, 0x105370b96aedcaee, - 0x3999e92f811cff71, 0xd230f8bcb591cfc9, 0x0dce3db2ba7bdea5, - 0xcf2f52c91eec99af, 0x2bc7c24a8b998a39, 0xbd8af1b0d599a19c, - 0x56bc45abc66059f5, 0x170a46dc170f7f1e, 0xc25daf5277b85fad, - 0xe629c2e0c948eadb, 0x1720a796915542ed, 0x22fb0caa4f909951, - 0x7e0c0f4175acd83d, 0xd9fcab37ff2a860c, 0xab2280fb2054bad1, - 0x58e8a06f37fa9e99, 0xc3a52a30b06528c7, 0x0175f773a13fc1bd, - 0x731cfc584b00e840, 0x404cc7b2648069cb, 0x5bc29153b0b7f783, - 0x771310a38cc999d1, 0x766a572f0a71a916, 0x90f450fb4fc48348, - 0xf080ea3e1c7b1a0d, 0x15471a4507d66a44, 0x7d58e55a78f3df69, - 0x0130a094576ac99c, 0x46669cb2d04b1d87, 0x17ab5bed20191840, - 0x95b177d260adff3e, 0x025fb624b6ee4c07, 0xb35de4330154a95f, - 0xe8510fff67e24c79, 0x132c3cbcd76ed2d3, 0x35e7cc145a093904, - 0x9f5b5b5f81583b79, 0x3ee749a533966233, 0x4af85886cdeda8cd, - 0x0ca5380ecb3ef3aa, 0x4f674eb7661d3192, 0x88a29aad00cd7733, - 0x70b627ca045ffac6, 0x5912b43ea887623d, 0x95dc9fc6f62cf221, - 0x926081a12a5c905b, 0x9c57d4cd7dfce651, 0x85ab2cbf23e3bb5d, - 0xc5cd669f63023152, 0x3067be0fad5d898e, 0x12b56f444cb53d05, - 0xbc2e5a640c3434fc, 0x9280bff0e4613fe1, 0x98819094c528743e, - 0x999d1c98d829df33, 0x9ff82a012dc89242, 0xf99183ed39c8be94, - 0xf0f59161cd421c55, 0x3c705730c2f6c48d, 0x66ad85c6e9278a61, - 0x2a3428e4a428d5d0, 0x79207d68fd04940d, 0xea7f2b402edc8430, - 0xa06b419ac857f63b, 0xcb1dd0e6fbc47e1c, 0x4f55229200ada6a4, - 0x9647b5e6359c927f, 0x30bf8f9197c7efe5, 0xa79519529cc384d0, - 0xbb22c4f339ad6497, 0xd7b9782f59d14175, 0x0dff12fff2ec0118, - 0xa331ad8305343a7c, 0x48dad7e3f17e0862, 0x324c6fb3fd3c9665, - 0xf0e4350e7933dfc4, 0x7ccda2f30b8b03b6, 0xa0afc6179005de40, - 0xee65da6d063b3a30, 0xb9506f42f2bfe87a, 0xc9a2e26b0ef5baa0, - 0x39fa9d4f495011d6, 0xbecc21a45d023948, 0x6bf484c6593f737f, - 0x8065e0070cadc3b7, 0x9ef617ed8d419799, 0xac692cf8c233dd15, - 0xd2ed87583c4ebb98, 0xad95ba1bebfedc62, 0x9b60b160a8264e43, - 0x0bc8c45f71fcf25b, 0x4a78035cdf1c9931, 0x4602dc106667e029, - 0xb335a3c250498ac8, 0x0256ebc4df20cab8, 0x0c61efd153f0c8d9, - 0xe5d0150a4f806f88, 0x99d6521d351e7d87, 0x8d4888c9f80f4325, - 0x106c5735c1ba868d, 0x73414881b880a878, 0x808a9a58a3064751, - 0x339a29f3746de3d5, 0x5410d7fa4f873896, 0xd84623c81d7b8a03, - 0x1f7c7e7a7f47f462, - }; - - pcg64_2018_engine engine(0); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(PCG642018EngineTest, VerifyGoldenSeeded) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0xb03988f1e39691ee, 0xbd2a1eb5ac31e97a, 0x8f00d6d433634d02, - 0x1823c28d483d5776, 0x000c3ee3e1aeb74a, 0xfa82ef27a4f3df9c, - 0xc6f382308654e454, 0x414afb1a238996c2, 0x4703a4bc252eb411, - 0x99d64f62c8f7f654, 0xbb07ebe11a34fa44, 0x79eb06a363c06131, - 0xf66ad3756f1c6b21, 0x130c01d5e869f457, 0x5ca2b9963aecbc81, - 0xfef7bebc1de27e6c, 0x1d174faa5ed2cdbf, 0xd75b7a773f2bb889, - 0xc35c872327a170a5, 0x46da6d88646a42fe, 0x4622985e0442dae2, - 0xbe3cbd67297f1f9b, 0xe7c37b4a4798bfd1, 0x173d5dfad15a25c3, - 0x0eb6849ba2961522, 0xb0ff7246e6700d73, 0x88cb9c42d3afa577, - 0xb609731dbd94d917, 0xd3941cda04b40081, 0x28d140f7409bea3a, - 0x3c96699a920a124a, 0xdb28be521958b2fd, 0x0a3f44db3d4c5124, - 0x7ac8e60ba13b70d2, 0x75f03a41ded5195a, 0xaed10ac7c4e4825d, - 0xb92a3b18aadb7adc, 0xda45e0081f2bca46, 0x74d39ab3753143fc, - 0xb686038018fac9ca, 0x4cc309fe99542dbb, 0xf3e1a4fcb311097c, - 0x58763d6fa698d69d, 0xd11c365dbecd8d60, 0x2c15d55725b1dee7, - 0x89805f254d85658c, 0x2374c44dfc62158b, 0x9a8350fa7995328d, - 0x198f838970cf91da, 0x96aff569562c0e53, 0xd76c8c52b7ec6e3f, - 0x23a01cd9ae4baa81, 0x3adb366b6d02a893, 0xb3313e2a4c5b333f, - 0x04c11230b96a5425, 0x1f7f7af04787d571, 0xaddb019365275ec7, - 0x5c960468ccb09f42, 0x8438db698c69a44a, 0x492be1e46111637e, - 0x9c6c01e18100c610, 0xbfe48e75b7d0aceb, 0xb5e0b89ec1ce6a00, - 0x9d280ecbc2fe8997, 0x290d9e991ba5fcab, 0xeec5bec7d9d2a4f0, - 0x726e81488f19150e, 0x1a6df7955a7e462c, 0x37a12d174ba46bb5, - 0x3cdcdffd96b1b5c5, 0x2c5d5ac10661a26e, 0xa742ed18f22e50c4, - 0x00e0ed88ff0d8a35, 0x3d3c1718cb1efc0b, 0x1d70c51ffbccbf11, - 0xfbbb895132a4092f, 0x619d27f2fb095f24, 0x69af68200985e5c4, - 0xbee4885f57373f8d, 0x10b7a6bfe0587e40, 0xa885e6cf2f7e5f0a, - 0x59f879464f767550, 0x24e805d69056990d, 0x860970b911095891, - 0xca3189954f84170d, 0x6652a5edd4590134, 0x5e1008cef76174bf, - 0xcbd417881f2bcfe5, 0xfd49fc9d706ecd17, 0xeebf540221ebd066, - 0x46af7679464504cb, 0xd4028486946956f1, 0xd4f41864b86c2103, - 0x7af090e751583372, 0x98cdaa09278cb642, 0xffd42b921215602f, - 0x1d05bec8466b1740, 0xf036fa78a0132044, 0x787880589d1ecc78, - 0x5644552cfef33230, 0x0a97e275fe06884b, 0x96d1b13333d470b5, - 0xc8b3cdad52d3b034, 0x091357b9db7376fd, 0xa5fe4232555edf8c, - 0x3371bc3b6ada76b5, 0x7deeb2300477c995, 0x6fc6d4244f2849c1, - 0x750e8cc797ca340a, 0x81728613cd79899f, 0x3467f4ee6f9aeb93, - 0x5ef0a905f58c640f, 0x432db85e5101c98a, 0x6488e96f46ac80c2, - 0x22fddb282625048c, 0x15b287a0bc2d4c5d, 0xa7e2343ef1f28bce, - 0xc87ee1aa89bed09e, 0x220610107812c5e9, 0xcbdab6fcd640f586, - 0x8d41047970928784, 0x1aa431509ec1ade0, 0xac3f0be53f518ddc, - 0x16f4428ad81d0cbb, 0x675b13c2736fc4bb, 0x6db073afdd87e32d, - 0x572f3ca2f1a078c6, - }; - - ExplicitSeedSeq seed_sequence{12, 34, 56}; - pcg64_2018_engine engine(seed_sequence); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(seed_sequence); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(PCG642018EngineTest, VerifyGoldenFromDeserializedEngine) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0xdd425b47b4113dea, 0x1b07176479d444b0, 0x6b391027586f2e42, - 0xa166f2b15f4a2143, 0xffb6dbd7a179ee97, 0xb2c00035365bf0b1, - 0x8fbb518b45855521, 0xfc789a55ddf87c3b, 0x429531f0f17ff355, - 0xbe708560d603d283, 0x5bff415175c5cb6b, 0xe813491f4ad45394, - 0xa853f4506d55880d, 0x7e538453e568172e, 0xe101f1e098ddd0ec, - 0x6ee31266ee4c766d, 0xa8786d92d66b39d7, 0xfee622a2acf5e5b0, - 0x5fe8e82c102fa7b3, 0x01f10be4cdb53c9d, 0xbe0545366f857022, - 0x12e74f010a339bca, 0xb10d85ca40d5ce34, 0xe80d6feba5054875, - 0x2b7c1ee6d567d4ee, 0x2a9cd043bfd03b66, 0x5cfc531bd239f3f1, - 0x1c4734e4647d70f5, 0x85a8f60f006b5760, 0x6a4239ce76dca387, - 0x8da0f86d7339335c, 0xf055b0468551374d, 0x486e8567e9bea9a0, - 0x4cb531b8405192dd, 0xf813b1ee3157110b, 0x214c2a664a875d8e, - 0x74531237b29b35f7, 0xa6f0267bb77a771e, 0x64b552bff54184a4, - 0xa2d6f7af2d75b6fc, 0x460a10018e03b5ab, 0x76fd1fdcb81d0800, - 0x76f5f81805070d9d, 0x1fb75cb1a70b289a, 0x9dfd25a022c4b27f, - 0x9a31a14a80528e9e, 0x910dc565ddc25820, 0xd6aef8e2b0936c10, - 0xe1773c507fe70225, 0xe027fd7aadd632bc, 0xc1fecb427089c8b8, - 0xb5c74c69fa9dbf26, 0x71bf9b0e4670227d, 0x25f48fad205dcfdd, - 0x905248ec4d689c56, 0x5c2b7631b0de5c9d, 0x9f2ee0f8f485036c, - 0xfd6ce4ebb90bf7ea, 0xd435d20046085574, 0x6b7eadcb0625f986, - 0x679d7d44b48be89e, 0x49683b8e1cdc49de, 0x4366cf76e9a2f4ca, - 0x54026ec1cdad7bed, 0xa9a04385207f28d3, 0xc8e66de4eba074b2, - 0x40b08c42de0f4cc0, 0x1d4c5e0e93c5bbc0, 0x19b80792e470ae2d, - 0x6fcaaeaa4c2a5bd9, 0xa92cb07c4238438e, 0x8bb5c918a007e298, - 0x7cd671e944874cf4, 0x88166470b1ba3cac, 0xd013d476eaeeade6, - 0xcee416947189b3c3, 0x5d7c16ab0dce6088, 0xd3578a5c32b13d27, - 0x3875db5adc9cc973, 0xfbdaba01c5b5dc56, 0xffc4fdd391b231c3, - 0x2334520ecb164fec, 0x361c115e7b6de1fa, 0xeee58106cc3563d7, - 0x8b7f35a8db25ebb8, 0xb29d00211e2cafa6, 0x22a39fe4614b646b, - 0x92ca6de8b998506d, 0x40922fe3d388d1db, 0x9da47f1e540f802a, - 0x811dceebf16a25db, 0xf6524ae22e0e53a9, 0x52d9e780a16eb99d, - 0x4f504286bb830207, 0xf6654d4786bd5cc3, 0x00bd98316003a7e1, - 0xefda054a6ab8f5f3, 0x46cfb0f4c1872827, 0xc22b316965c0f3b2, - 0xd1a28087c7e7562a, 0xaa4f6a094b7f5cff, 0xfe2bc853a041f7da, - 0xe9d531402a83c3ba, 0xe545d8663d3ce4dd, 0xfa2dcd7d91a13fa8, - 0xda1a080e52a127b8, 0x19c98f1f809c3d84, 0x2cef109af4678c88, - 0x53462accab3b9132, 0x176b13a80415394e, 0xea70047ef6bc178b, - 0x57bca80506d6dcdf, 0xd853ba09ff09f5c4, 0x75f4df3a7ddd4775, - 0x209c367ade62f4fe, 0xa9a0bbc74d5f4682, 0x5dfe34bada86c21a, - 0xc2c05bbcd38566d1, 0x6de8088e348c916a, 0x6a7001c6000c2196, - 0xd9fb51865fc4a367, 0x12f320e444ece8ff, 0x6d56f7f793d65035, - 0x138f31b7a865f8aa, 0x58fc68b4026b9adf, 0xcd48954b79fb6436, - 0x27dfce4a0232af87, - }; - -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - std::seed_seq seed_sequence{1, 2, 3}; - pcg64_2018_engine engine(seed_sequence); - std::ostringstream stream; - stream << engine; - auto str = stream.str(); - printf("%s\n\n", str.c_str()); - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - pcg64_2018_engine engine; - std::istringstream stream( - "2549297995355413924 4865540595714422341 6364136223846793005 " - "1442695040888963407 18088519957565336995 4845369368158826708"); - stream >> engine; - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -// ------------------------------------------------------------------ -// Stability tests for pcg32_2018_engine -// ------------------------------------------------------------------ -TEST(PCG322018EngineTest, VerifyGolden) { - constexpr uint32_t kGolden[kNumGoldenOutputs] = { - 0x7a7ecbd9, 0x89fd6c06, 0xae646aa8, 0xcd3cf945, 0x6204b303, 0x198c8585, - 0x49fce611, 0xd1e9297a, 0x142d9440, 0xee75f56b, 0x473a9117, 0xe3a45903, - 0xbce807a1, 0xe54e5f4d, 0x497d6c51, 0x61829166, 0xa740474b, 0x031912a8, - 0x9de3defa, 0xd266dbf1, 0x0f38bebb, 0xec3c4f65, 0x07c5057d, 0xbbce03c8, - 0xfd2ac7a8, 0xffcf4773, 0x5b10affb, 0xede1c842, 0xe22b01b7, 0xda133c8c, - 0xaf89b0f4, 0x25d1b8bc, 0x9f625482, 0x7bfd6882, 0x2e2210c0, 0x2c8fb9a6, - 0x42cb3b83, 0x40ce0dab, 0x644a3510, 0x36230ef2, 0xe2cb6d43, 0x1012b343, - 0x746c6c9f, 0x36714cf8, 0xed1f5026, 0x8bbbf83e, 0xe98710f4, 0x8a2afa36, - 0x09035349, 0x6dc1a487, 0x682b634b, 0xc106794f, 0x7dd78beb, 0x628c262b, - 0x852fb232, 0xb153ac4c, 0x4f169d1b, 0xa69ab774, 0x4bd4b6f2, 0xdc351dd3, - 0x93ff3c8c, 0xa30819ab, 0xff07758c, 0x5ab13c62, 0xd16d7fb5, 0xc4950ffa, - 0xd309ae49, 0xb9677a87, 0x4464e317, 0x90dc44f1, 0xc694c1d4, 0x1d5e1168, - 0xadf37a2d, 0xda38990d, 0x1ec4bd33, 0x36ca25ce, 0xfa0dc76a, 0x968a9d43, - 0x6950ac39, 0xdd3276bc, 0x06d5a71e, 0x1f6f282d, 0x5c626c62, 0xdde3fc31, - 0x152194ce, 0xc35ed14c, 0xb1f7224e, 0x47f76bb8, 0xb34fdd08, 0x7011395e, - 0x162d2a49, 0x0d1bf09f, 0x9428a952, 0x03c5c344, 0xd3525616, 0x7816fff3, - 0x6bceb8a8, 0x8345a081, 0x366420fd, 0x182abeda, 0x70f82745, 0xaf15ded8, - 0xc7f52ca2, 0xa98db9c5, 0x919d99ba, 0x9c376c1c, 0xed8d34c2, 0x716ae9f5, - 0xef062fa5, 0xee3b6c56, 0x52325658, 0x61afa9c3, 0xfdaf02f0, 0x961cf3ab, - 0x9f291565, 0x4fbf3045, 0x0590c899, 0xde901385, 0x45005ffb, 0x509db162, - 0x262fa941, 0x4c421653, 0x4b17c21e, 0xea0d1530, 0xde803845, 0x61bfd515, - 0x438523ef, - }; - - pcg32_2018_engine engine(0); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%08x, ", engine()); - if (i % 6 == 5) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(PCG322018EngineTest, VerifyGoldenSeeded) { - constexpr uint32_t kGolden[kNumGoldenOutputs] = { - 0x60b5a64c, 0x978502f9, 0x80a75f60, 0x241f1158, 0xa4cd1dbb, 0xe7284017, - 0x3b678da5, 0x5223ec99, 0xe4bdd5d9, 0x72190e6d, 0xe6e702c9, 0xff80c768, - 0xcf126ed3, 0x1fbd20ab, 0x60980489, 0xbc72bf89, 0x407ac6c0, 0x00bf3c51, - 0xf9087897, 0x172e4eb6, 0xe9e4f443, 0x1a6098bf, 0xbf44f8c2, 0xdd84a0e5, - 0xd9a52364, 0xc0e2e786, 0x061ae2ba, 0x9facb8e3, 0x6109432d, 0xd4e0a013, - 0xbd8eb9a6, 0x7e86c3b6, 0x629c0e68, 0x05337430, 0xb495b9f4, 0x11ccd65d, - 0xb578db25, 0x66f1246d, 0x6ef20a7f, 0x5e429812, 0x11772130, 0xb944b5c2, - 0x01624128, 0xa2385ab7, 0xd3e10d35, 0xbe570ec3, 0xc951656f, 0xbe8944a0, - 0x7be41062, 0x5709f919, 0xd745feda, 0x9870b9ae, 0xb44b8168, 0x19e7683b, - 0xded8017f, 0xc6e4d544, 0x91ae4225, 0xd6745fba, 0xb992f284, 0x65b12b33, - 0xa9d5fdb4, 0xf105ce1a, 0x35ca1a6e, 0x2ff70dd0, 0xd8335e49, 0xfb71ddf2, - 0xcaeabb89, 0x5c6f5f84, 0x9a811a7d, 0xbcecbbd1, 0x0f661ba0, 0x9ad93b9d, - 0xedd23e0b, 0x42062f48, 0xd38dd7e4, 0x6cd63c9c, 0x640b98ae, 0x4bff5653, - 0x12626371, 0x13266017, 0xe7a698d8, 0x39c74667, 0xe8fdf2e3, 0x52803bf8, - 0x2af6895b, 0x91335b7b, 0x699e4961, 0x00a40fff, 0x253ff2b6, 0x4a6cf672, - 0x9584e85f, 0xf2a5000c, 0x4d58aba8, 0xb8513e6a, 0x767fad65, 0x8e326f9e, - 0x182f15a1, 0x163dab52, 0xdf99c780, 0x047282a1, 0xee4f90dd, 0xd50394ae, - 0x6c9fd5f0, 0xb06a9194, 0x387e3840, 0x04a9487b, 0xf678a4c2, 0xd0a78810, - 0xd502c97e, 0xd6a9b12a, 0x4accc5dc, 0x416ed53e, 0x50411536, 0xeeb89c24, - 0x813a7902, 0x034ebca6, 0xffa52e7c, 0x7ecd3d0e, 0xfa37a0d2, 0xb1fbe2c1, - 0xb7efc6d1, 0xefa4ccee, 0xf6f80424, 0x2283f3d9, 0x68732284, 0x94f3b5c8, - 0xbbdeceb9, - }; - - ExplicitSeedSeq seed_sequence{12, 34, 56}; - pcg32_2018_engine engine(seed_sequence); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%08x, ", engine()); - if (i % 6 == 5) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(seed_sequence); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(PCG322018EngineTest, VerifyGoldenFromDeserializedEngine) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0x780f7042, 0xba137215, 0x43ab6f22, 0x0cb55f46, 0x44b2627d, 0x835597af, - 0xea973ea1, 0x0d2abd35, 0x4fdd601c, 0xac4342fe, 0x7db7e93c, 0xe56ebcaf, - 0x3596470a, 0x7770a9ad, 0x9b893320, 0x57db3415, 0xb432de54, 0xa02baf71, - 0xa256aadb, 0x88921fc7, 0xa35fa6b3, 0xde3eca46, 0x605739a7, 0xa890b82b, - 0xe457b7ad, 0x335fb903, 0xeb06790c, 0xb3c54bf6, 0x6141e442, 0xa599a482, - 0xb78987cc, 0xc61dfe9d, 0x0f1d6ace, 0x17460594, 0x8f6a5061, 0x083dc354, - 0xe9c337fb, 0xcfd105f7, 0x926764b6, 0x638d24dc, 0xeaac650a, 0x67d2cb9c, - 0xd807733c, 0x205fc52e, 0xf5399e2e, 0x6c46ddcc, 0xb603e875, 0xce113a25, - 0x3c8d4813, 0xfb584db8, 0xf6d255ff, 0xea80954f, 0x42e8be85, 0xb2feee72, - 0x62bd8d16, 0x1be4a142, 0x97dca1a4, 0xdd6e7333, 0xb2caa20e, 0xa12b1588, - 0xeb3a5a1a, 0x6fa5ba89, 0x077ea931, 0x8ddb1713, 0x0dd03079, 0x2c2ba965, - 0xa77fac17, 0xc8325742, 0x8bb893bf, 0xc2315741, 0xeaceee92, 0x81dd2ee2, - 0xe5214216, 0x1b9b8fb2, 0x01646d03, 0x24facc25, 0xd8c0e0bb, 0xa33fe106, - 0xf34fe976, 0xb3b4b44e, 0x65618fed, 0x032c6192, 0xa9dd72ce, 0xf391887b, - 0xf41c6a6e, 0x05c4bd6d, 0x37fa260e, 0x46b05659, 0xb5f6348a, 0x62d26d89, - 0x39f6452d, 0xb17b30a2, 0xbdd82743, 0x38ecae3b, 0xfe90f0a2, 0xcb2d226d, - 0xcf8a0b1c, 0x0eed3d4d, 0xa1f69cfc, 0xd7ac3ba5, 0xce9d9a6b, 0x121deb4c, - 0x4a0d03f3, 0xc1821ed1, 0x59c249ac, 0xc0abb474, 0x28149985, 0xfd9a82ba, - 0x5960c3b2, 0xeff00cba, 0x6073aa17, 0x25dc0919, 0x9976626e, 0xdd2ccc33, - 0x39ecb6ec, 0xc6e15d13, 0xfac94cfd, 0x28cfd34f, 0xf2d2c32d, 0x51c23d08, - 0x4fdb2f48, 0x97baa807, 0xf2c1004c, 0xc4ae8136, 0x71f31c94, 0x8c92d601, - 0x36caf5cd, - }; - -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - std::seed_seq seed_sequence{1, 2, 3}; - pcg32_2018_engine engine(seed_sequence); - std::ostringstream stream; - stream << engine; - auto str = stream.str(); - printf("%s\n\n", str.c_str()); - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%08x, ", engine()); - if (i % 6 == 5) { - printf("\n"); - } - } - printf("\n\n\n"); - - EXPECT_FALSE(true); -#else - pcg32_2018_engine engine; - std::istringstream stream( - "6364136223846793005 1442695040888963407 6537028157270659894"); - stream >> engine; - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/platform.h b/third_party/abseil_cpp/absl/random/internal/platform.h deleted file mode 100644 index bbdb4e620816..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/platform.h +++ /dev/null @@ -1,171 +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. - -#ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_ -#define ABSL_RANDOM_INTERNAL_PLATFORM_H_ - -// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate -// symbols from arbitrary system and other headers, since it may be built -// with different flags from other targets, using different levels of -// optimization, potentially introducing ODR violations. - -// ----------------------------------------------------------------------------- -// Platform Feature Checks -// ----------------------------------------------------------------------------- - -// Currently supported operating systems and associated preprocessor -// symbols: -// -// Linux and Linux-derived __linux__ -// Android __ANDROID__ (implies __linux__) -// Linux (non-Android) __linux__ && !__ANDROID__ -// Darwin (macOS and iOS) __APPLE__ -// Akaros (http://akaros.org) __ros__ -// Windows _WIN32 -// NaCL __native_client__ -// AsmJS __asmjs__ -// WebAssembly __wasm__ -// Fuchsia __Fuchsia__ -// -// Note that since Android defines both __ANDROID__ and __linux__, one -// may probe for either Linux or Android by simply testing for __linux__. -// -// NOTE: For __APPLE__ platforms, we use #include <TargetConditionals.h> -// to distinguish os variants. -// -// http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system - -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -// ----------------------------------------------------------------------------- -// Architecture Checks -// ----------------------------------------------------------------------------- - -// These preprocessor directives are trying to determine CPU architecture, -// including necessary headers to support hardware AES. -// -// ABSL_ARCH_{X86/PPC/ARM} macros determine the platform. -#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || \ - defined(_M_X64) -#define ABSL_ARCH_X86_64 -#elif defined(__i386) || defined(_M_IX86) -#define ABSL_ARCH_X86_32 -#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) -#define ABSL_ARCH_AARCH64 -#elif defined(__arm__) || defined(__ARMEL__) || defined(_M_ARM) -#define ABSL_ARCH_ARM -#elif defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ - defined(__ppc__) || defined(__PPC__) -#define ABSL_ARCH_PPC -#else -// Unsupported architecture. -// * https://sourceforge.net/p/predef/wiki/Architectures/ -// * https://msdn.microsoft.com/en-us/library/b0084kay.aspx -// * for gcc, clang: "echo | gcc -E -dM -" -#endif - -// ----------------------------------------------------------------------------- -// Attribute Checks -// ----------------------------------------------------------------------------- - -// ABSL_RANDOM_INTERNAL_RESTRICT annotates whether pointers may be considered -// to be unaliased. -#if defined(__clang__) || defined(__GNUC__) -#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict__ -#elif defined(_MSC_VER) -#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict -#else -#define ABSL_RANDOM_INTERNAL_RESTRICT -#endif - -// ABSL_HAVE_ACCELERATED_AES indicates whether the currently active compiler -// flags (e.g. -maes) allow using hardware accelerated AES instructions, which -// implies us assuming that the target platform supports them. -#define ABSL_HAVE_ACCELERATED_AES 0 - -#if defined(ABSL_ARCH_X86_64) - -#if defined(__AES__) || defined(__AVX__) -#undef ABSL_HAVE_ACCELERATED_AES -#define ABSL_HAVE_ACCELERATED_AES 1 -#endif - -#elif defined(ABSL_ARCH_PPC) - -// Rely on VSX and CRYPTO extensions for vcipher on PowerPC. -#if (defined(__VEC__) || defined(__ALTIVEC__)) && defined(__VSX__) && \ - defined(__CRYPTO__) -#undef ABSL_HAVE_ACCELERATED_AES -#define ABSL_HAVE_ACCELERATED_AES 1 -#endif - -#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64) - -// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf -// Rely on NEON+CRYPTO extensions for ARM. -#if defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO) -#undef ABSL_HAVE_ACCELERATED_AES -#define ABSL_HAVE_ACCELERATED_AES 1 -#endif - -#endif - -// NaCl does not allow AES. -#if defined(__native_client__) -#undef ABSL_HAVE_ACCELERATED_AES -#define ABSL_HAVE_ACCELERATED_AES 0 -#endif - -// ABSL_RANDOM_INTERNAL_AES_DISPATCH indicates whether the currently active -// platform has, or should use run-time dispatch for selecting the -// acclerated Randen implementation. -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 - -#if defined(ABSL_ARCH_X86_64) -// Dispatch is available on x86_64 -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 -#elif defined(__linux__) && defined(ABSL_ARCH_PPC) -// Or when running linux PPC -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 -#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64) -// Or when running linux AArch64 -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 -#elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8) -// Or when running linux ARM v8 or higher. -// (This captures a lot of Android configurations.) -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 -#endif - -// NaCl does not allow dispatch. -#if defined(__native_client__) -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 -#endif - -// iOS does not support dispatch, even on x86, since applications -// should be bundled as fat binaries, with a different build tailored for -// each specific supported platform/architecture. -#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ - (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR) -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 -#endif - -#endif // ABSL_RANDOM_INTERNAL_PLATFORM_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/pool_urbg.cc b/third_party/abseil_cpp/absl/random/internal/pool_urbg.cc deleted file mode 100644 index 5bee530770eb..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/pool_urbg.cc +++ /dev/null @@ -1,254 +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/pool_urbg.h" - -#include <algorithm> -#include <atomic> -#include <cstdint> -#include <cstring> -#include <iterator> - -#include "absl/base/attributes.h" -#include "absl/base/call_once.h" -#include "absl/base/config.h" -#include "absl/base/internal/endian.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/spinlock.h" -#include "absl/base/internal/sysinfo.h" -#include "absl/base/internal/unaligned_access.h" -#include "absl/base/optimization.h" -#include "absl/random/internal/randen.h" -#include "absl/random/internal/seed_material.h" -#include "absl/random/seed_gen_exception.h" - -using absl::base_internal::SpinLock; -using absl::base_internal::SpinLockHolder; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -// RandenPoolEntry is a thread-safe pseudorandom bit generator, implementing a -// single generator within a RandenPool<T>. It is an internal implementation -// detail, and does not aim to conform to [rand.req.urng]. -// -// NOTE: There are alignment issues when used on ARM, for instance. -// See the allocation code in PoolAlignedAlloc(). -class RandenPoolEntry { - public: - static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t); - static constexpr size_t kCapacity = - RandenTraits::kCapacityBytes / sizeof(uint32_t); - - void Init(absl::Span<const uint32_t> data) { - SpinLockHolder l(&mu_); // Always uncontested. - std::copy(data.begin(), data.end(), std::begin(state_)); - next_ = kState; - } - - // Copy bytes into out. - void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_); - - // Returns random bits from the buffer in units of T. - template <typename T> - inline T Generate() ABSL_LOCKS_EXCLUDED(mu_); - - inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { - if (next_ >= kState) { - next_ = kCapacity; - impl_.Generate(state_); - } - } - - private: - // Randen URBG state. - uint32_t state_[kState] ABSL_GUARDED_BY(mu_); // First to satisfy alignment. - SpinLock mu_; - const Randen impl_; - size_t next_ ABSL_GUARDED_BY(mu_); -}; - -template <> -inline uint8_t RandenPoolEntry::Generate<uint8_t>() { - SpinLockHolder l(&mu_); - MaybeRefill(); - return static_cast<uint8_t>(state_[next_++]); -} - -template <> -inline uint16_t RandenPoolEntry::Generate<uint16_t>() { - SpinLockHolder l(&mu_); - MaybeRefill(); - return static_cast<uint16_t>(state_[next_++]); -} - -template <> -inline uint32_t RandenPoolEntry::Generate<uint32_t>() { - SpinLockHolder l(&mu_); - MaybeRefill(); - return state_[next_++]; -} - -template <> -inline uint64_t RandenPoolEntry::Generate<uint64_t>() { - SpinLockHolder l(&mu_); - if (next_ >= kState - 1) { - next_ = kCapacity; - impl_.Generate(state_); - } - auto p = state_ + next_; - next_ += 2; - - uint64_t result; - std::memcpy(&result, p, sizeof(result)); - return result; -} - -void RandenPoolEntry::Fill(uint8_t* out, size_t bytes) { - SpinLockHolder l(&mu_); - while (bytes > 0) { - MaybeRefill(); - size_t remaining = (kState - next_) * sizeof(state_[0]); - size_t to_copy = std::min(bytes, remaining); - std::memcpy(out, &state_[next_], to_copy); - out += to_copy; - bytes -= to_copy; - next_ += (to_copy + sizeof(state_[0]) - 1) / sizeof(state_[0]); - } -} - -// Number of pooled urbg entries. -static constexpr int kPoolSize = 8; - -// Shared pool entries. -static absl::once_flag pool_once; -ABSL_CACHELINE_ALIGNED static RandenPoolEntry* shared_pools[kPoolSize]; - -// Returns an id in the range [0 ... kPoolSize), which indexes into the -// pool of random engines. -// -// Each thread to access the pool is assigned a sequential ID (without reuse) -// from the pool-id space; the id is cached in a thread_local variable. -// This id is assigned based on the arrival-order of the thread to the -// GetPoolID call; this has no binary, CL, or runtime stability because -// on subsequent runs the order within the same program may be significantly -// different. However, as other thread IDs are not assigned sequentially, -// this is not expected to matter. -int GetPoolID() { - static_assert(kPoolSize >= 1, - "At least one urbg instance is required for PoolURBG"); - - ABSL_CONST_INIT static std::atomic<int64_t> sequence{0}; - -#ifdef ABSL_HAVE_THREAD_LOCAL - static thread_local int my_pool_id = -1; - if (ABSL_PREDICT_FALSE(my_pool_id < 0)) { - my_pool_id = (sequence++ % kPoolSize); - } - return my_pool_id; -#else - static pthread_key_t tid_key = [] { - pthread_key_t tmp_key; - int err = pthread_key_create(&tmp_key, nullptr); - if (err) { - ABSL_RAW_LOG(FATAL, "pthread_key_create failed with %d", err); - } - return tmp_key; - }(); - - // Store the value in the pthread_{get/set}specific. However an uninitialized - // value is 0, so add +1 to distinguish from the null value. - intptr_t my_pool_id = - reinterpret_cast<intptr_t>(pthread_getspecific(tid_key)); - if (ABSL_PREDICT_FALSE(my_pool_id == 0)) { - // No allocated ID, allocate the next value, cache it, and return. - my_pool_id = (sequence++ % kPoolSize) + 1; - int err = pthread_setspecific(tid_key, reinterpret_cast<void*>(my_pool_id)); - if (err) { - ABSL_RAW_LOG(FATAL, "pthread_setspecific failed with %d", err); - } - } - return my_pool_id - 1; -#endif -} - -// Allocate a RandenPoolEntry with at least 32-byte alignment, which is required -// by ARM platform code. -RandenPoolEntry* PoolAlignedAlloc() { - constexpr size_t kAlignment = - ABSL_CACHELINE_SIZE > 32 ? ABSL_CACHELINE_SIZE : 32; - - // Not all the platforms that we build for have std::aligned_alloc, however - // since we never free these objects, we can over allocate and munge the - // pointers to the correct alignment. - void* memory = std::malloc(sizeof(RandenPoolEntry) + kAlignment); - auto x = reinterpret_cast<intptr_t>(memory); - auto y = x % kAlignment; - void* aligned = - (y == 0) ? memory : reinterpret_cast<void*>(x + kAlignment - y); - return new (aligned) RandenPoolEntry(); -} - -// Allocate and initialize kPoolSize objects of type RandenPoolEntry. -// -// The initialization strategy is to initialize one object directly from -// OS entropy, then to use that object to seed all of the individual -// pool instances. -void InitPoolURBG() { - static constexpr size_t kSeedSize = - RandenTraits::kStateBytes / sizeof(uint32_t); - // Read the seed data from OS entropy once. - uint32_t seed_material[kPoolSize * kSeedSize]; - if (!random_internal::ReadSeedMaterialFromOSEntropy( - absl::MakeSpan(seed_material))) { - random_internal::ThrowSeedGenException(); - } - for (int i = 0; i < kPoolSize; i++) { - shared_pools[i] = PoolAlignedAlloc(); - shared_pools[i]->Init( - absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize)); - } -} - -// Returns the pool entry for the current thread. -RandenPoolEntry* GetPoolForCurrentThread() { - absl::call_once(pool_once, InitPoolURBG); - return shared_pools[GetPoolID()]; -} - -} // namespace - -template <typename T> -typename RandenPool<T>::result_type RandenPool<T>::Generate() { - auto* pool = GetPoolForCurrentThread(); - return pool->Generate<T>(); -} - -template <typename T> -void RandenPool<T>::Fill(absl::Span<result_type> data) { - auto* pool = GetPoolForCurrentThread(); - pool->Fill(reinterpret_cast<uint8_t*>(data.data()), - data.size() * sizeof(result_type)); -} - -template class RandenPool<uint8_t>; -template class RandenPool<uint16_t>; -template class RandenPool<uint32_t>; -template class RandenPool<uint64_t>; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/pool_urbg.h b/third_party/abseil_cpp/absl/random/internal/pool_urbg.h deleted file mode 100644 index 05721929f54e..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/pool_urbg.h +++ /dev/null @@ -1,131 +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. - -#ifndef ABSL_RANDOM_INTERNAL_POOL_URBG_H_ -#define ABSL_RANDOM_INTERNAL_POOL_URBG_H_ - -#include <cinttypes> -#include <limits> - -#include "absl/random/internal/traits.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// RandenPool is a thread-safe random number generator [random.req.urbg] that -// uses an underlying pool of Randen generators to generate values. Each thread -// has affinity to one instance of the underlying pool generators. Concurrent -// access is guarded by a spin-lock. -template <typename T> -class RandenPool { - public: - using result_type = T; - static_assert(std::is_unsigned<result_type>::value, - "RandenPool template argument must be a built-in unsigned " - "integer type"); - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - RandenPool() {} - - // Returns a single value. - inline result_type operator()() { return Generate(); } - - // Fill data with random values. - static void Fill(absl::Span<result_type> data); - - protected: - // Generate returns a single value. - static result_type Generate(); -}; - -extern template class RandenPool<uint8_t>; -extern template class RandenPool<uint16_t>; -extern template class RandenPool<uint32_t>; -extern template class RandenPool<uint64_t>; - -// PoolURBG uses an underlying pool of random generators to implement a -// thread-compatible [random.req.urbg] interface with an internal cache of -// values. -template <typename T, size_t kBufferSize> -class PoolURBG { - // Inheritance to access the protected static members of RandenPool. - using unsigned_type = typename make_unsigned_bits<T>::type; - using PoolType = RandenPool<unsigned_type>; - using SpanType = absl::Span<unsigned_type>; - - static constexpr size_t kInitialBuffer = kBufferSize + 1; - static constexpr size_t kHalfBuffer = kBufferSize / 2; - - public: - using result_type = T; - - static_assert(std::is_unsigned<result_type>::value, - "PoolURBG must be parameterized by an unsigned integer type"); - - static_assert(kBufferSize > 1, - "PoolURBG must be parameterized by a buffer-size > 1"); - - static_assert(kBufferSize <= 256, - "PoolURBG must be parameterized by a buffer-size <= 256"); - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - PoolURBG() : next_(kInitialBuffer) {} - - // copy-constructor does not copy cache. - PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {} - const PoolURBG& operator=(const PoolURBG&) { - next_ = kInitialBuffer; - return *this; - } - - // move-constructor does move cache. - PoolURBG(PoolURBG&&) = default; - PoolURBG& operator=(PoolURBG&&) = default; - - inline result_type operator()() { - if (next_ >= kBufferSize) { - next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0; - PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_), - kBufferSize - next_)); - } - return state_[next_++]; - } - - private: - // Buffer size. - size_t next_; // index within state_ - result_type state_[kBufferSize]; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_POOL_URBG_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/pool_urbg_test.cc b/third_party/abseil_cpp/absl/random/internal/pool_urbg_test.cc deleted file mode 100644 index 53f4eacf16fe..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/pool_urbg_test.cc +++ /dev/null @@ -1,182 +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/pool_urbg.h" - -#include <algorithm> -#include <bitset> -#include <cmath> -#include <cstdint> -#include <iterator> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/types/span.h" - -using absl::random_internal::PoolURBG; -using absl::random_internal::RandenPool; - -namespace { - -// is_randen_pool trait is true when parameterized by an RandenPool -template <typename T> -using is_randen_pool = typename absl::disjunction< // - std::is_same<T, RandenPool<uint8_t>>, // - std::is_same<T, RandenPool<uint16_t>>, // - std::is_same<T, RandenPool<uint32_t>>, // - std::is_same<T, RandenPool<uint64_t>>>; // - -// MyFill either calls RandenPool::Fill() or std::generate(..., rng) -template <typename T, typename V> -typename absl::enable_if_t<absl::negation<is_randen_pool<T>>::value, void> // -MyFill(T& rng, absl::Span<V> data) { // NOLINT(runtime/references) - std::generate(std::begin(data), std::end(data), rng); -} - -template <typename T, typename V> -typename absl::enable_if_t<is_randen_pool<T>::value, void> // -MyFill(T& rng, absl::Span<V> data) { // NOLINT(runtime/references) - rng.Fill(data); -} - -template <typename EngineType> -class PoolURBGTypedTest : public ::testing::Test {}; - -using EngineTypes = ::testing::Types< // - RandenPool<uint8_t>, // - RandenPool<uint16_t>, // - RandenPool<uint32_t>, // - RandenPool<uint64_t>, // - PoolURBG<uint8_t, 2>, // - PoolURBG<uint16_t, 2>, // - PoolURBG<uint32_t, 2>, // - PoolURBG<uint64_t, 2>, // - PoolURBG<unsigned int, 8>, // NOLINT(runtime/int) - PoolURBG<unsigned long, 8>, // NOLINT(runtime/int) - PoolURBG<unsigned long int, 4>, // NOLINT(runtime/int) - PoolURBG<unsigned long long, 4>>; // NOLINT(runtime/int) - -TYPED_TEST_SUITE(PoolURBGTypedTest, EngineTypes); - -// This test is checks that the engines meet the URBG interface requirements -// defined in [rand.req.urbg]. -TYPED_TEST(PoolURBGTypedTest, URBGInterface) { - using E = TypeParam; - using T = typename E::result_type; - - static_assert(std::is_copy_constructible<E>::value, - "engine must be copy constructible"); - - static_assert(absl::is_copy_assignable<E>::value, - "engine must be copy assignable"); - - E e; - const E x; - - e(); - - static_assert(std::is_same<decltype(e()), T>::value, - "return type of operator() must be result_type"); - - E u0(x); - u0(); - - E u1 = e; - u1(); -} - -// This validates that sequences are independent. -TYPED_TEST(PoolURBGTypedTest, VerifySequences) { - using E = TypeParam; - using result_type = typename E::result_type; - - E rng; - (void)rng(); // Discard one value. - - constexpr int kNumOutputs = 64; - result_type a[kNumOutputs]; - result_type b[kNumOutputs]; - std::fill(std::begin(b), std::end(b), 0); - - // Fill a using Fill or generate, depending on the engine type. - { - E x = rng; - MyFill(x, absl::MakeSpan(a)); - } - - // Fill b using std::generate(). - { - E x = rng; - std::generate(std::begin(b), std::end(b), x); - } - - // Test that generated sequence changed as sequence of bits, i.e. if about - // half of the bites were flipped between two non-correlated values. - size_t changed_bits = 0; - size_t unchanged_bits = 0; - size_t total_set = 0; - size_t total_bits = 0; - size_t equal_count = 0; - for (size_t i = 0; i < kNumOutputs; ++i) { - equal_count += (a[i] == b[i]) ? 1 : 0; - std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]); - changed_bits += bitset.count(); - unchanged_bits += bitset.size() - bitset.count(); - - std::bitset<sizeof(result_type) * 8> a_set(a[i]); - std::bitset<sizeof(result_type) * 8> b_set(b[i]); - total_set += a_set.count() + b_set.count(); - total_bits += 2 * 8 * sizeof(result_type); - } - // On average, half the bits are changed between two calls. - EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits)); - EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits)); - - // verify using a quick normal-approximation to the binomial. - EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits)) - << "@" << total_set / static_cast<double>(total_bits); - - // Also, A[i] == B[i] with probability (1/range) * N. - // Give this a pretty wide latitude, though. - const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8); - EXPECT_LE(equal_count, 1.0 + kExpected); -} - -} // namespace - -/* -$ nanobenchmarks 1 RandenPool construct -$ nanobenchmarks 1 PoolURBG construct - -RandenPool<uint32_t> | 1 | 1000 | 48482.00 ticks | 48.48 ticks | 13.9 ns -RandenPool<uint32_t> | 10 | 2000 | 1028795.00 ticks | 51.44 ticks | 14.7 ns -RandenPool<uint32_t> | 100 | 1000 | 5119968.00 ticks | 51.20 ticks | 14.6 ns -RandenPool<uint32_t> | 1000 | 500 | 25867936.00 ticks | 51.74 ticks | 14.8 ns - -RandenPool<uint64_t> | 1 | 1000 | 49921.00 ticks | 49.92 ticks | 14.3 ns -RandenPool<uint64_t> | 10 | 2000 | 1208269.00 ticks | 60.41 ticks | 17.3 ns -RandenPool<uint64_t> | 100 | 1000 | 5844955.00 ticks | 58.45 ticks | 16.7 ns -RandenPool<uint64_t> | 1000 | 500 | 28767404.00 ticks | 57.53 ticks | 16.4 ns - -PoolURBG<uint32_t,8> | 1 | 1000 | 86431.00 ticks | 86.43 ticks | 24.7 ns -PoolURBG<uint32_t,8> | 10 | 1000 | 206191.00 ticks | 20.62 ticks | 5.9 ns -PoolURBG<uint32_t,8> | 100 | 1000 | 1516049.00 ticks | 15.16 ticks | 4.3 ns -PoolURBG<uint32_t,8> | 1000 | 500 | 7613936.00 ticks | 15.23 ticks | 4.4 ns - -PoolURBG<uint64_t,4> | 1 | 1000 | 96668.00 ticks | 96.67 ticks | 27.6 ns -PoolURBG<uint64_t,4> | 10 | 1000 | 282423.00 ticks | 28.24 ticks | 8.1 ns -PoolURBG<uint64_t,4> | 100 | 1000 | 2609587.00 ticks | 26.10 ticks | 7.5 ns -PoolURBG<uint64_t,4> | 1000 | 500 | 12408757.00 ticks | 24.82 ticks | 7.1 ns - -*/ diff --git a/third_party/abseil_cpp/absl/random/internal/randen.cc b/third_party/abseil_cpp/absl/random/internal/randen.cc deleted file mode 100644 index 78a1e00c0832..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen.cc +++ /dev/null @@ -1,91 +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.h" - -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/randen_detect.h" - -// 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. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -struct RandenState { - const void* keys; - bool has_crypto; -}; - -RandenState GetRandenState() { - static const RandenState state = []() { - RandenState tmp; -#if ABSL_RANDOM_INTERNAL_AES_DISPATCH - // HW AES Dispatch. - if (HasRandenHwAesImplementation() && CPUSupportsRandenHwAes()) { - tmp.has_crypto = true; - tmp.keys = RandenHwAes::GetKeys(); - } else { - tmp.has_crypto = false; - tmp.keys = RandenSlow::GetKeys(); - } -#elif ABSL_HAVE_ACCELERATED_AES - // HW AES is enabled. - tmp.has_crypto = true; - tmp.keys = RandenHwAes::GetKeys(); -#else - // HW AES is disabled. - tmp.has_crypto = false; - tmp.keys = RandenSlow::GetKeys(); -#endif - return tmp; - }(); - return state; -} - -} // namespace - -Randen::Randen() { - auto tmp = GetRandenState(); - keys_ = tmp.keys; -#if ABSL_RANDOM_INTERNAL_AES_DISPATCH - has_crypto_ = tmp.has_crypto; -#endif -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/randen.h b/third_party/abseil_cpp/absl/random/internal/randen.h deleted file mode 100644 index c2834aaf3d2c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen.h +++ /dev/null @@ -1,102 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_H_ - -#include <cstddef> - -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_hwaes.h" -#include "absl/random/internal/randen_slow.h" -#include "absl/random/internal/randen_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// RANDen = RANDom generator or beetroots in Swiss German. -// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random -// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32. -// -// Randen implements the basic state manipulation methods. -class Randen { - public: - static constexpr size_t kStateBytes = RandenTraits::kStateBytes; - static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes; - static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes; - - ~Randen() = default; - - Randen(); - - // Generate updates the randen sponge. The outer portion of the sponge - // (kCapacityBytes .. kStateBytes) may be consumed as PRNG state. - template <typename T, size_t N> - void Generate(T (&state)[N]) const { - static_assert(N * sizeof(T) == kStateBytes, - "Randen::Generate() requires kStateBytes of state"); -#if ABSL_RANDOM_INTERNAL_AES_DISPATCH - // HW AES Dispatch. - if (has_crypto_) { - RandenHwAes::Generate(keys_, state); - } else { - RandenSlow::Generate(keys_, state); - } -#elif ABSL_HAVE_ACCELERATED_AES - // HW AES is enabled. - RandenHwAes::Generate(keys_, state); -#else - // HW AES is disabled. - RandenSlow::Generate(keys_, state); -#endif - } - - // Absorb incorporates additional seed material into the randen sponge. After - // absorb returns, Generate must be called before the state may be consumed. - template <typename S, size_t M, typename T, size_t N> - void Absorb(const S (&seed)[M], T (&state)[N]) const { - static_assert(M * sizeof(S) == RandenTraits::kSeedBytes, - "Randen::Absorb() requires kSeedBytes of seed"); - - static_assert(N * sizeof(T) == RandenTraits::kStateBytes, - "Randen::Absorb() requires kStateBytes of state"); -#if ABSL_RANDOM_INTERNAL_AES_DISPATCH - // HW AES Dispatch. - if (has_crypto_) { - RandenHwAes::Absorb(seed, state); - } else { - RandenSlow::Absorb(seed, state); - } -#elif ABSL_HAVE_ACCELERATED_AES - // HW AES is enabled. - RandenHwAes::Absorb(seed, state); -#else - // HW AES is disabled. - RandenSlow::Absorb(seed, state); -#endif - } - - private: - const void* keys_; -#if ABSL_RANDOM_INTERNAL_AES_DISPATCH - bool has_crypto_; -#endif -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/randen_benchmarks.cc b/third_party/abseil_cpp/absl/random/internal/randen_benchmarks.cc deleted file mode 100644 index f589172c0466..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_benchmarks.cc +++ /dev/null @@ -1,174 +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.h" - -#include <cstdint> -#include <cstdio> -#include <cstring> - -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/nanobenchmark.h" -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_engine.h" -#include "absl/random/internal/randen_hwaes.h" -#include "absl/random/internal/randen_slow.h" -#include "absl/strings/numbers.h" - -namespace { - -using absl::random_internal::Randen; -using absl::random_internal::RandenHwAes; -using absl::random_internal::RandenSlow; - -using absl::random_internal_nanobenchmark::FuncInput; -using absl::random_internal_nanobenchmark::FuncOutput; -using absl::random_internal_nanobenchmark::InvariantTicksPerSecond; -using absl::random_internal_nanobenchmark::MeasureClosure; -using absl::random_internal_nanobenchmark::Params; -using absl::random_internal_nanobenchmark::PinThreadToCPU; -using absl::random_internal_nanobenchmark::Result; - -// Local state parameters. -static constexpr size_t kStateSizeT = Randen::kStateBytes / sizeof(uint64_t); -static constexpr size_t kSeedSizeT = Randen::kSeedBytes / sizeof(uint32_t); - -// Randen implementation benchmarks. -template <typename T> -struct AbsorbFn : public T { - mutable uint64_t state[kStateSizeT] = {}; - mutable uint32_t seed[kSeedSizeT] = {}; - - static constexpr size_t bytes() { return sizeof(seed); } - - FuncOutput operator()(const FuncInput num_iters) const { - for (size_t i = 0; i < num_iters; ++i) { - this->Absorb(seed, state); - } - return state[0]; - } -}; - -template <typename T> -struct GenerateFn : public T { - mutable uint64_t state[kStateSizeT]; - GenerateFn() { std::memset(state, 0, sizeof(state)); } - - static constexpr size_t bytes() { return sizeof(state); } - - FuncOutput operator()(const FuncInput num_iters) const { - const auto* keys = this->GetKeys(); - for (size_t i = 0; i < num_iters; ++i) { - this->Generate(keys, state); - } - return state[0]; - } -}; - -template <typename UInt> -struct Engine { - mutable absl::random_internal::randen_engine<UInt> rng; - - static constexpr size_t bytes() { return sizeof(UInt); } - - FuncOutput operator()(const FuncInput num_iters) const { - for (size_t i = 0; i < num_iters - 1; ++i) { - rng(); - } - return rng(); - } -}; - -template <size_t N> -void Print(const char* name, const size_t n, const Result (&results)[N], - const size_t bytes) { - if (n == 0) { - ABSL_RAW_LOG( - WARNING, - "WARNING: Measurement failed, should not happen when using " - "PinThreadToCPU unless the region to measure takes > 1 second.\n"); - return; - } - - static const double ns_per_tick = 1e9 / InvariantTicksPerSecond(); - static constexpr const double kNsPerS = 1e9; // ns/s - static constexpr const double kMBPerByte = 1.0 / 1048576.0; // Mb / b - static auto header = [] { - return printf("%20s %8s: %12s ticks; %9s (%9s) %8s\n", "Name", "Count", - "Total", "Variance", "Time", "bytes/s"); - }(); - (void)header; - - for (size_t i = 0; i < n; ++i) { - const double ticks_per_call = results[i].ticks / results[i].input; - const double ns_per_call = ns_per_tick * ticks_per_call; - const double bytes_per_ns = bytes / ns_per_call; - const double mb_per_s = bytes_per_ns * kNsPerS * kMBPerByte; - // Output - printf("%20s %8zu: %12.2f ticks; MAD=%4.2f%% (%6.1f ns) %8.1f Mb/s\n", - name, results[i].input, results[i].ticks, - results[i].variability * 100.0, ns_per_call, mb_per_s); - } -} - -// Fails here -template <typename Op, size_t N> -void Measure(const char* name, const FuncInput (&inputs)[N]) { - Op op; - - Result results[N]; - Params params; - params.verbose = false; - params.max_evals = 6; // avoid test timeout - const size_t num_results = MeasureClosure(op, inputs, N, results, params); - Print(name, num_results, results, op.bytes()); -} - -// unpredictable == 1 but the compiler does not know that. -void RunAll(const int argc, char* argv[]) { - if (argc == 2) { - int cpu = -1; - if (!absl::SimpleAtoi(argv[1], &cpu)) { - ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n"); - } - PinThreadToCPU(cpu); - } - - // The compiler cannot reduce this to a constant. - const FuncInput unpredictable = (argc != 999); - static const FuncInput inputs[] = {unpredictable * 100, unpredictable * 1000}; - -#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES - Measure<AbsorbFn<RandenHwAes>>("Absorb (HwAes)", inputs); -#endif - Measure<AbsorbFn<RandenSlow>>("Absorb (Slow)", inputs); - -#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES - Measure<GenerateFn<RandenHwAes>>("Generate (HwAes)", inputs); -#endif - Measure<GenerateFn<RandenSlow>>("Generate (Slow)", inputs); - - // Measure the production engine. - static const FuncInput inputs1[] = {unpredictable * 1000, - unpredictable * 10000}; - Measure<Engine<uint64_t>>("randen_engine<uint64_t>", inputs1); - Measure<Engine<uint32_t>>("randen_engine<uint32_t>", inputs1); -} - -} // namespace - -int main(int argc, char* argv[]) { - RunAll(argc, argv); - return 0; -} diff --git a/third_party/abseil_cpp/absl/random/internal/randen_detect.cc b/third_party/abseil_cpp/absl/random/internal/randen_detect.cc deleted file mode 100644 index bbe7b965329c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_detect.cc +++ /dev/null @@ -1,221 +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. - -// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate -// symbols from arbitrary system and other headers, since it may be built -// with different flags from other targets, using different levels of -// optimization, potentially introducing ODR violations. - -#include "absl/random/internal/randen_detect.h" - -#include <cstdint> -#include <cstring> - -#include "absl/random/internal/platform.h" - -#if defined(ABSL_ARCH_X86_64) -#define ABSL_INTERNAL_USE_X86_CPUID -#elif defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \ - defined(ABSL_ARCH_AARCH64) -#if defined(__ANDROID__) -#define ABSL_INTERNAL_USE_ANDROID_GETAUXVAL -#define ABSL_INTERNAL_USE_GETAUXVAL -#elif defined(__linux__) -#define ABSL_INTERNAL_USE_LINUX_GETAUXVAL -#define ABSL_INTERNAL_USE_GETAUXVAL -#endif -#endif - -#if defined(ABSL_INTERNAL_USE_X86_CPUID) -#if defined(_WIN32) || defined(_WIN64) -#include <intrin.h> // NOLINT(build/include_order) -#pragma intrinsic(__cpuid) -#else -// MSVC-equivalent __cpuid intrinsic function. -static void __cpuid(int cpu_info[4], int info_type) { - __asm__ volatile("cpuid \n\t" - : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), - "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#endif -#endif // ABSL_INTERNAL_USE_X86_CPUID - -// On linux, just use the c-library getauxval call. -#if defined(ABSL_INTERNAL_USE_LINUX_GETAUXVAL) - -extern "C" unsigned long getauxval(unsigned long type); // NOLINT(runtime/int) - -static uint32_t GetAuxval(uint32_t hwcap_type) { - return static_cast<uint32_t>(getauxval(hwcap_type)); -} - -#endif - -// On android, probe the system's C library for getauxval(). -// This is the same technique used by the android NDK cpu features library -// as well as the google open-source cpu_features library. -// -// TODO(absl-team): Consider implementing a fallback of directly reading -// /proc/self/auxval. -#if defined(ABSL_INTERNAL_USE_ANDROID_GETAUXVAL) -#include <dlfcn.h> - -static uint32_t GetAuxval(uint32_t hwcap_type) { - // NOLINTNEXTLINE(runtime/int) - typedef unsigned long (*getauxval_func_t)(unsigned long); - - dlerror(); // Cleaning error state before calling dlopen. - void* libc_handle = dlopen("libc.so", RTLD_NOW); - if (!libc_handle) { - return 0; - } - uint32_t result = 0; - void* sym = dlsym(libc_handle, "getauxval"); - if (sym) { - getauxval_func_t func; - memcpy(&func, &sym, sizeof(func)); - result = static_cast<uint32_t>((*func)(hwcap_type)); - } - dlclose(libc_handle); - return result; -} - -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// The default return at the end of the function might be unreachable depending -// on the configuration. Ignore that warning. -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code-return" -#endif - -// CPUSupportsRandenHwAes returns whether the CPU is a microarchitecture -// which supports the crpyto/aes instructions or extensions necessary to use the -// accelerated RandenHwAes implementation. -// -// 1. For x86 it is sufficient to use the CPUID instruction to detect whether -// the cpu supports AES instructions. Done. -// -// Fon non-x86 it is much more complicated. -// -// 2. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either -// the direct c-library version, or the android probing version which loads -// libc), and read the hardware capability bits. -// This is based on the technique used by boringssl uses to detect -// cpu capabilities, and should allow us to enable crypto in the android -// builds where it is supported. -// -// 3. Use the default for the compiler architecture. -// - -bool CPUSupportsRandenHwAes() { -#if defined(ABSL_INTERNAL_USE_X86_CPUID) - // 1. For x86: Use CPUID to detect the required AES instruction set. - int regs[4]; - __cpuid(reinterpret_cast<int*>(regs), 1); - return regs[2] & (1 << 25); // AES - -#elif defined(ABSL_INTERNAL_USE_GETAUXVAL) - // 2. Use getauxval() to read the hardware bits and determine - // cpu capabilities. - -#define AT_HWCAP 16 -#define AT_HWCAP2 26 -#if defined(ABSL_ARCH_PPC) - // For Power / PPC: Expect that the cpu supports VCRYPTO - // See https://members.openpowerfoundation.org/document/dl/576 - // VCRYPTO should be present in POWER8 >= 2.07. - // Uses Linux kernel constants from arch/powerpc/include/uapi/asm/cputable.h - static const uint32_t kVCRYPTO = 0x02000000; - const uint32_t hwcap = GetAuxval(AT_HWCAP2); - return (hwcap & kVCRYPTO) != 0; - -#elif defined(ABSL_ARCH_ARM) - // For ARM: Require crypto+neon - // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html - // Uses Linux kernel constants from arch/arm64/include/asm/hwcap.h - static const uint32_t kNEON = 1 << 12; - uint32_t hwcap = GetAuxval(AT_HWCAP); - if ((hwcap & kNEON) == 0) { - return false; - } - - // And use it again to detect AES. - static const uint32_t kAES = 1 << 0; - const uint32_t hwcap2 = GetAuxval(AT_HWCAP2); - return (hwcap2 & kAES) != 0; - -#elif defined(ABSL_ARCH_AARCH64) - // For AARCH64: Require crypto+neon - // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html - static const uint32_t kNEON = 1 << 1; - static const uint32_t kAES = 1 << 3; - const uint32_t hwcap = GetAuxval(AT_HWCAP); - return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0); -#endif - -#else // ABSL_INTERNAL_USE_GETAUXVAL - // 3. By default, assume that the compiler default. - return ABSL_HAVE_ACCELERATED_AES ? true : false; - -#endif - // NOTE: There are some other techniques that may be worth trying: - // - // * Use an environment variable: ABSL_RANDOM_USE_HWAES - // - // * Rely on compiler-generated target-based dispatch. - // Using x86/gcc it might look something like this: - // - // int __attribute__((target("aes"))) HasAes() { return 1; } - // int __attribute__((target("default"))) HasAes() { return 0; } - // - // This does not work on all architecture/compiler combinations. - // - // * On Linux consider reading /proc/cpuinfo and/or /proc/self/auxv. - // These files have lines which are easy to parse; for ARM/AARCH64 it is quite - // easy to find the Features: line and extract aes / neon. Likewise for - // PPC. - // - // * Fork a process and test for SIGILL: - // - // * Many architectures have instructions to read the ISA. Unfortunately - // most of those require that the code is running in ring 0 / - // protected-mode. - // - // There are several examples. e.g. Valgrind detects PPC ISA 2.07: - // https://github.com/lu-zero/valgrind/blob/master/none/tests/ppc64/test_isa_2_07_part1.c - // - // MRS <Xt>, ID_AA64ISAR0_EL1 ; Read ID_AA64ISAR0_EL1 into Xt - // - // uint64_t val; - // __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val)); - // - // * Use a CPUID-style heuristic database. - // - // * On Apple (__APPLE__), AES is available on Arm v8. - // https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios -} - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/randen_detect.h b/third_party/abseil_cpp/absl/random/internal/randen_detect.h deleted file mode 100644 index f283f4322647..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_detect.h +++ /dev/null @@ -1,33 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Returns whether the current CPU supports RandenHwAes implementation. -// This typically involves supporting cryptographic extensions on whichever -// platform is currently running. -bool CPUSupportsRandenHwAes(); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/randen_engine.h b/third_party/abseil_cpp/absl/random/internal/randen_engine.h deleted file mode 100644 index 6b33731336e7..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_engine.h +++ /dev/null @@ -1,230 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_ - -#include <algorithm> -#include <cinttypes> -#include <cstdlib> -#include <iostream> -#include <iterator> -#include <limits> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/random/internal/iostream_state_saver.h" -#include "absl/random/internal/randen.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Deterministic pseudorandom byte generator with backtracking resistance -// (leaking the state does not compromise prior outputs). Based on Reverie -// (see "A Robust and Sponge-Like PRNG with Improved Efficiency") instantiated -// with an improved Simpira-like permutation. -// Returns values of type "T" (must be a built-in unsigned integer type). -// -// RANDen = RANDom generator or beetroots in Swiss High German. -// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random -// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32. -template <typename T> -class alignas(16) randen_engine { - public: - // C++11 URBG interface: - using result_type = T; - static_assert(std::is_unsigned<result_type>::value, - "randen_engine template argument must be a built-in unsigned " - "integer type"); - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - explicit randen_engine(result_type seed_value = 0) { seed(seed_value); } - - template <class SeedSequence, - typename = typename absl::enable_if_t< - !std::is_same<SeedSequence, randen_engine>::value>> - explicit randen_engine(SeedSequence&& seq) { - seed(seq); - } - - randen_engine(const randen_engine&) = default; - - // Returns random bits from the buffer in units of result_type. - result_type operator()() { - // Refill the buffer if needed (unlikely). - if (next_ >= kStateSizeT) { - next_ = kCapacityT; - impl_.Generate(state_); - } - - return state_[next_++]; - } - - template <class SeedSequence> - typename absl::enable_if_t< - !std::is_convertible<SeedSequence, result_type>::value> - seed(SeedSequence&& seq) { - // Zeroes the state. - seed(); - reseed(seq); - } - - void seed(result_type seed_value = 0) { - next_ = kStateSizeT; - // Zeroes the inner state and fills the outer state with seed_value to - // mimics behaviour of reseed - std::fill(std::begin(state_), std::begin(state_) + kCapacityT, 0); - std::fill(std::begin(state_) + kCapacityT, std::end(state_), seed_value); - } - - // Inserts entropy into (part of) the state. Calling this periodically with - // sufficient entropy ensures prediction resistance (attackers cannot predict - // future outputs even if state is compromised). - template <class SeedSequence> - void reseed(SeedSequence& seq) { - using sequence_result_type = typename SeedSequence::result_type; - static_assert(sizeof(sequence_result_type) == 4, - "SeedSequence::result_type must be 32-bit"); - - constexpr size_t kBufferSize = - Randen::kSeedBytes / sizeof(sequence_result_type); - alignas(16) sequence_result_type buffer[kBufferSize]; - - // Randen::Absorb XORs the seed into state, which is then mixed by a call - // to Randen::Generate. Seeding with only the provided entropy is preferred - // to using an arbitrary generate() call, so use [rand.req.seed_seq] - // size as a proxy for the number of entropy units that can be generated - // without relying on seed sequence mixing... - const size_t entropy_size = seq.size(); - if (entropy_size < kBufferSize) { - // ... and only request that many values, or 256-bits, when unspecified. - const size_t requested_entropy = (entropy_size == 0) ? 8u : entropy_size; - std::fill(std::begin(buffer) + requested_entropy, std::end(buffer), 0); - seq.generate(std::begin(buffer), std::begin(buffer) + requested_entropy); - // The Randen paper suggests preferentially initializing even-numbered - // 128-bit vectors of the randen state (there are 16 such vectors). - // The seed data is merged into the state offset by 128-bits, which - // implies prefering seed bytes [16..31, ..., 208..223]. Since the - // buffer is 32-bit values, we swap the corresponding buffer positions in - // 128-bit chunks. - size_t dst = kBufferSize; - while (dst > 7) { - // leave the odd bucket as-is. - dst -= 4; - size_t src = dst >> 1; - // swap 128-bits into the even bucket - std::swap(buffer[--dst], buffer[--src]); - std::swap(buffer[--dst], buffer[--src]); - std::swap(buffer[--dst], buffer[--src]); - std::swap(buffer[--dst], buffer[--src]); - } - } else { - seq.generate(std::begin(buffer), std::end(buffer)); - } - impl_.Absorb(buffer, state_); - - // Generate will be called when operator() is called - next_ = kStateSizeT; - } - - void discard(uint64_t count) { - uint64_t step = std::min<uint64_t>(kStateSizeT - next_, count); - count -= step; - - constexpr uint64_t kRateT = kStateSizeT - kCapacityT; - while (count > 0) { - next_ = kCapacityT; - impl_.Generate(state_); - step = std::min<uint64_t>(kRateT, count); - count -= step; - } - next_ += step; - } - - bool operator==(const randen_engine& other) const { - return next_ == other.next_ && - std::equal(std::begin(state_), std::end(state_), - std::begin(other.state_)); - } - - bool operator!=(const randen_engine& other) const { - return !(*this == other); - } - - template <class CharT, class Traits> - friend std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const randen_engine<T>& engine) { // NOLINT(runtime/references) - using numeric_type = - typename random_internal::stream_format_type<result_type>::type; - auto saver = random_internal::make_ostream_state_saver(os); - for (const auto& elem : engine.state_) { - // In the case that `elem` is `uint8_t`, it must be cast to something - // larger so that it prints as an integer rather than a character. For - // simplicity, apply the cast all circumstances. - os << static_cast<numeric_type>(elem) << os.fill(); - } - os << engine.next_; - return os; - } - - template <class CharT, class Traits> - friend std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - randen_engine<T>& engine) { // NOLINT(runtime/references) - using numeric_type = - typename random_internal::stream_format_type<result_type>::type; - result_type state[kStateSizeT]; - size_t next; - for (auto& elem : state) { - // It is not possible to read uint8_t from wide streams, so it is - // necessary to read a wider type and then cast it to uint8_t. - numeric_type value; - is >> value; - elem = static_cast<result_type>(value); - } - is >> next; - if (is.fail()) { - return is; - } - std::memcpy(engine.state_, state, sizeof(engine.state_)); - engine.next_ = next; - return is; - } - - private: - static constexpr size_t kStateSizeT = - Randen::kStateBytes / sizeof(result_type); - static constexpr size_t kCapacityT = - Randen::kCapacityBytes / sizeof(result_type); - - // First kCapacityT are `inner', the others are accessible random bits. - alignas(16) result_type state_[kStateSizeT]; - size_t next_; // index within state_ - Randen impl_; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/randen_engine_test.cc b/third_party/abseil_cpp/absl/random/internal/randen_engine_test.cc deleted file mode 100644 index c8e7685bddad..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_engine_test.cc +++ /dev/null @@ -1,656 +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_engine.h" - -#include <algorithm> -#include <bitset> -#include <random> -#include <sstream> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/explicit_seed_seq.h" -#include "absl/strings/str_cat.h" -#include "absl/time/clock.h" - -#define UPDATE_GOLDEN 0 - -using randen_u64 = absl::random_internal::randen_engine<uint64_t>; -using randen_u32 = absl::random_internal::randen_engine<uint32_t>; -using absl::random_internal::ExplicitSeedSeq; - -namespace { - -template <typename UIntType> -class RandenEngineTypedTest : public ::testing::Test {}; - -using UIntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>; - -TYPED_TEST_SUITE(RandenEngineTypedTest, UIntTypes); - -TYPED_TEST(RandenEngineTypedTest, VerifyReseedChangesAllValues) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - using result_type = typename randen::result_type; - - const size_t kNumOutputs = (sizeof(randen) * 2 / sizeof(TypeParam)) + 1; - randen engine; - - // MSVC emits error 2719 without the use of std::ref below. - // * formal parameter with __declspec(align('#')) won't be aligned - - { - std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7}; - engine.seed(seq1); - } - result_type a[kNumOutputs]; - std::generate(std::begin(a), std::end(a), std::ref(engine)); - - { - std::random_device rd; - std::seed_seq seq2{rd(), rd(), rd()}; - engine.seed(seq2); - } - result_type b[kNumOutputs]; - std::generate(std::begin(b), std::end(b), std::ref(engine)); - - // Test that generated sequence changed as sequence of bits, i.e. if about - // half of the bites were flipped between two non-correlated values. - size_t changed_bits = 0; - size_t unchanged_bits = 0; - size_t total_set = 0; - size_t total_bits = 0; - size_t equal_count = 0; - for (size_t i = 0; i < kNumOutputs; ++i) { - equal_count += (a[i] == b[i]) ? 1 : 0; - std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]); - changed_bits += bitset.count(); - unchanged_bits += bitset.size() - bitset.count(); - - std::bitset<sizeof(result_type) * 8> a_set(a[i]); - std::bitset<sizeof(result_type) * 8> b_set(b[i]); - total_set += a_set.count() + b_set.count(); - total_bits += 2 * 8 * sizeof(result_type); - } - // On average, half the bits are changed between two calls. - EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits)); - EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits)); - - // Verify using a quick normal-approximation to the binomial. - EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits)) - << "@" << total_set / static_cast<double>(total_bits); - - // Also, A[i] == B[i] with probability (1/range) * N. - // Give this a pretty wide latitude, though. - const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8); - EXPECT_LE(equal_count, 1.0 + kExpected); -} - -// Number of values that needs to be consumed to clean two sizes of buffer -// and trigger third refresh. (slightly overestimates the actual state size). -constexpr size_t kTwoBufferValues = sizeof(randen_u64) / sizeof(uint16_t) + 1; - -TYPED_TEST(RandenEngineTypedTest, VerifyDiscard) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - - for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) { - randen engine_used; - for (size_t i = 0; i < num_used; ++i) { - engine_used(); - } - - for (size_t num_discard = 0; num_discard < kTwoBufferValues; - ++num_discard) { - randen engine1 = engine_used; - randen engine2 = engine_used; - for (size_t i = 0; i < num_discard; ++i) { - engine1(); - } - engine2.discard(num_discard); - for (size_t i = 0; i < kTwoBufferValues; ++i) { - const auto r1 = engine1(); - const auto r2 = engine2(); - ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard; - } - } - } -} - -TYPED_TEST(RandenEngineTypedTest, StreamOperatorsResult) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - std::wostringstream os; - std::wistringstream is; - randen engine; - - EXPECT_EQ(&(os << engine), &os); - EXPECT_EQ(&(is >> engine), &is); -} - -TYPED_TEST(RandenEngineTypedTest, StreamSerialization) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - - for (size_t discard = 0; discard < kTwoBufferValues; ++discard) { - ExplicitSeedSeq seed_sequence{12, 34, 56}; - randen engine(seed_sequence); - engine.discard(discard); - - std::stringstream stream; - stream << engine; - - randen new_engine; - stream >> new_engine; - for (size_t i = 0; i < 64; ++i) { - EXPECT_EQ(engine(), new_engine()) << " " << i; - } - } -} - -constexpr size_t kNumGoldenOutputs = 127; - -// This test is checking if randen_engine is meets interface requirements -// defined in [rand.req.urbg]. -TYPED_TEST(RandenEngineTypedTest, RandomNumberEngineInterface) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - - using E = randen; - using T = typename E::result_type; - - static_assert(std::is_copy_constructible<E>::value, - "randen_engine must be copy constructible"); - - static_assert(absl::is_copy_assignable<E>::value, - "randen_engine must be copy assignable"); - - static_assert(std::is_move_constructible<E>::value, - "randen_engine must be move constructible"); - - static_assert(absl::is_move_assignable<E>::value, - "randen_engine must be move assignable"); - - static_assert(std::is_same<decltype(std::declval<E>()()), T>::value, - "return type of operator() must be result_type"); - - // Names after definition of [rand.req.urbg] in C++ standard. - // e us a value of E - // v is a lvalue of E - // x, y are possibly const values of E - // s is a value of T - // q is a value satisfying requirements of seed_sequence - // z is a value of type unsigned long long - // os is a some specialization of basic_ostream - // is is a some specialization of basic_istream - - E e, v; - const E x, y; - T s = 1; - std::seed_seq q{1, 2, 3}; - unsigned long long z = 1; // NOLINT(runtime/int) - std::wostringstream os; - std::wistringstream is; - - E{}; - E{x}; - E{s}; - E{q}; - - e.seed(); - - // MSVC emits error 2718 when using EXPECT_EQ(e, x) - // * actual parameter with __declspec(align('#')) won't be aligned - EXPECT_TRUE(e == x); - - e.seed(q); - { - E tmp(q); - EXPECT_TRUE(e == tmp); - } - - e(); - { - E tmp(q); - EXPECT_TRUE(e != tmp); - } - - e.discard(z); - - static_assert(std::is_same<decltype(x == y), bool>::value, - "return type of operator== must be bool"); - - static_assert(std::is_same<decltype(x != y), bool>::value, - "return type of operator== must be bool"); -} - -TYPED_TEST(RandenEngineTypedTest, RandenEngineSFINAETest) { - using randen = typename absl::random_internal::randen_engine<TypeParam>; - using result_type = typename randen::result_type; - - { - randen engine(result_type(1)); - engine.seed(result_type(1)); - } - - { - result_type n = 1; - randen engine(n); - engine.seed(n); - } - - { - randen engine(1); - engine.seed(1); - } - - { - int n = 1; - randen engine(n); - engine.seed(n); - } - - { - std::seed_seq seed_seq; - randen engine(seed_seq); - engine.seed(seed_seq); - } - - { - randen engine{std::seed_seq()}; - engine.seed(std::seed_seq()); - } -} - -TEST(RandenTest, VerifyGoldenRanden64Default) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0xc3c14f134e433977, 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, - 0xf0b780f545c72912, 0x15dbb1d37696599f, 0x30ec63baff3c6d59, - 0xb29f73606f7f20a6, 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, - 0x9cbf605e3fd9de8a, 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, - 0xf4b327fe0fc73c37, 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, - 0xd5af05dd3eff9556, 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, - 0x58d3575834956d42, 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, - 0x497cabf3431154fc, 0x4e24370570029a8b, 0xd88b5749f090e5ea, - 0xc651a582a970692f, 0x78fcec2cbb6342f5, 0x463cb745612f55db, - 0x352ee4ad1816afe3, 0x026ff374c101da7e, 0x811ef0821c3de851, - 0x6f7e616704c4fa59, 0xa0660379992d58fc, 0x04b0a374a3b795c7, - 0x915f3445685da798, 0x26802a8ac76571ce, 0x4663352533ce1882, - 0xb9fdefb4a24dc738, 0x5588ba3a4d6e6c51, 0xa2101a42d35f1956, - 0x607195a5e200f5fd, 0x7e100308f3290764, 0xe1e5e03c759c0709, - 0x082572cc5da6606f, 0xcbcf585399e432f1, 0xe8a2be4f8335d8f1, - 0x0904469acbfee8f2, 0xf08bd31b6daecd51, 0x08e8a1f1a69da69a, - 0x6542a20aad57bff5, 0x2e9705bb053d6b46, 0xda2fc9db0713c391, - 0x78e3a810213b6ffb, 0xdc16a59cdd85f8a6, 0xc0932718cd55781f, - 0xb9bfb29c2b20bfe5, 0xb97289c1be0f2f9c, 0xc0a2a0e403a892d4, - 0x5524bb834771435b, 0x8265da3d39d1a750, 0xff4af3ab8d1b78c5, - 0xf0ec5f424bcad77f, 0x66e455f627495189, 0xc82d3120b57e3270, - 0x3424e47dc22596e3, 0xbc0c95129ccedcdd, 0xc191c595afc4dcbf, - 0x120392bd2bb70939, 0x7f90650ea6cd6ab4, 0x7287491832695ad3, - 0xa7c8fac5a7917eb0, 0xd088cb9418be0361, 0x7c1bf9839c7c1ce5, - 0xe2e991fa58e1e79e, 0x78565cdefd28c4ad, 0x7351b9fef98bafad, - 0x2a9eac28b08c96bf, 0x6c4f179696cb2225, 0x13a685861bab87e0, - 0x64c6de5aa0501971, 0x30537425cac70991, 0x01590d9dc6c532b7, - 0x7e05e3aa8ec720dc, 0x74a07d9c54e3e63f, 0x738184388f3bc1d2, - 0x26ffdc5067be3acb, 0x6bcdf185561f255f, 0xa0eaf2e1cf99b1c6, - 0x171df81934f68604, 0x7ea5a21665683e5a, 0x5d1cb02075ba1cea, - 0x957f38cbd2123fdf, 0xba6364eff80de02f, 0x606e0a0e41d452ee, - 0x892d8317de82f7a2, 0xe707b1db50f7b43e, 0x4eb28826766fcf5b, - 0x5a362d56e80a0951, 0x6ee217df16527d78, 0xf6737962ba6b23dd, - 0x443e63857d4076ca, 0x790d9a5f048adfeb, 0xd796b052151ee94d, - 0x033ed95c12b04a03, 0x8b833ff84893da5d, 0x3d6724b1bb15eab9, - 0x9877c4225061ca76, 0xd68d6810adf74fb3, 0x42e5352fe30ce989, - 0x265b565a7431fde7, 0x3cdbf7e358df4b8b, 0x2922a47f6d3e8779, - 0x52d2242f65b37f88, 0x5d836d6e2958d6b5, 0x29d40f00566d5e26, - 0x288db0e1124b14a0, 0x6c056608b7d9c1b6, 0x0b9471bdb8f19d32, - 0x8fb946504faa6c9d, 0x8943a9464540251c, 0xfd1fe27d144a09e0, - 0xea6ac458da141bda, 0x8048f217633fce36, 0xfeda1384ade74d31, - 0x4334b8b02ff7612f, 0xdbc8441f5227e216, 0x096d119a3605c85b, - 0x2b72b31c21b7d7d0}; - - randen_u64 engine; -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(RandenTest, VerifyGoldenRanden64Seeded) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0x83a9e58f94d3dcd5, 0x70bbdff3d97949fb, 0x0438481f7471c1b4, - 0x34fdc58ee5fb5930, 0xceee4f2d2a937d17, 0xb5a26a68e432aea9, - 0x8b64774a3fb51740, 0xd89ac1fc74249c74, 0x03910d1d23fc3fdf, - 0xd38f630878aa897f, 0x0ee8f0f5615f7e44, 0x98f5a53df8279d52, - 0xb403f52c25938d0e, 0x240072996ea6e838, 0xd3a791246190fa61, - 0xaaedd3df7a7b4f80, 0xc6eacabe05deaf6e, 0xb7967dd8790edf4d, - 0x9a0a8e67e049d279, 0x0494f606aebc23e7, 0x598dcd687bc3e0ee, - 0x010ac81802d452a1, 0x6407c87160aa2842, 0x5a56e276486f93a0, - 0xc887a399d46a8f02, 0x9e1e6100fe93b740, 0x12d02e330f8901f6, - 0xc39ca52b47e790b7, 0xb0b0a2fa11e82e61, 0x1542d841a303806a, - 0x1fe659fd7d6e9d86, 0xb8c90d80746541ac, 0x239d56a5669ddc94, - 0xd40db57c8123d13c, 0x3abc2414153a0db0, 0x9bad665630cb8d61, - 0x0bd1fb90ee3f4bbc, 0x8f0b4d7e079b4e42, 0xfa0fb0e0ee59e793, - 0x51080b283e071100, 0x2c4b9e715081cc15, 0xbe10ed49de4941df, - 0xf8eaac9d4b1b0d37, 0x4bcce4b54605e139, 0xa64722b76765dda6, - 0xb9377d738ca28ab5, 0x779fad81a8ccc1af, 0x65cb3ee61ffd3ba7, - 0xd74e79087862836f, 0xd05b9c584c3f25bf, 0x2ba93a4693579827, - 0xd81530aff05420ce, 0xec06cea215478621, 0x4b1798a6796d65ad, - 0xf142f3fb3a6f6fa6, 0x002b7bf7e237b560, 0xf47f2605ef65b4f8, - 0x9804ec5517effc18, 0xaed3d7f8b7d481cd, 0x5651c24c1ce338d1, - 0x3e7a38208bf0a3c6, 0x6796a7b614534aed, 0x0d0f3b848358460f, - 0x0fa5fe7600b19524, 0x2b0cf38253faaedc, 0x10df9188233a9fd6, - 0x3a10033880138b59, 0x5fb0b0d23948e80f, 0x9e76f7b02fbf5350, - 0x0816052304b1a985, 0x30c9880db41fd218, 0x14aa399b65e20f28, - 0xe1454a8cace787b4, 0x325ac971b6c6f0f5, 0x716b1aa2784f3d36, - 0x3d5ce14accfd144f, 0x6c0c97710f651792, 0xbc5b0f59fb333532, - 0x2a90a7d2140470bc, 0x8da269f55c1e1c8d, 0xcfc37143895792ca, - 0xbe21eab1f30b238f, 0x8c47229dee4d65fd, 0x5743614ed1ed7d54, - 0x351372a99e9c476e, 0x2bd5ea15e5db085f, 0x6925fde46e0af4ca, - 0xed3eda2bdc1f45bd, 0xdef68c68d460fa6e, 0xe42a0de76253e2b5, - 0x4e5176dcbc29c305, 0xbfd85fba9f810f6e, 0x76a5a2a9beb815c6, - 0x01edc4ddceaf414c, 0xa4e98904b4bb3b4b, 0x00bd63ac7d2f1ddd, - 0xb8491fe6e998ddbb, 0xb386a3463dda6800, 0x0081887688871619, - 0x33d394b3344e9a38, 0x815dba65a3a8baf9, 0x4232f6ec02c2fd1a, - 0xb5cff603edd20834, 0x580189243f687663, 0xa8d5a2cbdc27fe99, - 0x725d881693fa0131, 0xa2be2c13db2c7ac5, 0x7b6a9614b509fd78, - 0xb6b136d71e717636, 0x660f1a71aff046ea, 0x0ba10ae346c8ec9e, - 0xe66dde53e3145b41, 0x3b18288c88c26be6, 0x4d9d9d2ff02db933, - 0x4167da8c70f46e8a, 0xf183beef8c6318b4, 0x4d889e1e71eeeef1, - 0x7175c71ad6689b6b, 0xfb9e42beacd1b7dd, 0xc33d0e91b29b5e0d, - 0xd39b83291ce47922, 0xc4d570fb8493d12e, 0x23d5a5724f424ae6, - 0x5245f161876b6616, 0x38d77dbd21ab578d, 0x9c3423311f4ecbfe, - 0x76fe31389bacd9d5, - }; - - ExplicitSeedSeq seed_sequence{12, 34, 56}; - randen_u64 engine(seed_sequence); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(seed_sequence); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(RandenTest, VerifyGoldenRanden32Default) { - constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = { - 0x4e433977, 0xc3c14f13, 0xd90410ee, 0xdda9f47c, 0x7fd8ca10, 0x887bf308, - 0x45c72912, 0xf0b780f5, 0x7696599f, 0x15dbb1d3, 0xff3c6d59, 0x30ec63ba, - 0x6f7f20a6, 0xb29f7360, 0x6f49a54c, 0x02808a31, 0xd5c8e50e, 0x3b8feaf9, - 0x3fd9de8a, 0x9cbf605e, 0x78183bbb, 0xc970ae1a, 0x56301ed5, 0xd8b2ffd3, - 0x0fc73c37, 0xf4b327fe, 0xeb8f9a19, 0xcdfd8d76, 0x91420c9d, 0xc3a506eb, - 0x3eff9556, 0xd5af05dd, 0x8f83c4a1, 0x48db1bb7, 0x0d6bfe8c, 0x7023920e, - 0x34956d42, 0x58d35758, 0x6b87b840, 0xed1ef4c2, 0x3e0b2df3, 0x8eef32a2, - 0x431154fc, 0x497cabf3, 0x70029a8b, 0x4e243705, 0xf090e5ea, 0xd88b5749, - 0xa970692f, 0xc651a582, 0xbb6342f5, 0x78fcec2c, 0x612f55db, 0x463cb745, - 0x1816afe3, 0x352ee4ad, 0xc101da7e, 0x026ff374, 0x1c3de851, 0x811ef082, - 0x04c4fa59, 0x6f7e6167, 0x992d58fc, 0xa0660379, 0xa3b795c7, 0x04b0a374, - 0x685da798, 0x915f3445, 0xc76571ce, 0x26802a8a, 0x33ce1882, 0x46633525, - 0xa24dc738, 0xb9fdefb4, 0x4d6e6c51, 0x5588ba3a, 0xd35f1956, 0xa2101a42, - 0xe200f5fd, 0x607195a5, 0xf3290764, 0x7e100308, 0x759c0709, 0xe1e5e03c, - 0x5da6606f, 0x082572cc, 0x99e432f1, 0xcbcf5853, 0x8335d8f1, 0xe8a2be4f, - 0xcbfee8f2, 0x0904469a, 0x6daecd51, 0xf08bd31b, 0xa69da69a, 0x08e8a1f1, - 0xad57bff5, 0x6542a20a, 0x053d6b46, 0x2e9705bb, 0x0713c391, 0xda2fc9db, - 0x213b6ffb, 0x78e3a810, 0xdd85f8a6, 0xdc16a59c, 0xcd55781f, 0xc0932718, - 0x2b20bfe5, 0xb9bfb29c, 0xbe0f2f9c, 0xb97289c1, 0x03a892d4, 0xc0a2a0e4, - 0x4771435b, 0x5524bb83, 0x39d1a750, 0x8265da3d, 0x8d1b78c5, 0xff4af3ab, - 0x4bcad77f, 0xf0ec5f42, 0x27495189, 0x66e455f6, 0xb57e3270, 0xc82d3120, - 0xc22596e3, 0x3424e47d, 0x9ccedcdd, 0xbc0c9512, 0xafc4dcbf, 0xc191c595, - 0x2bb70939, 0x120392bd, 0xa6cd6ab4, 0x7f90650e, 0x32695ad3, 0x72874918, - 0xa7917eb0, 0xa7c8fac5, 0x18be0361, 0xd088cb94, 0x9c7c1ce5, 0x7c1bf983, - 0x58e1e79e, 0xe2e991fa, 0xfd28c4ad, 0x78565cde, 0xf98bafad, 0x7351b9fe, - 0xb08c96bf, 0x2a9eac28, 0x96cb2225, 0x6c4f1796, 0x1bab87e0, 0x13a68586, - 0xa0501971, 0x64c6de5a, 0xcac70991, 0x30537425, 0xc6c532b7, 0x01590d9d, - 0x8ec720dc, 0x7e05e3aa, 0x54e3e63f, 0x74a07d9c, 0x8f3bc1d2, 0x73818438, - 0x67be3acb, 0x26ffdc50, 0x561f255f, 0x6bcdf185, 0xcf99b1c6, 0xa0eaf2e1, - 0x34f68604, 0x171df819, 0x65683e5a, 0x7ea5a216, 0x75ba1cea, 0x5d1cb020, - 0xd2123fdf, 0x957f38cb, 0xf80de02f, 0xba6364ef, 0x41d452ee, 0x606e0a0e, - 0xde82f7a2, 0x892d8317, 0x50f7b43e, 0xe707b1db, 0x766fcf5b, 0x4eb28826, - 0xe80a0951, 0x5a362d56, 0x16527d78, 0x6ee217df, 0xba6b23dd, 0xf6737962, - 0x7d4076ca, 0x443e6385, 0x048adfeb, 0x790d9a5f, 0x151ee94d, 0xd796b052, - 0x12b04a03, 0x033ed95c, 0x4893da5d, 0x8b833ff8, 0xbb15eab9, 0x3d6724b1, - 0x5061ca76, 0x9877c422, 0xadf74fb3, 0xd68d6810, 0xe30ce989, 0x42e5352f, - 0x7431fde7, 0x265b565a, 0x58df4b8b, 0x3cdbf7e3, 0x6d3e8779, 0x2922a47f, - 0x65b37f88, 0x52d2242f, 0x2958d6b5, 0x5d836d6e, 0x566d5e26, 0x29d40f00, - 0x124b14a0, 0x288db0e1, 0xb7d9c1b6, 0x6c056608, 0xb8f19d32, 0x0b9471bd, - 0x4faa6c9d, 0x8fb94650, 0x4540251c, 0x8943a946, 0x144a09e0, 0xfd1fe27d, - 0xda141bda, 0xea6ac458, 0x633fce36, 0x8048f217, 0xade74d31, 0xfeda1384, - 0x2ff7612f, 0x4334b8b0, 0x5227e216, 0xdbc8441f, 0x3605c85b, 0x096d119a, - 0x21b7d7d0, 0x2b72b31c}; - - randen_u32 engine; -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) { - printf("0x%08x, ", engine()); - if (i % 6 == 5) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(RandenTest, VerifyGoldenRanden32Seeded) { - constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = { - 0x94d3dcd5, 0x83a9e58f, 0xd97949fb, 0x70bbdff3, 0x7471c1b4, 0x0438481f, - 0xe5fb5930, 0x34fdc58e, 0x2a937d17, 0xceee4f2d, 0xe432aea9, 0xb5a26a68, - 0x3fb51740, 0x8b64774a, 0x74249c74, 0xd89ac1fc, 0x23fc3fdf, 0x03910d1d, - 0x78aa897f, 0xd38f6308, 0x615f7e44, 0x0ee8f0f5, 0xf8279d52, 0x98f5a53d, - 0x25938d0e, 0xb403f52c, 0x6ea6e838, 0x24007299, 0x6190fa61, 0xd3a79124, - 0x7a7b4f80, 0xaaedd3df, 0x05deaf6e, 0xc6eacabe, 0x790edf4d, 0xb7967dd8, - 0xe049d279, 0x9a0a8e67, 0xaebc23e7, 0x0494f606, 0x7bc3e0ee, 0x598dcd68, - 0x02d452a1, 0x010ac818, 0x60aa2842, 0x6407c871, 0x486f93a0, 0x5a56e276, - 0xd46a8f02, 0xc887a399, 0xfe93b740, 0x9e1e6100, 0x0f8901f6, 0x12d02e33, - 0x47e790b7, 0xc39ca52b, 0x11e82e61, 0xb0b0a2fa, 0xa303806a, 0x1542d841, - 0x7d6e9d86, 0x1fe659fd, 0x746541ac, 0xb8c90d80, 0x669ddc94, 0x239d56a5, - 0x8123d13c, 0xd40db57c, 0x153a0db0, 0x3abc2414, 0x30cb8d61, 0x9bad6656, - 0xee3f4bbc, 0x0bd1fb90, 0x079b4e42, 0x8f0b4d7e, 0xee59e793, 0xfa0fb0e0, - 0x3e071100, 0x51080b28, 0x5081cc15, 0x2c4b9e71, 0xde4941df, 0xbe10ed49, - 0x4b1b0d37, 0xf8eaac9d, 0x4605e139, 0x4bcce4b5, 0x6765dda6, 0xa64722b7, - 0x8ca28ab5, 0xb9377d73, 0xa8ccc1af, 0x779fad81, 0x1ffd3ba7, 0x65cb3ee6, - 0x7862836f, 0xd74e7908, 0x4c3f25bf, 0xd05b9c58, 0x93579827, 0x2ba93a46, - 0xf05420ce, 0xd81530af, 0x15478621, 0xec06cea2, 0x796d65ad, 0x4b1798a6, - 0x3a6f6fa6, 0xf142f3fb, 0xe237b560, 0x002b7bf7, 0xef65b4f8, 0xf47f2605, - 0x17effc18, 0x9804ec55, 0xb7d481cd, 0xaed3d7f8, 0x1ce338d1, 0x5651c24c, - 0x8bf0a3c6, 0x3e7a3820, 0x14534aed, 0x6796a7b6, 0x8358460f, 0x0d0f3b84, - 0x00b19524, 0x0fa5fe76, 0x53faaedc, 0x2b0cf382, 0x233a9fd6, 0x10df9188, - 0x80138b59, 0x3a100338, 0x3948e80f, 0x5fb0b0d2, 0x2fbf5350, 0x9e76f7b0, - 0x04b1a985, 0x08160523, 0xb41fd218, 0x30c9880d, 0x65e20f28, 0x14aa399b, - 0xace787b4, 0xe1454a8c, 0xb6c6f0f5, 0x325ac971, 0x784f3d36, 0x716b1aa2, - 0xccfd144f, 0x3d5ce14a, 0x0f651792, 0x6c0c9771, 0xfb333532, 0xbc5b0f59, - 0x140470bc, 0x2a90a7d2, 0x5c1e1c8d, 0x8da269f5, 0x895792ca, 0xcfc37143, - 0xf30b238f, 0xbe21eab1, 0xee4d65fd, 0x8c47229d, 0xd1ed7d54, 0x5743614e, - 0x9e9c476e, 0x351372a9, 0xe5db085f, 0x2bd5ea15, 0x6e0af4ca, 0x6925fde4, - 0xdc1f45bd, 0xed3eda2b, 0xd460fa6e, 0xdef68c68, 0x6253e2b5, 0xe42a0de7, - 0xbc29c305, 0x4e5176dc, 0x9f810f6e, 0xbfd85fba, 0xbeb815c6, 0x76a5a2a9, - 0xceaf414c, 0x01edc4dd, 0xb4bb3b4b, 0xa4e98904, 0x7d2f1ddd, 0x00bd63ac, - 0xe998ddbb, 0xb8491fe6, 0x3dda6800, 0xb386a346, 0x88871619, 0x00818876, - 0x344e9a38, 0x33d394b3, 0xa3a8baf9, 0x815dba65, 0x02c2fd1a, 0x4232f6ec, - 0xedd20834, 0xb5cff603, 0x3f687663, 0x58018924, 0xdc27fe99, 0xa8d5a2cb, - 0x93fa0131, 0x725d8816, 0xdb2c7ac5, 0xa2be2c13, 0xb509fd78, 0x7b6a9614, - 0x1e717636, 0xb6b136d7, 0xaff046ea, 0x660f1a71, 0x46c8ec9e, 0x0ba10ae3, - 0xe3145b41, 0xe66dde53, 0x88c26be6, 0x3b18288c, 0xf02db933, 0x4d9d9d2f, - 0x70f46e8a, 0x4167da8c, 0x8c6318b4, 0xf183beef, 0x71eeeef1, 0x4d889e1e, - 0xd6689b6b, 0x7175c71a, 0xacd1b7dd, 0xfb9e42be, 0xb29b5e0d, 0xc33d0e91, - 0x1ce47922, 0xd39b8329, 0x8493d12e, 0xc4d570fb, 0x4f424ae6, 0x23d5a572, - 0x876b6616, 0x5245f161, 0x21ab578d, 0x38d77dbd, 0x1f4ecbfe, 0x9c342331, - 0x9bacd9d5, 0x76fe3138, - }; - - ExplicitSeedSeq seed_sequence{12, 34, 56}; - randen_u32 engine(seed_sequence); -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) { - printf("0x%08x, ", engine()); - if (i % 6 == 5) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } - engine.seed(seed_sequence); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(RandenTest, VerifyGoldenFromDeserializedEngine) { - constexpr uint64_t kGolden[kNumGoldenOutputs] = { - 0x067f9f9ab919657a, 0x0534605912988583, 0x8a303f72feaa673f, - 0x77b7fd747909185c, 0xd9af90403c56d891, 0xd939c6cb204d14b5, - 0x7fbe6b954a47b483, 0x8b31a47cc34c768d, 0x3a9e546da2701a9c, - 0x5246539046253e71, 0x417191ffb2a848a1, 0x7b1c7bf5a5001d09, - 0x9489b15d194f2361, 0xfcebdeea3bcd2461, 0xd643027c854cec97, - 0x5885397f91e0d21c, 0x53173b0efae30d58, 0x1c9c71168449fac1, - 0xe358202b711ed8aa, 0x94e3918ed1d8227c, 0x5bb4e251450144cf, - 0xb5c7a519b489af3b, 0x6f8b560b1f7b3469, 0xfde11dd4a1c74eef, - 0x33383d2f76457dcf, 0x3060c0ec6db9fce1, 0x18f451fcddeec766, - 0xe73c5d6b9f26da2a, 0x8d4cc566671b32a4, 0xb8189b73776bc9ff, - 0x497a70f9caf0bc23, 0x23afcc509791dcea, 0x18af70dc4b27d306, - 0xd3853f955a0ce5b9, 0x441db6c01a0afb17, 0xd0136c3fb8e1f13f, - 0x5e4fd6fc2f33783c, 0xe0d24548adb5da51, 0x0f4d8362a7d3485a, - 0x9f572d68270fa563, 0x6351fbc823024393, 0xa66dbfc61810e9ab, - 0x0ff17fc14b651af8, 0xd74c55dafb99e623, 0x36303bc1ad85c6c2, - 0x4920cd6a2af7e897, 0x0b8848addc30fecd, 0x9e1562eda6488e93, - 0x197553807d607828, 0xbef5eaeda5e21235, 0x18d91d2616aca527, - 0xb7821937f5c873cd, 0x2cd4ae5650dbeefc, 0xb35a64376f75ffdf, - 0x9226d414d647fe07, 0x663f3db455bbb35e, 0xa829eead6ae93247, - 0x7fd69c204dd0d25f, 0xbe1411f891c9acb1, 0xd476f34a506d5f11, - 0xf423d2831649c5ca, 0x1e503962951abd75, 0xeccc9e8b1e34b537, - 0xb11a147294044854, 0xc4cf27f0abf4929d, 0xe9193abf6fa24c8c, - 0xa94a259e3aba8808, 0x21dc414197deffa3, 0xa2ae211d1ff622ae, - 0xfe3995c46be5a4f4, 0xe9984c284bf11128, 0xcb1ce9d2f0851a80, - 0x42fee17971d87cd8, 0xac76a98d177adc88, 0xa0973b3dedc4af6f, - 0xdf56d6bbcb1b8e86, 0xf1e6485f407b11c9, 0x2c63de4deccb15c0, - 0x6fe69db32ed4fad7, 0xaa51a65f84bca1f1, 0x242f2ee81d608afc, - 0x8eb88b2b69fc153b, 0x22c20098baf73fd1, 0x57759466f576488c, - 0x075ca562cea1be9d, 0x9a74814d73d28891, 0x73d1555fc02f4d3d, - 0xc17f8f210ee89337, 0x46cca7999eaeafd4, 0x5db8d6a327a0d8ac, - 0xb79b4f93c738d7a1, 0x9994512f0036ded1, 0xd3883026f38747f4, - 0xf31f7458078d097c, 0x736ce4d480680669, 0x7a496f4c7e1033e3, - 0xecf85bf297fbc68c, 0x9e37e1d0f24f3c4e, 0x15b6e067ca0746fc, - 0xdd4a39905c5db81c, 0xb5dfafa7bcfdf7da, 0xca6646fb6f92a276, - 0x1c6b35f363ef0efd, 0x6a33d06037ad9f76, 0x45544241afd8f80f, - 0x83f8d83f859c90c5, 0x22aea9c5365e8c19, 0xfac35b11f20b6a6a, - 0xd1acf49d1a27dd2f, 0xf281cd09c4fed405, 0x076000a42cd38e4f, - 0x6ace300565070445, 0x463a62781bddc4db, 0x1477126b46b569ac, - 0x127f2bb15035fbb8, 0xdfa30946049c04a8, 0x89072a586ba8dd3e, - 0x62c809582bb7e74d, 0x22c0c3641406c28b, 0x9b66e36c47ff004d, - 0xb9cd2c7519653330, 0x18608d79cd7a598d, 0x92c0bd1323e53e32, - 0x887ff00de8524aa5, 0xa074410b787abd10, 0x18ab41b8057a2063, - 0x1560abf26bc5f987}; - -#if UPDATE_GOLDEN - (void)kGolden; // Silence warning. - std::seed_seq seed_sequence{1, 2, 3, 4, 5}; - randen_u64 engine(seed_sequence); - std::ostringstream stream; - stream << engine; - auto str = stream.str(); - printf("%s\n\n", str.c_str()); - for (size_t i = 0; i < kNumGoldenOutputs; ++i) { - printf("0x%016lx, ", engine()); - if (i % 3 == 2) { - printf("\n"); - } - } - printf("\n\n\n"); -#else - randen_u64 engine; - std::istringstream stream( - "0 0 9824501439887287479 3242284395352394785 243836530774933777 " - "4047941804708365596 17165468127298385802 949276103645889255 " - "10659970394998657921 1657570836810929787 11697746266668051452 " - "9967209969299905230 14140390331161524430 7383014124183271684 " - "13146719127702337852 13983155220295807171 11121125587542359264 " - "195757810993252695 17138580243103178492 11326030747260920501 " - "8585097322474965590 18342582839328350995 15052982824209724634 " - "7321861343874683609 1806786911778767826 10100850842665572955 " - "9249328950653985078 13600624835326909759 11137960060943860251 " - "10208781341792329629 9282723971471525577 16373271619486811032 32"); - stream >> engine; - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, engine()); - } -#endif -} - -TEST(RandenTest, IsFastOrSlow) { - // randen_engine typically costs ~5ns per value for the optimized code paths, - // and the ~1000ns per value for slow code paths. However when running under - // msan, asan, etc. it can take much longer. - // - // The estimated operation time is something like: - // - // linux, optimized ~5ns - // ppc, optimized ~7ns - // nacl (slow), ~1100ns - // - // `kCount` is chosen below so that, in debug builds and without hardware - // acceleration, the test (assuming ~1us per call) should finish in ~0.1s - static constexpr size_t kCount = 100000; - randen_u64 engine; - randen_u64::result_type sum = 0; - auto start = absl::GetCurrentTimeNanos(); - for (int i = 0; i < kCount; i++) { - sum += engine(); - } - auto duration = absl::GetCurrentTimeNanos() - start; - - ABSL_INTERNAL_LOG(INFO, absl::StrCat(static_cast<double>(duration) / - static_cast<double>(kCount), - "ns")); - - EXPECT_GT(sum, 0); - EXPECT_GE(duration, kCount); // Should be slower than 1ns per call. -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/randen_hwaes.cc b/third_party/abseil_cpp/absl/random/internal/randen_hwaes.cc deleted file mode 100644 index b5a3f90aee63..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_hwaes.cc +++ /dev/null @@ -1,573 +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. - -// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate -// symbols from arbitrary system and other headers, since it may be built -// with different flags from other targets, using different levels of -// optimization, potentially introducing ODR violations. - -#include "absl/random/internal/randen_hwaes.h" - -#include <cstdint> -#include <cstring> - -#include "absl/base/attributes.h" -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_traits.h" - -// ABSL_RANDEN_HWAES_IMPL indicates whether this file will contain -// a hardware accelerated implementation of randen, or whether it -// will contain stubs that exit the process. -#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) -// The platform.h directives are sufficient to indicate whether -// we should build accelerated implementations for x86. -#if (ABSL_HAVE_ACCELERATED_AES || ABSL_RANDOM_INTERNAL_AES_DISPATCH) -#define ABSL_RANDEN_HWAES_IMPL 1 -#endif -#elif defined(ABSL_ARCH_PPC) -// The platform.h directives are sufficient to indicate whether -// we should build accelerated implementations for PPC. -// -// NOTE: This has mostly been tested on 64-bit Power variants, -// and not embedded cpus such as powerpc32-8540 -#if ABSL_HAVE_ACCELERATED_AES -#define ABSL_RANDEN_HWAES_IMPL 1 -#endif -#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64) -// ARM is somewhat more complicated. We might support crypto natively... -#if ABSL_HAVE_ACCELERATED_AES || \ - (defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)) -#define ABSL_RANDEN_HWAES_IMPL 1 - -#elif ABSL_RANDOM_INTERNAL_AES_DISPATCH && !defined(__APPLE__) && \ - (defined(__GNUC__) && __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 9) -// ...or, on GCC, we can use an ASM directive to -// instruct the assember to allow crypto instructions. -#define ABSL_RANDEN_HWAES_IMPL 1 -#define ABSL_RANDEN_HWAES_IMPL_CRYPTO_DIRECTIVE 1 -#endif -#else -// HWAES is unsupported by these architectures / platforms: -// __myriad2__ -// __mips__ -// -// Other architectures / platforms are unknown. -// -// See the Abseil documentation on supported macros at: -// https://abseil.io/docs/cpp/platforms/macros -#endif - -#if !defined(ABSL_RANDEN_HWAES_IMPL) -// No accelerated implementation is supported. -// The RandenHwAes functions are stubs that print an error and exit. - -#include <cstdio> -#include <cstdlib> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// No accelerated implementation. -bool HasRandenHwAesImplementation() { return false; } - -// NOLINTNEXTLINE -const void* RandenHwAes::GetKeys() { - // Attempted to dispatch to an unsupported dispatch target. - const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH; - fprintf(stderr, "AES Hardware detection failed (%d).\n", d); - exit(1); - return nullptr; -} - -// NOLINTNEXTLINE -void RandenHwAes::Absorb(const void*, void*) { - // Attempted to dispatch to an unsupported dispatch target. - const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH; - fprintf(stderr, "AES Hardware detection failed (%d).\n", d); - exit(1); -} - -// NOLINTNEXTLINE -void RandenHwAes::Generate(const void*, void*) { - // Attempted to dispatch to an unsupported dispatch target. - const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH; - fprintf(stderr, "AES Hardware detection failed (%d).\n", d); - exit(1); -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#else // defined(ABSL_RANDEN_HWAES_IMPL) -// -// Accelerated implementations are supported. -// We need the per-architecture includes and defines. -// -namespace { - -using absl::random_internal::RandenTraits; - -// Randen operates on 128-bit vectors. -struct alignas(16) u64x2 { - uint64_t data[2]; -}; - -} // namespace - -// TARGET_CRYPTO defines a crypto attribute for each architecture. -// -// NOTE: Evaluate whether we should eliminate ABSL_TARGET_CRYPTO. -#if (defined(__clang__) || defined(__GNUC__)) -#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) -#define ABSL_TARGET_CRYPTO __attribute__((target("aes"))) -#elif defined(ABSL_ARCH_PPC) -#define ABSL_TARGET_CRYPTO __attribute__((target("crypto"))) -#else -#define ABSL_TARGET_CRYPTO -#endif -#else -#define ABSL_TARGET_CRYPTO -#endif - -#if defined(ABSL_ARCH_PPC) -// NOTE: Keep in mind that PPC can operate in little-endian or big-endian mode, -// however the PPC altivec vector registers (and thus the AES instructions) -// always operate in big-endian mode. - -#include <altivec.h> -// <altivec.h> #defines vector __vector; in C++, this is bad form. -#undef vector -#undef bool - -// Rely on the PowerPC AltiVec vector operations for accelerated AES -// instructions. GCC support of the PPC vector types is described in: -// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/PowerPC-AltiVec_002fVSX-Built-in-Functions.html -// -// Already provides operator^=. -using Vector128 = __vector unsigned long long; // NOLINT(runtime/int) - -namespace { -inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) { - // Reverses the bytes of the vector. - const __vector unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0}; - return vec_perm(v, v, perm); -} - -// WARNING: these load/store in native byte order. It is OK to load and then -// store an unchanged vector, but interpreting the bits as a number or input -// to AES will have undefined results. -inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) { - return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from)); -} - -inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) { - vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to)); -} - -// One round of AES. "round_key" is a public constant for breaking the -// symmetry of AES (ensures previously equal columns differ afterwards). -inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state, - const Vector128& round_key) { - return Vector128(__builtin_crypto_vcipher(state, round_key)); -} - -// Enables native loads in the round loop by pre-swapping. -inline ABSL_TARGET_CRYPTO void SwapEndian(u64x2* state) { - for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) { - Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block); - } -} - -} // namespace - -#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64) - -// This asm directive will cause the file to be compiled with crypto extensions -// whether or not the cpu-architecture supports it. -#if ABSL_RANDEN_HWAES_IMPL_CRYPTO_DIRECTIVE -asm(".arch_extension crypto\n"); - -// Override missing defines. -#if !defined(__ARM_NEON) -#define __ARM_NEON 1 -#endif - -#if !defined(__ARM_FEATURE_CRYPTO) -#define __ARM_FEATURE_CRYPTO 1 -#endif - -#endif - -// Rely on the ARM NEON+Crypto advanced simd types, defined in <arm_neon.h>. -// uint8x16_t is the user alias for underlying __simd128_uint8_t type. -// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf -// -// <arm_neon> defines the following -// -// typedef __attribute__((neon_vector_type(16))) uint8_t uint8x16_t; -// typedef __attribute__((neon_vector_type(16))) int8_t int8x16_t; -// typedef __attribute__((neon_polyvector_type(16))) int8_t poly8x16_t; -// -// vld1q_v -// vst1q_v -// vaeseq_v -// vaesmcq_v -#include <arm_neon.h> - -// Already provides operator^=. -using Vector128 = uint8x16_t; - -namespace { - -inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) { - return vld1q_u8(reinterpret_cast<const uint8_t*>(from)); -} - -inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) { - vst1q_u8(reinterpret_cast<uint8_t*>(to), v); -} - -// One round of AES. "round_key" is a public constant for breaking the -// symmetry of AES (ensures previously equal columns differ afterwards). -inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state, - const Vector128& round_key) { - // It is important to always use the full round function - omitting the - // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf] - // and does not help because we never decrypt. - // - // Note that ARM divides AES instructions differently than x86 / PPC, - // And we need to skip the first AddRoundKey step and add an extra - // AddRoundKey step to the end. Lucky for us this is just XOR. - return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key; -} - -inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {} - -} // namespace - -#elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) -// On x86 we rely on the aesni instructions -#include <wmmintrin.h> - -namespace { - -// Vector128 class is only wrapper for __m128i, benchmark indicates that it's -// faster than using __m128i directly. -class Vector128 { - public: - // Convert from/to intrinsics. - inline explicit Vector128(const __m128i& Vector128) : data_(Vector128) {} - - inline __m128i data() const { return data_; } - - inline Vector128& operator^=(const Vector128& other) { - data_ = _mm_xor_si128(data_, other.data()); - return *this; - } - - private: - __m128i data_; -}; - -inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) { - return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from))); -} - -inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) { - _mm_store_si128(reinterpret_cast<__m128i*>(to), v.data()); -} - -// One round of AES. "round_key" is a public constant for breaking the -// symmetry of AES (ensures previously equal columns differ afterwards). -inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state, - const Vector128& round_key) { - // It is important to always use the full round function - omitting the - // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf] - // and does not help because we never decrypt. - return Vector128(_mm_aesenc_si128(state.data(), round_key.data())); -} - -inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {} - -} // namespace - -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#endif - -// At this point, all of the platform-specific features have been defined / -// implemented. -// -// REQUIRES: using Vector128 = ... -// REQUIRES: Vector128 Vector128Load(void*) {...} -// REQUIRES: void Vector128Store(Vector128, void*) {...} -// REQUIRES: Vector128 AesRound(Vector128, Vector128) {...} -// REQUIRES: void SwapEndian(uint64_t*) {...} -// -// PROVIDES: absl::random_internal::RandenHwAes::Absorb -// PROVIDES: absl::random_internal::RandenHwAes::Generate -namespace { - -// Block shuffles applies a shuffle to the entire state between AES rounds. -// Improved odd-even shuffle from "New criterion for diffusion property". -inline ABSL_TARGET_CRYPTO void BlockShuffle(u64x2* state) { - static_assert(RandenTraits::kFeistelBlocks == 16, - "Expecting 16 FeistelBlocks."); - - constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = { - 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12}; - - const Vector128 v0 = Vector128Load(state + shuffle[0]); - const Vector128 v1 = Vector128Load(state + shuffle[1]); - const Vector128 v2 = Vector128Load(state + shuffle[2]); - const Vector128 v3 = Vector128Load(state + shuffle[3]); - const Vector128 v4 = Vector128Load(state + shuffle[4]); - const Vector128 v5 = Vector128Load(state + shuffle[5]); - const Vector128 v6 = Vector128Load(state + shuffle[6]); - const Vector128 v7 = Vector128Load(state + shuffle[7]); - const Vector128 w0 = Vector128Load(state + shuffle[8]); - const Vector128 w1 = Vector128Load(state + shuffle[9]); - const Vector128 w2 = Vector128Load(state + shuffle[10]); - const Vector128 w3 = Vector128Load(state + shuffle[11]); - const Vector128 w4 = Vector128Load(state + shuffle[12]); - const Vector128 w5 = Vector128Load(state + shuffle[13]); - const Vector128 w6 = Vector128Load(state + shuffle[14]); - const Vector128 w7 = Vector128Load(state + shuffle[15]); - - Vector128Store(v0, state + 0); - Vector128Store(v1, state + 1); - Vector128Store(v2, state + 2); - Vector128Store(v3, state + 3); - Vector128Store(v4, state + 4); - Vector128Store(v5, state + 5); - Vector128Store(v6, state + 6); - Vector128Store(v7, state + 7); - Vector128Store(w0, state + 8); - Vector128Store(w1, state + 9); - Vector128Store(w2, state + 10); - Vector128Store(w3, state + 11); - Vector128Store(w4, state + 12); - Vector128Store(w5, state + 13); - Vector128Store(w6, state + 14); - Vector128Store(w7, state + 15); -} - -// Feistel round function using two AES subrounds. Very similar to F() -// from Simpira v2, but with independent subround keys. Uses 17 AES rounds -// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in -// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel -// XORs are 'free' (included in the second AES instruction). -inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound( - u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) { - static_assert(RandenTraits::kFeistelBlocks == 16, - "Expecting 16 FeistelBlocks."); - - // MSVC does a horrible job at unrolling loops. - // So we unroll the loop by hand to improve the performance. - const Vector128 s0 = Vector128Load(state + 0); - const Vector128 s1 = Vector128Load(state + 1); - const Vector128 s2 = Vector128Load(state + 2); - const Vector128 s3 = Vector128Load(state + 3); - const Vector128 s4 = Vector128Load(state + 4); - const Vector128 s5 = Vector128Load(state + 5); - const Vector128 s6 = Vector128Load(state + 6); - const Vector128 s7 = Vector128Load(state + 7); - const Vector128 s8 = Vector128Load(state + 8); - const Vector128 s9 = Vector128Load(state + 9); - const Vector128 s10 = Vector128Load(state + 10); - const Vector128 s11 = Vector128Load(state + 11); - const Vector128 s12 = Vector128Load(state + 12); - const Vector128 s13 = Vector128Load(state + 13); - const Vector128 s14 = Vector128Load(state + 14); - const Vector128 s15 = Vector128Load(state + 15); - - // Encode even blocks with keys. - const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0)); - const Vector128 e2 = AesRound(s2, Vector128Load(keys + 1)); - const Vector128 e4 = AesRound(s4, Vector128Load(keys + 2)); - const Vector128 e6 = AesRound(s6, Vector128Load(keys + 3)); - const Vector128 e8 = AesRound(s8, Vector128Load(keys + 4)); - const Vector128 e10 = AesRound(s10, Vector128Load(keys + 5)); - const Vector128 e12 = AesRound(s12, Vector128Load(keys + 6)); - const Vector128 e14 = AesRound(s14, Vector128Load(keys + 7)); - - // Encode odd blocks with even output from above. - const Vector128 o1 = AesRound(e0, s1); - const Vector128 o3 = AesRound(e2, s3); - const Vector128 o5 = AesRound(e4, s5); - const Vector128 o7 = AesRound(e6, s7); - const Vector128 o9 = AesRound(e8, s9); - const Vector128 o11 = AesRound(e10, s11); - const Vector128 o13 = AesRound(e12, s13); - const Vector128 o15 = AesRound(e14, s15); - - // Store odd blocks. (These will be shuffled later). - Vector128Store(o1, state + 1); - Vector128Store(o3, state + 3); - Vector128Store(o5, state + 5); - Vector128Store(o7, state + 7); - Vector128Store(o9, state + 9); - Vector128Store(o11, state + 11); - Vector128Store(o13, state + 13); - Vector128Store(o15, state + 15); - - return keys + 8; -} - -// Cryptographic permutation based via type-2 Generalized Feistel Network. -// Indistinguishable from ideal by chosen-ciphertext adversaries using less than -// 2^64 queries if the round function is a PRF. This is similar to the b=8 case -// of Simpira v2, but more efficient than its generic construction for b=16. -inline ABSL_TARGET_CRYPTO void Permute( - u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) { - // (Successfully unrolled; the first iteration jumps into the second half) -#ifdef __clang__ -#pragma clang loop unroll_count(2) -#endif - for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) { - keys = FeistelRound(state, keys); - BlockShuffle(state); - } -} - -} // namespace - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -bool HasRandenHwAesImplementation() { return true; } - -const void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() { - // Round keys for one AES per Feistel round and branch. - // The canonical implementation uses first digits of Pi. -#if defined(ABSL_ARCH_PPC) - return kRandenRoundKeysBE; -#else - return kRandenRoundKeys; -#endif -} - -// NOLINTNEXTLINE -void ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void, - void* state_void) { - static_assert(RandenTraits::kCapacityBytes / sizeof(Vector128) == 1, - "Unexpected Randen kCapacityBlocks"); - static_assert(RandenTraits::kStateBytes / sizeof(Vector128) == 16, - "Unexpected Randen kStateBlocks"); - - auto* state = - reinterpret_cast<u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void); - const auto* seed = - reinterpret_cast<const u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(seed_void); - - Vector128 b1 = Vector128Load(state + 1); - b1 ^= Vector128Load(seed + 0); - Vector128Store(b1, state + 1); - - Vector128 b2 = Vector128Load(state + 2); - b2 ^= Vector128Load(seed + 1); - Vector128Store(b2, state + 2); - - Vector128 b3 = Vector128Load(state + 3); - b3 ^= Vector128Load(seed + 2); - Vector128Store(b3, state + 3); - - Vector128 b4 = Vector128Load(state + 4); - b4 ^= Vector128Load(seed + 3); - Vector128Store(b4, state + 4); - - Vector128 b5 = Vector128Load(state + 5); - b5 ^= Vector128Load(seed + 4); - Vector128Store(b5, state + 5); - - Vector128 b6 = Vector128Load(state + 6); - b6 ^= Vector128Load(seed + 5); - Vector128Store(b6, state + 6); - - Vector128 b7 = Vector128Load(state + 7); - b7 ^= Vector128Load(seed + 6); - Vector128Store(b7, state + 7); - - Vector128 b8 = Vector128Load(state + 8); - b8 ^= Vector128Load(seed + 7); - Vector128Store(b8, state + 8); - - Vector128 b9 = Vector128Load(state + 9); - b9 ^= Vector128Load(seed + 8); - Vector128Store(b9, state + 9); - - Vector128 b10 = Vector128Load(state + 10); - b10 ^= Vector128Load(seed + 9); - Vector128Store(b10, state + 10); - - Vector128 b11 = Vector128Load(state + 11); - b11 ^= Vector128Load(seed + 10); - Vector128Store(b11, state + 11); - - Vector128 b12 = Vector128Load(state + 12); - b12 ^= Vector128Load(seed + 11); - Vector128Store(b12, state + 12); - - Vector128 b13 = Vector128Load(state + 13); - b13 ^= Vector128Load(seed + 12); - Vector128Store(b13, state + 13); - - Vector128 b14 = Vector128Load(state + 14); - b14 ^= Vector128Load(seed + 13); - Vector128Store(b14, state + 14); - - Vector128 b15 = Vector128Load(state + 15); - b15 ^= Vector128Load(seed + 14); - Vector128Store(b15, state + 15); -} - -// NOLINTNEXTLINE -void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void, - void* state_void) { - static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128), - "Capacity mismatch"); - - auto* state = reinterpret_cast<u64x2*>(state_void); - const auto* keys = reinterpret_cast<const u64x2*>(keys_void); - - const Vector128 prev_inner = Vector128Load(state); - - SwapEndian(state); - - Permute(state, keys); - - SwapEndian(state); - - // Ensure backtracking resistance. - Vector128 inner = Vector128Load(state); - inner ^= prev_inner; - Vector128Store(inner, state); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // (ABSL_RANDEN_HWAES_IMPL) diff --git a/third_party/abseil_cpp/absl/random/internal/randen_hwaes.h b/third_party/abseil_cpp/absl/random/internal/randen_hwaes.h deleted file mode 100644 index bce36b522609..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_hwaes.h +++ /dev/null @@ -1,50 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ - -#include "absl/base/config.h" - -// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate -// symbols from arbitrary system and other headers, since it may be built -// with different flags from other targets, using different levels of -// optimization, potentially introducing ODR violations. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// RANDen = RANDom generator or beetroots in Swiss German. -// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random -// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32. -// -// RandenHwAes implements the basic state manipulation methods. -class RandenHwAes { - public: - static void Generate(const void* keys, void* state_void); - static void Absorb(const void* seed_void, void* state_void); - static const void* GetKeys(); -}; - -// HasRandenHwAesImplementation returns true when there is an accelerated -// implementation, and false otherwise. If there is no implementation, -// then attempting to use it will abort the program. -bool HasRandenHwAesImplementation(); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/randen_hwaes_test.cc b/third_party/abseil_cpp/absl/random/internal/randen_hwaes_test.cc deleted file mode 100644 index 66ddb43fd6a7..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_hwaes_test.cc +++ /dev/null @@ -1,104 +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_hwaes.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_detect.h" -#include "absl/random/internal/randen_traits.h" -#include "absl/strings/str_format.h" - -namespace { - -using absl::random_internal::RandenHwAes; -using absl::random_internal::RandenTraits; - -// Local state parameters. -constexpr size_t kSeedBytes = - RandenTraits::kStateBytes - RandenTraits::kCapacityBytes; -constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t); -constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t); - -struct alignas(16) randen { - uint64_t state[kStateSizeT]; - uint32_t seed[kSeedSizeT]; -}; - -TEST(RandenHwAesTest, Default) { - EXPECT_TRUE(absl::random_internal::CPUSupportsRandenHwAes()); - - constexpr uint64_t kGolden[] = { - 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977, - 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912, - 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6, - 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a, - 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37, - 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556, - 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42, - 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc, - 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f, - 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3, - 0x026ff374c101da7e, 0x811ef0821c3de851, - }; - - alignas(16) randen d; - memset(d.state, 0, sizeof(d.state)); - RandenHwAes::Generate(RandenHwAes::GetKeys(), d.state); - - uint64_t* id = d.state; - for (const auto& elem : kGolden) { - auto a = absl::StrFormat("%#x", elem); - auto b = absl::StrFormat("%#x", *id++); - EXPECT_EQ(a, b); - } -} - -} // namespace - -int main(int argc, char* argv[]) { - testing::InitGoogleTest(&argc, argv); - - ABSL_RAW_LOG(INFO, "ABSL_HAVE_ACCELERATED_AES=%d", ABSL_HAVE_ACCELERATED_AES); - ABSL_RAW_LOG(INFO, "ABSL_RANDOM_INTERNAL_AES_DISPATCH=%d", - ABSL_RANDOM_INTERNAL_AES_DISPATCH); - -#if defined(ABSL_ARCH_X86_64) - ABSL_RAW_LOG(INFO, "ABSL_ARCH_X86_64"); -#elif defined(ABSL_ARCH_X86_32) - ABSL_RAW_LOG(INFO, "ABSL_ARCH_X86_32"); -#elif defined(ABSL_ARCH_AARCH64) - ABSL_RAW_LOG(INFO, "ABSL_ARCH_AARCH64"); -#elif defined(ABSL_ARCH_ARM) - ABSL_RAW_LOG(INFO, "ABSL_ARCH_ARM"); -#elif defined(ABSL_ARCH_PPC) - ABSL_RAW_LOG(INFO, "ABSL_ARCH_PPC"); -#else - ABSL_RAW_LOG(INFO, "ARCH Unknown"); -#endif - - int x = absl::random_internal::HasRandenHwAesImplementation(); - ABSL_RAW_LOG(INFO, "HasRandenHwAesImplementation = %d", x); - - int y = absl::random_internal::CPUSupportsRandenHwAes(); - ABSL_RAW_LOG(INFO, "CPUSupportsRandenHwAes = %d", x); - - if (!x || !y) { - ABSL_RAW_LOG(INFO, "Skipping Randen HWAES tests."); - return 0; - } - return RUN_ALL_TESTS(); -} diff --git a/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 5fb3ca556db6..000000000000 --- 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 deleted file mode 100644 index 4e5f3dc1c7b7..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_slow.cc +++ /dev/null @@ -1,457 +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_slow.h" - -#include <cstddef> -#include <cstdint> -#include <cstring> - -#include "absl/base/attributes.h" -#include "absl/random/internal/platform.h" -#include "absl/random/internal/randen_traits.h" - -#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \ - __attribute__((always_inline)) -#elif defined(_MSC_VER) -// We can achieve something similar to attribute((always_inline)) with MSVC by -// using the __forceinline keyword, however this is not perfect. MSVC is -// much less aggressive about inlining, and even with the __forceinline keyword. -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE __forceinline -#else -#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE -#endif - -namespace { - -// AES portions based on rijndael-alg-fst.c, -// https://fastcrypto.org/front/misc/rijndael-alg-fst.c -// -// Implementation of -// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf -constexpr uint32_t te0[256] = { - 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, - 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, - 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, - 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, - 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, - 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, - 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, - 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, - 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, - 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, - 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, - 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, - 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, - 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, - 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, - 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, - 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, - 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, - 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, - 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, - 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, - 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, - 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, - 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, - 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, - 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, - 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, - 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, - 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, - 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, - 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, - 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, - 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, - 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, - 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, - 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, - 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, - 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, - 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, - 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, - 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, - 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, - 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, -}; - -constexpr uint32_t te1[256] = { - 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, - 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, - 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, - 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, - 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, - 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, - 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, - 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, - 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, - 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, - 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, - 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, - 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, - 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, - 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, - 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, - 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, - 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, - 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, - 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, - 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, - 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, - 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, - 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, - 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, - 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, - 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, - 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, - 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, - 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, - 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, - 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, - 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, - 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, - 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, - 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, - 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, - 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, - 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, - 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, - 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, - 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, - 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, -}; - -constexpr uint32_t te2[256] = { - 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, - 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, - 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, - 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, - 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, - 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, - 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, - 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, - 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, - 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, - 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, - 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, - 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, - 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, - 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, - 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, - 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, - 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, - 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, - 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, - 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, - 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, - 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, - 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, - 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, - 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, - 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, - 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, - 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, - 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, - 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, - 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, - 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, - 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, - 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, - 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, - 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, - 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, - 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, - 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, - 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, - 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, - 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, -}; - -constexpr uint32_t te3[256] = { - 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, - 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, - 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, - 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, - 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, - 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, - 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, - 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, - 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, - 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, - 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, - 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, - 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, - 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, - 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, - 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, - 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, - 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, - 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, - 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, - 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, - 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, - 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, - 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, - 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, - 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, - 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, - 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, - 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, - 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, - 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, - 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, - 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, - 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, - 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, - 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, - 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, - 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, - 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, - 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, - 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, - 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, - 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, -}; - -// Software implementation of the Vector128 class, using uint32_t -// as an underlying vector register. -struct alignas(16) Vector128 { - uint32_t s[4]; -}; - -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128 -Vector128Load(const void* from) { - Vector128 result; - const uint8_t* src = reinterpret_cast<const uint8_t*>(from); - result.s[0] = static_cast<uint32_t>(src[0]) << 24 | - static_cast<uint32_t>(src[1]) << 16 | - static_cast<uint32_t>(src[2]) << 8 | - static_cast<uint32_t>(src[3]); - result.s[1] = static_cast<uint32_t>(src[4]) << 24 | - static_cast<uint32_t>(src[5]) << 16 | - static_cast<uint32_t>(src[6]) << 8 | - static_cast<uint32_t>(src[7]); - result.s[2] = static_cast<uint32_t>(src[8]) << 24 | - static_cast<uint32_t>(src[9]) << 16 | - static_cast<uint32_t>(src[10]) << 8 | - static_cast<uint32_t>(src[11]); - result.s[3] = static_cast<uint32_t>(src[12]) << 24 | - static_cast<uint32_t>(src[13]) << 16 | - static_cast<uint32_t>(src[14]) << 8 | - static_cast<uint32_t>(src[15]); - return result; -} - -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store( - const Vector128& v, void* to) { - uint8_t* dst = reinterpret_cast<uint8_t*>(to); - dst[0] = static_cast<uint8_t>(v.s[0] >> 24); - dst[1] = static_cast<uint8_t>(v.s[0] >> 16); - dst[2] = static_cast<uint8_t>(v.s[0] >> 8); - dst[3] = static_cast<uint8_t>(v.s[0]); - dst[4] = static_cast<uint8_t>(v.s[1] >> 24); - dst[5] = static_cast<uint8_t>(v.s[1] >> 16); - dst[6] = static_cast<uint8_t>(v.s[1] >> 8); - dst[7] = static_cast<uint8_t>(v.s[1]); - dst[8] = static_cast<uint8_t>(v.s[2] >> 24); - dst[9] = static_cast<uint8_t>(v.s[2] >> 16); - dst[10] = static_cast<uint8_t>(v.s[2] >> 8); - dst[11] = static_cast<uint8_t>(v.s[2]); - dst[12] = static_cast<uint8_t>(v.s[3] >> 24); - dst[13] = static_cast<uint8_t>(v.s[3] >> 16); - dst[14] = static_cast<uint8_t>(v.s[3] >> 8); - dst[15] = static_cast<uint8_t>(v.s[3]); -} - -// One round of AES. "round_key" is a public constant for breaking the -// symmetry of AES (ensures previously equal columns differ afterwards). -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128 -AesRound(const Vector128& state, const Vector128& round_key) { - Vector128 result; - result.s[0] = round_key.s[0] ^ // - te0[uint8_t(state.s[0] >> 24)] ^ // - te1[uint8_t(state.s[1] >> 16)] ^ // - te2[uint8_t(state.s[2] >> 8)] ^ // - te3[uint8_t(state.s[3])]; - result.s[1] = round_key.s[1] ^ // - te0[uint8_t(state.s[1] >> 24)] ^ // - te1[uint8_t(state.s[2] >> 16)] ^ // - te2[uint8_t(state.s[3] >> 8)] ^ // - te3[uint8_t(state.s[0])]; - result.s[2] = round_key.s[2] ^ // - te0[uint8_t(state.s[2] >> 24)] ^ // - te1[uint8_t(state.s[3] >> 16)] ^ // - te2[uint8_t(state.s[0] >> 8)] ^ // - te3[uint8_t(state.s[1])]; - result.s[3] = round_key.s[3] ^ // - te0[uint8_t(state.s[3] >> 24)] ^ // - te1[uint8_t(state.s[0] >> 16)] ^ // - te2[uint8_t(state.s[1] >> 8)] ^ // - te3[uint8_t(state.s[2])]; - return result; -} - -using ::absl::random_internal::RandenTraits; - -// Randen operates on 128-bit vectors. -struct alignas(16) u64x2 { - uint64_t data[2]; -}; - -// The improved Feistel block shuffle function for 16 blocks. -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle( - u64x2* state) { - static_assert(RandenTraits::kFeistelBlocks == 16, - "Feistel block shuffle only works for 16 blocks."); - - constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = { - 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12}; - - // The fully unrolled loop without the memcpy improves the speed by about - // 30% over the equivalent: -#if 0 - u64x2 source[RandenTraits::kFeistelBlocks]; - std::memcpy(source, state, sizeof(source)); - for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) { - const u64x2 v0 = source[shuffle[i]]; - state[i] = v0; - } - return; -#endif - - const u64x2 v0 = state[shuffle[0]]; - const u64x2 v1 = state[shuffle[1]]; - const u64x2 v2 = state[shuffle[2]]; - const u64x2 v3 = state[shuffle[3]]; - const u64x2 v4 = state[shuffle[4]]; - const u64x2 v5 = state[shuffle[5]]; - const u64x2 v6 = state[shuffle[6]]; - const u64x2 v7 = state[shuffle[7]]; - const u64x2 w0 = state[shuffle[8]]; - const u64x2 w1 = state[shuffle[9]]; - const u64x2 w2 = state[shuffle[10]]; - const u64x2 w3 = state[shuffle[11]]; - const u64x2 w4 = state[shuffle[12]]; - const u64x2 w5 = state[shuffle[13]]; - const u64x2 w6 = state[shuffle[14]]; - const u64x2 w7 = state[shuffle[15]]; - state[0] = v0; - state[1] = v1; - state[2] = v2; - state[3] = v3; - state[4] = v4; - state[5] = v5; - state[6] = v6; - state[7] = v7; - state[8] = w0; - state[9] = w1; - state[10] = w2; - state[11] = w3; - state[12] = w4; - state[13] = w5; - state[14] = w6; - state[15] = w7; -} - -// Feistel round function using two AES subrounds. Very similar to F() -// from Simpira v2, but with independent subround keys. Uses 17 AES rounds -// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in -// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel -// XORs are 'free' (included in the second AES instruction). -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const u64x2* FeistelRound( - u64x2* ABSL_RANDOM_INTERNAL_RESTRICT state, - const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) { - for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) { - const Vector128 s0 = Vector128Load(state + branch); - const Vector128 s1 = Vector128Load(state + branch + 1); - const Vector128 f0 = AesRound(s0, Vector128Load(keys)); - keys++; - const Vector128 o1 = AesRound(f0, s1); - Vector128Store(o1, state + branch + 1); - - // Manually unroll this loop once. about 10% better than not unrolled. - const Vector128 s2 = Vector128Load(state + branch + 2); - const Vector128 s3 = Vector128Load(state + branch + 3); - const Vector128 f2 = AesRound(s2, Vector128Load(keys)); - keys++; - const Vector128 o3 = AesRound(f2, s3); - Vector128Store(o3, state + branch + 3); - } - return keys; -} - -// Cryptographic permutation based via type-2 Generalized Feistel Network. -// Indistinguishable from ideal by chosen-ciphertext adversaries using less than -// 2^64 queries if the round function is a PRF. This is similar to the b=8 case -// of Simpira v2, but more efficient than its generic construction for b=16. -inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute( - u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) { - for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) { - keys = FeistelRound(state, keys); - BlockShuffle(state); - } -} - -} // namespace - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -const void* RandenSlow::GetKeys() { - // Round keys for one AES per Feistel round and branch. - // The canonical implementation uses first digits of Pi. - return kRandenRoundKeys; -} - -void RandenSlow::Absorb(const void* seed_void, void* state_void) { - auto* state = - reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void); - const auto* seed = - reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>( - seed_void); - - constexpr size_t kCapacityBlocks = - RandenTraits::kCapacityBytes / sizeof(uint64_t); - static_assert( - kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes, - "Not i*V"); - - for (size_t i = kCapacityBlocks; - i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) { - state[i] ^= seed[i - kCapacityBlocks]; - } -} - -void RandenSlow::Generate(const void* keys_void, void* state_void) { - static_assert(RandenTraits::kCapacityBytes == sizeof(u64x2), - "Capacity mismatch"); - - auto* state = reinterpret_cast<u64x2*>(state_void); - const auto* keys = reinterpret_cast<const u64x2*>(keys_void); - - const u64x2 prev_inner = state[0]; - - Permute(state, keys); - - // Ensure backtracking resistance. - state[0].data[0] ^= prev_inner.data[0]; - state[0].data[1] ^= prev_inner.data[1]; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/randen_slow.h b/third_party/abseil_cpp/absl/random/internal/randen_slow.h deleted file mode 100644 index b6f137eb94b1..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_slow.h +++ /dev/null @@ -1,40 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_ - -#include <cstddef> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// RANDen = RANDom generator or beetroots in Swiss German. -// RandenSlow implements the basic state manipulation methods for -// architectures lacking AES hardware acceleration intrinsics. -class RandenSlow { - public: - static void Generate(const void* keys, void* state_void); - static void Absorb(const void* seed_void, void* state_void); - static const void* GetKeys(); -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/randen_slow_test.cc b/third_party/abseil_cpp/absl/random/internal/randen_slow_test.cc deleted file mode 100644 index 4a5358370586..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_slow_test.cc +++ /dev/null @@ -1,63 +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_slow.h" - -#include <cstring> - -#include "gtest/gtest.h" -#include "absl/random/internal/randen_traits.h" - -namespace { - -using absl::random_internal::RandenSlow; -using absl::random_internal::RandenTraits; - -// Local state parameters. -constexpr size_t kSeedBytes = - RandenTraits::kStateBytes - RandenTraits::kCapacityBytes; -constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t); -constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t); - -struct alignas(16) randen { - uint64_t state[kStateSizeT]; - uint32_t seed[kSeedSizeT]; -}; - -TEST(RandenSlowTest, Default) { - constexpr uint64_t kGolden[] = { - 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977, - 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912, - 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6, - 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a, - 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37, - 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556, - 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42, - 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc, - 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f, - 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3, - 0x026ff374c101da7e, 0x811ef0821c3de851, - }; - - alignas(16) randen d; - std::memset(d.state, 0, sizeof(d.state)); - RandenSlow::Generate(RandenSlow::GetKeys(), d.state); - - uint64_t* id = d.state; - for (const auto& elem : kGolden) { - EXPECT_EQ(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 deleted file mode 100644 index c186fe0d686b..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_test.cc +++ /dev/null @@ -1,70 +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.h" - -#include <cstring> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" - -namespace { - -using absl::random_internal::Randen; - -// Local state parameters. -constexpr size_t kStateSizeT = Randen::kStateBytes / sizeof(uint64_t); - -TEST(RandenTest, CopyAndMove) { - static_assert(std::is_copy_constructible<Randen>::value, - "Randen must be copy constructible"); - - static_assert(absl::is_copy_assignable<Randen>::value, - "Randen must be copy assignable"); - - static_assert(std::is_move_constructible<Randen>::value, - "Randen must be move constructible"); - - static_assert(absl::is_move_assignable<Randen>::value, - "Randen must be move assignable"); -} - -TEST(RandenTest, Default) { - constexpr uint64_t kGolden[] = { - 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977, - 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912, - 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6, - 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a, - 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37, - 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556, - 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42, - 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc, - 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f, - 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3, - 0x026ff374c101da7e, 0x811ef0821c3de851, - }; - - alignas(16) uint64_t state[kStateSizeT]; - std::memset(state, 0, sizeof(state)); - - Randen r; - r.Generate(state); - - auto id = std::begin(state); - for (const auto& elem : kGolden) { - EXPECT_EQ(elem, *id++); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/randen_traits.h b/third_party/abseil_cpp/absl/random/internal/randen_traits.h deleted file mode 100644 index 53caa936140a..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/randen_traits.h +++ /dev/null @@ -1,88 +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. - -#ifndef ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_ -#define ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_ - -// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate -// symbols from arbitrary system and other headers, since it may be built -// with different flags from other targets, using different levels of -// optimization, potentially introducing ODR violations. - -#include <cstddef> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// RANDen = RANDom generator or beetroots in Swiss German. -// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random -// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32. -// -// High-level summary: -// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is -// a sponge-like random generator that requires a cryptographic permutation. -// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by -// achieving backtracking resistance with only one Permute() per buffer. -// -// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round -// Function" constructs up to 1024-bit permutations using an improved -// Generalized Feistel network with 2-round AES-128 functions. This Feistel -// block shuffle achieves diffusion faster and is less vulnerable to -// sliced-biclique attacks than the Type-2 cyclic shuffle. -// -// 3) "Improving the Generalized Feistel" and "New criterion for diffusion -// property" extends the same kind of improved Feistel block shuffle to 16 -// branches, which enables a 2048-bit permutation. -// -// Combine these three ideas and also change Simpira's subround keys from -// structured/low-entropy counters to digits of Pi (or other random source). - -// RandenTraits contains the basic algorithm traits, such as the size of the -// state, seed, sponge, etc. -struct RandenTraits { - // Size of the entire sponge / state for the randen PRNG. - static constexpr size_t kStateBytes = 256; // 2048-bit - - // Size of the 'inner' (inaccessible) part of the sponge. Larger values would - // require more frequent calls to RandenGenerate. - static constexpr size_t kCapacityBytes = 16; // 128-bit - - // Size of the default seed consumed by the sponge. - static constexpr size_t kSeedBytes = kStateBytes - kCapacityBytes; - - // Assuming 128-bit blocks, the number of blocks in the state. - // Largest size for which security proofs are known. - static constexpr size_t kFeistelBlocks = 16; - - // Ensures SPRP security and two full subblock diffusions. - // Must be > 4 * log2(kFeistelBlocks). - static constexpr size_t kFeistelRounds = 16 + 1; - - // Size of the key. A 128-bit key block is used for every-other - // feistel block (Type-2 generalized Feistel network) in each round. - static constexpr size_t kKeyBytes = 16 * kFeistelRounds * kFeistelBlocks / 2; -}; - -// Randen key arrays. In randen_round_keys.cc -extern const unsigned char kRandenRoundKeys[RandenTraits::kKeyBytes]; -extern const unsigned char kRandenRoundKeysBE[RandenTraits::kKeyBytes]; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/salted_seed_seq.h b/third_party/abseil_cpp/absl/random/internal/salted_seed_seq.h deleted file mode 100644 index 5953a090f80c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/salted_seed_seq.h +++ /dev/null @@ -1,167 +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. - -#ifndef ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_ -#define ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_ - -#include <cstdint> -#include <cstdlib> -#include <initializer_list> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> - -#include "absl/container/inlined_vector.h" -#include "absl/meta/type_traits.h" -#include "absl/random/internal/seed_material.h" -#include "absl/types/optional.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// This class conforms to the C++ Standard "Seed Sequence" concept -// [rand.req.seedseq]. -// -// A `SaltedSeedSeq` is meant to wrap an existing seed sequence and modify -// generated sequence by mixing with extra entropy. This entropy may be -// build-dependent or process-dependent. The implementation may change to be -// have either or both kinds of entropy. If salt is not available sequence is -// not modified. -template <typename SSeq> -class SaltedSeedSeq { - public: - using inner_sequence_type = SSeq; - using result_type = typename SSeq::result_type; - - SaltedSeedSeq() : seq_(absl::make_unique<SSeq>()) {} - - template <typename Iterator> - SaltedSeedSeq(Iterator begin, Iterator end) - : seq_(absl::make_unique<SSeq>(begin, end)) {} - - template <typename T> - SaltedSeedSeq(std::initializer_list<T> il) - : SaltedSeedSeq(il.begin(), il.end()) {} - - SaltedSeedSeq(const SaltedSeedSeq&) = delete; - SaltedSeedSeq& operator=(const SaltedSeedSeq&) = delete; - - SaltedSeedSeq(SaltedSeedSeq&&) = default; - SaltedSeedSeq& operator=(SaltedSeedSeq&&) = default; - - template <typename RandomAccessIterator> - void generate(RandomAccessIterator begin, RandomAccessIterator end) { - // The common case is that generate is called with ContiguousIterators - // to uint arrays. Such contiguous memory regions may be optimized, - // which we detect here. - using tag = absl::conditional_t< - (std::is_pointer<RandomAccessIterator>::value && - std::is_same<absl::decay_t<decltype(*begin)>, uint32_t>::value), - ContiguousAndUint32Tag, DefaultTag>; - if (begin != end) { - generate_impl(begin, end, tag{}); - } - } - - template <typename OutIterator> - void param(OutIterator out) const { - seq_->param(out); - } - - size_t size() const { return seq_->size(); } - - private: - struct ContiguousAndUint32Tag {}; - struct DefaultTag {}; - - // Generate which requires the iterators are contiguous pointers to uint32_t. - void generate_impl(uint32_t* begin, uint32_t* end, ContiguousAndUint32Tag) { - generate_contiguous(absl::MakeSpan(begin, end)); - } - - // The uncommon case for generate is that it is called with iterators over - // some other buffer type which is assignable from a 32-bit value. In this - // case we allocate a temporary 32-bit buffer and then copy-assign back - // to the initial inputs. - template <typename RandomAccessIterator> - void generate_impl(RandomAccessIterator begin, RandomAccessIterator end, - DefaultTag) { - return generate_and_copy(std::distance(begin, end), begin); - } - - // Fills the initial seed buffer the underlying SSeq::generate() call, - // mixing in the salt material. - void generate_contiguous(absl::Span<uint32_t> buffer) { - seq_->generate(buffer.begin(), buffer.end()); - const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0); - MixIntoSeedMaterial(absl::MakeConstSpan(&salt, 1), buffer); - } - - // Allocates a seed buffer of `n` elements, generates the seed, then - // copies the result into the `out` iterator. - template <typename Iterator> - void generate_and_copy(size_t n, Iterator out) { - // Allocate a temporary buffer, generate, and then copy. - absl::InlinedVector<uint32_t, 8> data(n, 0); - generate_contiguous(absl::MakeSpan(data.data(), data.size())); - std::copy(data.begin(), data.end(), out); - } - - // Because [rand.req.seedseq] is not required to be copy-constructible, - // copy-assignable nor movable, we wrap it with unique pointer to be able - // to move SaltedSeedSeq. - std::unique_ptr<SSeq> seq_; -}; - -// is_salted_seed_seq indicates whether the type is a SaltedSeedSeq. -template <typename T, typename = void> -struct is_salted_seed_seq : public std::false_type {}; - -template <typename T> -struct is_salted_seed_seq< - T, typename std::enable_if<std::is_same< - T, SaltedSeedSeq<typename T::inner_sequence_type>>::value>::type> - : public std::true_type {}; - -// MakeSaltedSeedSeq returns a salted variant of the seed sequence. -// When provided with an existing SaltedSeedSeq, returns the input parameter, -// otherwise constructs a new SaltedSeedSeq which embodies the original -// non-salted seed parameters. -template < - typename SSeq, // - typename EnableIf = absl::enable_if_t<is_salted_seed_seq<SSeq>::value>> -SSeq MakeSaltedSeedSeq(SSeq&& seq) { - return SSeq(std::forward<SSeq>(seq)); -} - -template < - typename SSeq, // - typename EnableIf = absl::enable_if_t<!is_salted_seed_seq<SSeq>::value>> -SaltedSeedSeq<typename std::decay<SSeq>::type> MakeSaltedSeedSeq(SSeq&& seq) { - using sseq_type = typename std::decay<SSeq>::type; - using result_type = typename sseq_type::result_type; - - absl::InlinedVector<result_type, 8> data; - seq.param(std::back_inserter(data)); - return SaltedSeedSeq<sseq_type>(data.begin(), data.end()); -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/salted_seed_seq_test.cc b/third_party/abseil_cpp/absl/random/internal/salted_seed_seq_test.cc deleted file mode 100644 index 0bf19a63ef8c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/salted_seed_seq_test.cc +++ /dev/null @@ -1,168 +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/salted_seed_seq.h" - -#include <iterator> -#include <random> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -using absl::random_internal::GetSaltMaterial; -using absl::random_internal::MakeSaltedSeedSeq; -using absl::random_internal::SaltedSeedSeq; -using testing::Eq; -using testing::Pointwise; - -namespace { - -template <typename Sseq> -void ConformsToInterface() { - // Check that the SeedSequence can be default-constructed. - { Sseq default_constructed_seq; } - // Check that the SeedSequence can be constructed with two iterators. - { - uint32_t init_array[] = {1, 3, 5, 7, 9}; - Sseq iterator_constructed_seq(std::begin(init_array), std::end(init_array)); - } - // Check that the SeedSequence can be std::initializer_list-constructed. - { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; } - // Check that param() and size() return state provided to constructor. - { - uint32_t init_array[] = {1, 2, 3, 4, 5}; - Sseq seq(std::begin(init_array), std::end(init_array)); - EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array)); - - std::vector<uint32_t> state_vector; - seq.param(std::back_inserter(state_vector)); - - EXPECT_EQ(state_vector.size(), ABSL_ARRAYSIZE(init_array)); - for (int i = 0; i < state_vector.size(); i++) { - EXPECT_EQ(state_vector[i], i + 1); - } - } - // Check for presence of generate() method. - { - Sseq seq; - uint32_t seeds[5]; - - seq.generate(std::begin(seeds), std::end(seeds)); - } -} - -TEST(SaltedSeedSeq, CheckInterfaces) { - // Control case - ConformsToInterface<std::seed_seq>(); - - // Abseil classes - ConformsToInterface<SaltedSeedSeq<std::seed_seq>>(); -} - -TEST(SaltedSeedSeq, CheckConstructingFromOtherSequence) { - std::vector<uint32_t> seed_values(10, 1); - std::seed_seq seq(seed_values.begin(), seed_values.end()); - auto salted_seq = MakeSaltedSeedSeq(std::move(seq)); - - EXPECT_EQ(seq.size(), salted_seq.size()); - - std::vector<uint32_t> param_result; - seq.param(std::back_inserter(param_result)); - - EXPECT_EQ(seed_values, param_result); -} - -TEST(SaltedSeedSeq, SaltedSaltedSeedSeqIsNotDoubleSalted) { - uint32_t init[] = {1, 3, 5, 7, 9}; - - std::seed_seq seq(std::begin(init), std::end(init)); - - // The first salting. - SaltedSeedSeq<std::seed_seq> salted_seq = MakeSaltedSeedSeq(std::move(seq)); - uint32_t a[16]; - salted_seq.generate(std::begin(a), std::end(a)); - - // The second salting. - SaltedSeedSeq<std::seed_seq> salted_salted_seq = - MakeSaltedSeedSeq(std::move(salted_seq)); - uint32_t b[16]; - salted_salted_seq.generate(std::begin(b), std::end(b)); - - // ... both should be equal. - EXPECT_THAT(b, Pointwise(Eq(), a)) << "a[0] " << a[0]; -} - -TEST(SaltedSeedSeq, SeedMaterialIsSalted) { - const size_t kNumBlocks = 16; - - uint32_t seed_material[kNumBlocks]; - std::random_device urandom{"/dev/urandom"}; - for (uint32_t& seed : seed_material) { - seed = urandom(); - } - - std::seed_seq seq(std::begin(seed_material), std::end(seed_material)); - SaltedSeedSeq<std::seed_seq> salted_seq(std::begin(seed_material), - std::end(seed_material)); - - bool salt_is_available = GetSaltMaterial().has_value(); - - // If salt is available generated sequence should be different. - if (salt_is_available) { - uint32_t outputs[kNumBlocks]; - uint32_t salted_outputs[kNumBlocks]; - - seq.generate(std::begin(outputs), std::end(outputs)); - salted_seq.generate(std::begin(salted_outputs), std::end(salted_outputs)); - - EXPECT_THAT(outputs, Pointwise(testing::Ne(), salted_outputs)); - } -} - -TEST(SaltedSeedSeq, GenerateAcceptsDifferentTypes) { - const size_t kNumBlocks = 4; - - SaltedSeedSeq<std::seed_seq> seq({1, 2, 3}); - - uint32_t expected[kNumBlocks]; - seq.generate(std::begin(expected), std::end(expected)); - - // 32-bit outputs - { - unsigned long seed_material[kNumBlocks]; // NOLINT(runtime/int) - seq.generate(std::begin(seed_material), std::end(seed_material)); - EXPECT_THAT(seed_material, Pointwise(Eq(), expected)); - } - { - unsigned int seed_material[kNumBlocks]; // NOLINT(runtime/int) - seq.generate(std::begin(seed_material), std::end(seed_material)); - EXPECT_THAT(seed_material, Pointwise(Eq(), expected)); - } - - // 64-bit outputs. - { - uint64_t seed_material[kNumBlocks]; - seq.generate(std::begin(seed_material), std::end(seed_material)); - EXPECT_THAT(seed_material, Pointwise(Eq(), expected)); - } - { - int64_t seed_material[kNumBlocks]; - seq.generate(std::begin(seed_material), std::end(seed_material)); - EXPECT_THAT(seed_material, Pointwise(Eq(), expected)); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/seed_material.cc b/third_party/abseil_cpp/absl/random/internal/seed_material.cc deleted file mode 100644 index 4d38a57419ec..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/seed_material.cc +++ /dev/null @@ -1,219 +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/seed_material.h" - -#include <fcntl.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <io.h> -#endif - -#include <algorithm> -#include <cerrno> -#include <cstdint> -#include <cstdlib> -#include <cstring> - -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/ascii.h" -#include "absl/strings/escaping.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" - -#if defined(__native_client__) - -#include <nacl/nacl_random.h> -#define ABSL_RANDOM_USE_NACL_SECURE_RANDOM 1 - -#elif defined(_WIN32) - -#include <windows.h> -#define ABSL_RANDOM_USE_BCRYPT 1 -#pragma comment(lib, "bcrypt.lib") - -#elif defined(__Fuchsia__) -#include <zircon/syscalls.h> - -#endif - -#if defined(ABSL_RANDOM_USE_BCRYPT) -#include <bcrypt.h> - -#ifndef BCRYPT_SUCCESS -#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) -#endif -// Also link bcrypt; this can be done via linker options or: -// #pragma comment(lib, "bcrypt.lib") -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { -namespace { - -// Read OS Entropy for random number seeds. -// TODO(absl-team): Possibly place a cap on how much entropy may be read at a -// time. - -#if defined(ABSL_RANDOM_USE_BCRYPT) - -// On Windows potentially use the BCRYPT CNG API to read available entropy. -bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) { - BCRYPT_ALG_HANDLE hProvider; - NTSTATUS ret; - ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM, - MS_PRIMITIVE_PROVIDER, 0); - if (!(BCRYPT_SUCCESS(ret))) { - ABSL_RAW_LOG(ERROR, "Failed to open crypto provider."); - return false; - } - ret = BCryptGenRandom( - hProvider, // provider - reinterpret_cast<UCHAR*>(values.data()), // buffer - static_cast<ULONG>(sizeof(uint32_t) * values.size()), // bytes - 0); // flags - BCryptCloseAlgorithmProvider(hProvider, 0); - return BCRYPT_SUCCESS(ret); -} - -#elif defined(ABSL_RANDOM_USE_NACL_SECURE_RANDOM) - -// On NaCL use nacl_secure_random to acquire bytes. -bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) { - auto buffer = reinterpret_cast<uint8_t*>(values.data()); - size_t buffer_size = sizeof(uint32_t) * values.size(); - - uint8_t* output_ptr = buffer; - while (buffer_size > 0) { - size_t nread = 0; - const int error = nacl_secure_random(output_ptr, buffer_size, &nread); - if (error != 0 || nread > buffer_size) { - ABSL_RAW_LOG(ERROR, "Failed to read secure_random seed data: %d", error); - return false; - } - output_ptr += nread; - buffer_size -= nread; - } - return true; -} - -#elif defined(__Fuchsia__) - -bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) { - auto buffer = reinterpret_cast<uint8_t*>(values.data()); - size_t buffer_size = sizeof(uint32_t) * values.size(); - zx_cprng_draw(buffer, buffer_size); - return true; -} - -#else - -// On *nix, read entropy from /dev/urandom. -bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) { - const char kEntropyFile[] = "/dev/urandom"; - - auto buffer = reinterpret_cast<uint8_t*>(values.data()); - size_t buffer_size = sizeof(uint32_t) * values.size(); - - int dev_urandom = open(kEntropyFile, O_RDONLY); - bool success = (-1 != dev_urandom); - if (!success) { - return false; - } - - while (success && buffer_size > 0) { - int bytes_read = read(dev_urandom, buffer, buffer_size); - int read_error = errno; - success = (bytes_read > 0); - if (success) { - buffer += bytes_read; - buffer_size -= bytes_read; - } else if (bytes_read == -1 && read_error == EINTR) { - success = true; // Need to try again. - } - } - close(dev_urandom); - return success; -} - -#endif - -} // namespace - -bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values) { - assert(values.data() != nullptr); - if (values.data() == nullptr) { - return false; - } - if (values.empty()) { - return true; - } - return ReadSeedMaterialFromOSEntropyImpl(values); -} - -void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence, - absl::Span<uint32_t> seed_material) { - // Algorithm is based on code available at - // https://gist.github.com/imneme/540829265469e673d045 - constexpr uint32_t kInitVal = 0x43b0d7e5; - constexpr uint32_t kHashMul = 0x931e8875; - constexpr uint32_t kMixMulL = 0xca01f9dd; - constexpr uint32_t kMixMulR = 0x4973f715; - constexpr uint32_t kShiftSize = sizeof(uint32_t) * 8 / 2; - - uint32_t hash_const = kInitVal; - auto hash = [&](uint32_t value) { - value ^= hash_const; - hash_const *= kHashMul; - value *= hash_const; - value ^= value >> kShiftSize; - return value; - }; - - auto mix = [&](uint32_t x, uint32_t y) { - uint32_t result = kMixMulL * x - kMixMulR * y; - result ^= result >> kShiftSize; - return result; - }; - - for (const auto& seq_val : sequence) { - for (auto& elem : seed_material) { - elem = mix(elem, hash(seq_val)); - } - } -} - -absl::optional<uint32_t> GetSaltMaterial() { - // Salt must be common for all generators within the same process so read it - // only once and store in static variable. - static const auto salt_material = []() -> absl::optional<uint32_t> { - uint32_t salt_value = 0; - - if (random_internal::ReadSeedMaterialFromOSEntropy( - MakeSpan(&salt_value, 1))) { - return salt_value; - } - - return absl::nullopt; - }(); - - return salt_material; -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/internal/seed_material.h b/third_party/abseil_cpp/absl/random/internal/seed_material.h deleted file mode 100644 index 4be10e925685..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/seed_material.h +++ /dev/null @@ -1,104 +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. - -#ifndef ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_ -#define ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_ - -#include <cassert> -#include <cstdint> -#include <cstdlib> -#include <string> -#include <vector> - -#include "absl/base/attributes.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/types/optional.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Returns the number of 32-bit blocks needed to contain the given number of -// bits. -constexpr size_t SeedBitsToBlocks(size_t seed_size) { - return (seed_size + 31) / 32; -} - -// Amount of entropy (measured in bits) used to instantiate a Seed Sequence, -// with which to create a URBG. -constexpr size_t kEntropyBitsNeeded = 256; - -// Amount of entropy (measured in 32-bit blocks) used to instantiate a Seed -// Sequence, with which to create a URBG. -constexpr size_t kEntropyBlocksNeeded = - random_internal::SeedBitsToBlocks(kEntropyBitsNeeded); - -static_assert(kEntropyBlocksNeeded > 0, - "Entropy used to seed URBGs must be nonzero."); - -// Attempts to fill a span of uint32_t-values using an OS-provided source of -// true entropy (eg. /dev/urandom) into an array of uint32_t blocks of data. The -// resulting array may be used to initialize an instance of a class conforming -// to the C++ Standard "Seed Sequence" concept [rand.req.seedseq]. -// -// If values.data() == nullptr, the behavior is undefined. -ABSL_MUST_USE_RESULT -bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values); - -// Attempts to fill a span of uint32_t-values using variates generated by an -// existing instance of a class conforming to the C++ Standard "Uniform Random -// Bit Generator" concept [rand.req.urng]. The resulting data may be used to -// initialize an instance of a class conforming to the C++ Standard -// "Seed Sequence" concept [rand.req.seedseq]. -// -// If urbg == nullptr or values.data() == nullptr, the behavior is undefined. -template <typename URBG> -ABSL_MUST_USE_RESULT bool ReadSeedMaterialFromURBG( - URBG* urbg, absl::Span<uint32_t> values) { - random_internal::FastUniformBits<uint32_t> distr; - - assert(urbg != nullptr && values.data() != nullptr); - if (urbg == nullptr || values.data() == nullptr) { - return false; - } - - for (uint32_t& seed_value : values) { - seed_value = distr(*urbg); - } - return true; -} - -// Mixes given sequence of values with into given sequence of seed material. -// Time complexity of this function is O(sequence.size() * -// seed_material.size()). -// -// Algorithm is based on code available at -// https://gist.github.com/imneme/540829265469e673d045 -// by Melissa O'Neill. -void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence, - absl::Span<uint32_t> seed_material); - -// Returns salt value. -// -// Salt is obtained only once and stored in static variable. -// -// May return empty value if optaining the salt was not possible. -absl::optional<uint32_t> GetSaltMaterial(); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/seed_material_test.cc b/third_party/abseil_cpp/absl/random/internal/seed_material_test.cc deleted file mode 100644 index 6db2820ec707..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/seed_material_test.cc +++ /dev/null @@ -1,202 +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/seed_material.h" - -#include <bitset> -#include <cstdlib> -#include <cstring> -#include <random> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -#ifdef __ANDROID__ -// Android assert messages only go to system log, so death tests cannot inspect -// the message for matching. -#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - EXPECT_DEATH_IF_SUPPORTED(statement, ".*") -#else -#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - EXPECT_DEATH_IF_SUPPORTED(statement, regex) -#endif - -namespace { - -using testing::Each; -using testing::ElementsAre; -using testing::Eq; -using testing::Ne; -using testing::Pointwise; - -TEST(SeedBitsToBlocks, VerifyCases) { - EXPECT_EQ(0, absl::random_internal::SeedBitsToBlocks(0)); - EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(1)); - EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(31)); - EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(32)); - EXPECT_EQ(2, absl::random_internal::SeedBitsToBlocks(33)); - EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(127)); - EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(128)); - EXPECT_EQ(5, absl::random_internal::SeedBitsToBlocks(129)); -} - -TEST(ReadSeedMaterialFromOSEntropy, SuccessiveReadsAreDistinct) { - constexpr size_t kSeedMaterialSize = 64; - uint32_t seed_material_1[kSeedMaterialSize] = {}; - uint32_t seed_material_2[kSeedMaterialSize] = {}; - - EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy( - absl::Span<uint32_t>(seed_material_1, kSeedMaterialSize))); - EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy( - absl::Span<uint32_t>(seed_material_2, kSeedMaterialSize))); - - EXPECT_THAT(seed_material_1, Pointwise(Ne(), seed_material_2)); -} - -TEST(ReadSeedMaterialFromOSEntropy, ReadZeroBytesIsNoOp) { - uint32_t seed_material[32] = {}; - std::memset(seed_material, 0xAA, sizeof(seed_material)); - EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy( - absl::Span<uint32_t>(seed_material, 0))); - - EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA))); -} - -TEST(ReadSeedMaterialFromOSEntropy, NullPtrVectorArgument) { -#ifdef NDEBUG - EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromOSEntropy( - absl::Span<uint32_t>(nullptr, 32))); -#else - bool result; - ABSL_EXPECT_DEATH_IF_SUPPORTED( - result = absl::random_internal::ReadSeedMaterialFromOSEntropy( - absl::Span<uint32_t>(nullptr, 32)), - "!= nullptr"); - (void)result; // suppress unused-variable warning -#endif -} - -TEST(ReadSeedMaterialFromURBG, SeedMaterialEqualsVariateSequence) { - // Two default-constructed instances of std::mt19937_64 are guaranteed to - // produce equal variate-sequences. - std::mt19937 urbg_1; - std::mt19937 urbg_2; - constexpr size_t kSeedMaterialSize = 1024; - uint32_t seed_material[kSeedMaterialSize] = {}; - - EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG( - &urbg_1, absl::Span<uint32_t>(seed_material, kSeedMaterialSize))); - for (uint32_t seed : seed_material) { - EXPECT_EQ(seed, urbg_2()); - } -} - -TEST(ReadSeedMaterialFromURBG, ReadZeroBytesIsNoOp) { - std::mt19937_64 urbg; - uint32_t seed_material[32]; - std::memset(seed_material, 0xAA, sizeof(seed_material)); - EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG( - &urbg, absl::Span<uint32_t>(seed_material, 0))); - - EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA))); -} - -TEST(ReadSeedMaterialFromURBG, NullUrbgArgument) { - constexpr size_t kSeedMaterialSize = 32; - uint32_t seed_material[kSeedMaterialSize]; -#ifdef NDEBUG - EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>( - nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize))); -#else - bool result; - ABSL_EXPECT_DEATH_IF_SUPPORTED( - result = absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>( - nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)), - "!= nullptr"); - (void)result; // suppress unused-variable warning -#endif -} - -TEST(ReadSeedMaterialFromURBG, NullPtrVectorArgument) { - std::mt19937_64 urbg; -#ifdef NDEBUG - EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG( - &urbg, absl::Span<uint32_t>(nullptr, 32))); -#else - bool result; - ABSL_EXPECT_DEATH_IF_SUPPORTED( - result = absl::random_internal::ReadSeedMaterialFromURBG( - &urbg, absl::Span<uint32_t>(nullptr, 32)), - "!= nullptr"); - (void)result; // suppress unused-variable warning -#endif -} - -// The avalanche effect is a desirable cryptographic property of hashes in which -// changing a single bit in the input causes each bit of the output to be -// changed with probability near 50%. -// -// https://en.wikipedia.org/wiki/Avalanche_effect - -TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitLong) { - std::vector<uint32_t> seed_material = {1, 2, 3, 4, 5, 6, 7, 8}; - - // For every 32-bit number with exactly one bit set, verify the avalanche - // effect holds. In order to reduce flakiness of tests, accept values - // anywhere in the range of 30%-70%. - for (uint32_t v = 1; v != 0; v <<= 1) { - std::vector<uint32_t> seed_material_copy = seed_material; - absl::random_internal::MixIntoSeedMaterial( - absl::Span<uint32_t>(&v, 1), - absl::Span<uint32_t>(seed_material_copy.data(), - seed_material_copy.size())); - - uint32_t changed_bits = 0; - for (size_t i = 0; i < seed_material.size(); i++) { - std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^ - seed_material_copy[i]); - changed_bits += bitset.count(); - } - - EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size()); - EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size()); - } -} - -TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitShort) { - std::vector<uint32_t> seed_material = {1}; - - // For every 32-bit number with exactly one bit set, verify the avalanche - // effect holds. In order to reduce flakiness of tests, accept values - // anywhere in the range of 30%-70%. - for (uint32_t v = 1; v != 0; v <<= 1) { - std::vector<uint32_t> seed_material_copy = seed_material; - absl::random_internal::MixIntoSeedMaterial( - absl::Span<uint32_t>(&v, 1), - absl::Span<uint32_t>(seed_material_copy.data(), - seed_material_copy.size())); - - uint32_t changed_bits = 0; - for (size_t i = 0; i < seed_material.size(); i++) { - std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^ - seed_material_copy[i]); - changed_bits += bitset.count(); - } - - EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size()); - EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size()); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/sequence_urbg.h b/third_party/abseil_cpp/absl/random/internal/sequence_urbg.h deleted file mode 100644 index bc96a12cd29c..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/sequence_urbg.h +++ /dev/null @@ -1,60 +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. - -#ifndef ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_ -#define ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_ - -#include <cstdint> -#include <cstring> -#include <limits> -#include <type_traits> -#include <vector> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// `sequence_urbg` is a simple random number generator which meets the -// requirements of [rand.req.urbg], and is solely for testing absl -// distributions. -class sequence_urbg { - public: - using result_type = uint64_t; - - static constexpr result_type(min)() { - return (std::numeric_limits<result_type>::min)(); - } - static constexpr result_type(max)() { - return (std::numeric_limits<result_type>::max)(); - } - - sequence_urbg(std::initializer_list<result_type> data) : i_(0), data_(data) {} - void reset() { i_ = 0; } - - result_type operator()() { return data_[i_++ % data_.size()]; } - - size_t invocations() const { return i_; } - - private: - size_t i_; - std::vector<result_type> data_; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/traits.h b/third_party/abseil_cpp/absl/random/internal/traits.h deleted file mode 100644 index 75772bd9abb4..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/traits.h +++ /dev/null @@ -1,101 +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. - -#ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_ -#define ABSL_RANDOM_INTERNAL_TRAITS_H_ - -#include <cstdint> -#include <limits> -#include <type_traits> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// random_internal::is_widening_convertible<A, B> -// -// Returns whether a type A is widening-convertible to a type B. -// -// A is widening-convertible to B means: -// A a = <any number>; -// B b = a; -// A c = b; -// EXPECT_EQ(a, c); -template <typename A, typename B> -class is_widening_convertible { - // As long as there are enough bits in the exact part of a number: - // - unsigned can fit in float, signed, unsigned - // - signed can fit in float, signed - // - float can fit in float - // So we define rank to be: - // - rank(float) -> 2 - // - rank(signed) -> 1 - // - rank(unsigned) -> 0 - template <class T> - static constexpr int rank() { - return !std::numeric_limits<T>::is_integer + - std::numeric_limits<T>::is_signed; - } - - public: - // If an arithmetic-type B can represent at least as many digits as a type A, - // and B belongs to a rank no lower than A, then A can be safely represented - // by B through a widening-conversion. - static constexpr bool value = - std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits && - rank<A>() <= rank<B>(); -}; - -// unsigned_bits<N>::type returns the unsigned int type with the indicated -// number of bits. -template <size_t N> -struct unsigned_bits; - -template <> -struct unsigned_bits<8> { - using type = uint8_t; -}; -template <> -struct unsigned_bits<16> { - using type = uint16_t; -}; -template <> -struct unsigned_bits<32> { - using type = uint32_t; -}; -template <> -struct unsigned_bits<64> { - using type = uint64_t; -}; - -#ifdef ABSL_HAVE_INTRINSIC_INT128 -template <> -struct unsigned_bits<128> { - using type = __uint128_t; -}; -#endif - -template <typename IntType> -struct make_unsigned_bits { - using type = typename unsigned_bits<std::numeric_limits< - typename std::make_unsigned<IntType>::type>::digits>::type; -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_TRAITS_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/traits_test.cc b/third_party/abseil_cpp/absl/random/internal/traits_test.cc deleted file mode 100644 index a844887d3e44..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/traits_test.cc +++ /dev/null @@ -1,126 +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/traits.h" - -#include <cstdint> -#include <type_traits> - -#include "gtest/gtest.h" - -namespace { - -using absl::random_internal::is_widening_convertible; - -// CheckWideningConvertsToSelf<T1, T2, ...>() -// -// For each type T, checks: -// - T IS widening-convertible to itself. -// -template <typename T> -void CheckWideningConvertsToSelf() { - static_assert(is_widening_convertible<T, T>::value, - "Type is not convertible to self!"); -} - -template <typename T, typename Next, typename... Args> -void CheckWideningConvertsToSelf() { - CheckWideningConvertsToSelf<T>(); - CheckWideningConvertsToSelf<Next, Args...>(); -} - -// CheckNotWideningConvertibleWithSigned<T1, T2, ...>() -// -// For each unsigned-type T, checks that: -// - T is NOT widening-convertible to Signed(T) -// - Signed(T) is NOT widening-convertible to T -// -template <typename T> -void CheckNotWideningConvertibleWithSigned() { - using signed_t = typename std::make_signed<T>::type; - - static_assert(!is_widening_convertible<T, signed_t>::value, - "Unsigned type is convertible to same-sized signed-type!"); - static_assert(!is_widening_convertible<signed_t, T>::value, - "Signed type is convertible to same-sized unsigned-type!"); -} - -template <typename T, typename Next, typename... Args> -void CheckNotWideningConvertibleWithSigned() { - CheckNotWideningConvertibleWithSigned<T>(); - CheckWideningConvertsToSelf<Next, Args...>(); -} - -// CheckWideningConvertsToLargerType<T1, T2, ...>() -// -// For each successive unsigned-types {Ti, Ti+1}, checks that: -// - Ti IS widening-convertible to Ti+1 -// - Ti IS widening-convertible to Signed(Ti+1) -// - Signed(Ti) is NOT widening-convertible to Ti -// - Signed(Ti) IS widening-convertible to Ti+1 -template <typename T, typename Higher> -void CheckWideningConvertsToLargerTypes() { - using signed_t = typename std::make_signed<T>::type; - using higher_t = Higher; - using signed_higher_t = typename std::make_signed<Higher>::type; - - static_assert(is_widening_convertible<T, higher_t>::value, - "Type not embeddable into larger type!"); - static_assert(is_widening_convertible<T, signed_higher_t>::value, - "Type not embeddable into larger signed type!"); - static_assert(!is_widening_convertible<signed_t, higher_t>::value, - "Signed type is embeddable into larger unsigned type!"); - static_assert(is_widening_convertible<signed_t, signed_higher_t>::value, - "Signed type not embeddable into larger signed type!"); -} - -template <typename T, typename Higher, typename Next, typename... Args> -void CheckWideningConvertsToLargerTypes() { - CheckWideningConvertsToLargerTypes<T, Higher>(); - CheckWideningConvertsToLargerTypes<Higher, Next, Args...>(); -} - -// CheckWideningConvertsTo<T, U, [expect]> -// -// Checks that T DOES widening-convert to U. -// If "expect" is false, then asserts that T does NOT widening-convert to U. -template <typename T, typename U, bool expect = true> -void CheckWideningConvertsTo() { - static_assert(is_widening_convertible<T, U>::value == expect, - "Unexpected result for is_widening_convertible<T, U>!"); -} - -TEST(TraitsTest, IsWideningConvertibleTest) { - constexpr bool kInvalid = false; - - CheckWideningConvertsToSelf< - uint8_t, uint16_t, uint32_t, uint64_t, - int8_t, int16_t, int32_t, int64_t, - float, double>(); - CheckNotWideningConvertibleWithSigned< - uint8_t, uint16_t, uint32_t, uint64_t>(); - CheckWideningConvertsToLargerTypes< - uint8_t, uint16_t, uint32_t, uint64_t>(); - - CheckWideningConvertsTo<float, double>(); - CheckWideningConvertsTo<uint16_t, float>(); - CheckWideningConvertsTo<uint32_t, double>(); - CheckWideningConvertsTo<uint64_t, double, kInvalid>(); - CheckWideningConvertsTo<double, float, kInvalid>(); - - CheckWideningConvertsTo<bool, int>(); - CheckWideningConvertsTo<bool, float>(); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/internal/uniform_helper.h b/third_party/abseil_cpp/absl/random/internal/uniform_helper.h deleted file mode 100644 index 1243bc1c62ab..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/uniform_helper.h +++ /dev/null @@ -1,244 +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_UNIFORM_HELPER_H_ -#define ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_ - -#include <cmath> -#include <limits> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" -#include "absl/random/internal/traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -template <typename IntType> -class uniform_int_distribution; - -template <typename RealType> -class uniform_real_distribution; - -// Interval tag types which specify whether the interval is open or closed -// on either boundary. - -namespace random_internal { -template <typename T> -struct TagTypeCompare {}; - -template <typename T> -constexpr bool operator==(TagTypeCompare<T>, TagTypeCompare<T>) { - // Tags are mono-states. They always compare equal. - return true; -} -template <typename T> -constexpr bool operator!=(TagTypeCompare<T>, TagTypeCompare<T>) { - return false; -} - -} // namespace random_internal - -struct IntervalClosedClosedTag - : public random_internal::TagTypeCompare<IntervalClosedClosedTag> {}; -struct IntervalClosedOpenTag - : public random_internal::TagTypeCompare<IntervalClosedOpenTag> {}; -struct IntervalOpenClosedTag - : public random_internal::TagTypeCompare<IntervalOpenClosedTag> {}; -struct IntervalOpenOpenTag - : public random_internal::TagTypeCompare<IntervalOpenOpenTag> {}; - -namespace random_internal { - -// In the absence of an explicitly provided return-type, the template -// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on -// the data-types of the endpoint-arguments {A lo, B hi}. -// -// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the -// return-type, if one type can be implicitly converted into the other, in a -// lossless way. The template "is_widening_convertible" implements the -// compile-time logic for deciding if such a conversion is possible. -// -// If no such conversion between {A, B} exists, then the overload for -// absl::Uniform() will be discarded, and the call will be ill-formed. -// Return-type for absl::Uniform() when the return-type is inferred. -template <typename A, typename B> -using uniform_inferred_return_t = - absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>, - is_widening_convertible<B, A>>::value, - typename std::conditional< - is_widening_convertible<A, B>::value, B, A>::type>; - -// The functions -// uniform_lower_bound(tag, a, b) -// and -// uniform_upper_bound(tag, a, b) -// are used as implementation-details for absl::Uniform(). -// -// Conceptually, -// [a, b] == [uniform_lower_bound(IntervalClosedClosed, a, b), -// uniform_upper_bound(IntervalClosedClosed, a, b)] -// (a, b) == [uniform_lower_bound(IntervalOpenOpen, a, b), -// uniform_upper_bound(IntervalOpenOpen, a, b)] -// [a, b) == [uniform_lower_bound(IntervalClosedOpen, a, b), -// uniform_upper_bound(IntervalClosedOpen, a, b)] -// (a, b] == [uniform_lower_bound(IntervalOpenClosed, a, b), -// uniform_upper_bound(IntervalOpenClosed, a, b)] -// -template <typename IntType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_integral<IntType>, - absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>, - std::is_same<Tag, IntervalOpenOpenTag>>>::value, - IntType> -uniform_lower_bound(Tag, IntType a, IntType) { - return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a; -} - -template <typename FloatType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_floating_point<FloatType>, - absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>, - std::is_same<Tag, IntervalOpenOpenTag>>>::value, - FloatType> -uniform_lower_bound(Tag, FloatType a, FloatType b) { - return std::nextafter(a, b); -} - -template <typename NumType, typename Tag> -typename absl::enable_if_t< - absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>, - std::is_same<Tag, IntervalClosedOpenTag>>::value, - NumType> -uniform_lower_bound(Tag, NumType a, NumType) { - return a; -} - -template <typename IntType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_integral<IntType>, - absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>, - std::is_same<Tag, IntervalOpenOpenTag>>>::value, - IntType> -uniform_upper_bound(Tag, IntType, IntType b) { - return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b; -} - -template <typename FloatType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_floating_point<FloatType>, - absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>, - std::is_same<Tag, IntervalOpenOpenTag>>>::value, - FloatType> -uniform_upper_bound(Tag, FloatType, FloatType b) { - return b; -} - -template <typename IntType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_integral<IntType>, - absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>, - std::is_same<Tag, IntervalOpenClosedTag>>>::value, - IntType> -uniform_upper_bound(Tag, IntType, IntType b) { - return b; -} - -template <typename FloatType, typename Tag> -typename absl::enable_if_t< - absl::conjunction< - std::is_floating_point<FloatType>, - absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>, - std::is_same<Tag, IntervalOpenClosedTag>>>::value, - FloatType> -uniform_upper_bound(Tag, FloatType, FloatType b) { - return std::nextafter(b, (std::numeric_limits<FloatType>::max)()); -} - -// Returns whether the bounds are valid for the underlying distribution. -// Inputs must have already been resolved via uniform_*_bound calls. -// -// The c++ standard constraints in [rand.dist.uni.int] are listed as: -// requires: lo <= hi. -// -// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus: -// [0, 0] is legal. -// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0]. -// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1]. -// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1]. -// -// The c++ standard constraints in [rand.dist.uni.real] are listed as: -// requires: lo <= hi. -// requires: (hi - lo) <= numeric_limits<T>::max() -// -// In the uniform_real_distribution, {lo, hi} are closed, open, Thus: -// [0, 0] is legal, which is [0, 0+epsilon). -// [0, 0) is legal. -// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is. -// (0, 0] is not legal, but (0, 0+epsilon] is. -// -template <typename FloatType> -absl::enable_if_t<std::is_floating_point<FloatType>::value, bool> -is_uniform_range_valid(FloatType a, FloatType b) { - return a <= b && std::isfinite(b - a); -} - -template <typename IntType> -absl::enable_if_t<std::is_integral<IntType>::value, bool> -is_uniform_range_valid(IntType a, IntType b) { - return a <= b; -} - -// UniformDistribution selects either absl::uniform_int_distribution -// or absl::uniform_real_distribution depending on the NumType parameter. -template <typename NumType> -using UniformDistribution = - typename std::conditional<std::is_integral<NumType>::value, - absl::uniform_int_distribution<NumType>, - absl::uniform_real_distribution<NumType>>::type; - -// UniformDistributionWrapper is used as the underlying distribution type -// by the absl::Uniform template function. It selects the proper Abseil -// uniform distribution and provides constructor overloads that match the -// expected parameter order as well as adjusting distribtuion bounds based -// on the tag. -template <typename NumType> -struct UniformDistributionWrapper : public UniformDistribution<NumType> { - template <typename TagType> - explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi) - : UniformDistribution<NumType>( - uniform_lower_bound<NumType>(TagType{}, lo, hi), - uniform_upper_bound<NumType>(TagType{}, lo, hi)) {} - - explicit UniformDistributionWrapper(NumType lo, NumType hi) - : UniformDistribution<NumType>( - uniform_lower_bound<NumType>(IntervalClosedOpenTag(), lo, hi), - uniform_upper_bound<NumType>(IntervalClosedOpenTag(), lo, hi)) {} - - explicit UniformDistributionWrapper() - : UniformDistribution<NumType>(std::numeric_limits<NumType>::lowest(), - (std::numeric_limits<NumType>::max)()) {} -}; - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_ diff --git a/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 173c49b0b7f8..000000000000 --- 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 deleted file mode 100644 index 0afcbe08e229..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/wide_multiply.h +++ /dev/null @@ -1,111 +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. - -#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_ -#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_ - -#include <cstdint> -#include <limits> -#include <type_traits> - -#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64) -#include <intrin.h> // NOLINT(build/include_order) -#pragma intrinsic(_umul128) -#define ABSL_INTERNAL_USE_UMUL128 1 -#endif - -#include "absl/base/config.h" -#include "absl/base/internal/bits.h" -#include "absl/numeric/int128.h" -#include "absl/random/internal/traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace random_internal { - -// Helper object to multiply two 64-bit values to a 128-bit value. -// MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value. -// If an intrinsic is available, it is used, otherwise use native 32-bit -// multiplies to construct the result. -inline absl::uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) { -#if defined(ABSL_HAVE_INTRINSIC_INT128) - return absl::uint128(static_cast<__uint128_t>(a) * b); -#elif defined(ABSL_INTERNAL_USE_UMUL128) - // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC. - uint64_t high = 0; - const uint64_t low = _umul128(a, b, &high); - return absl::MakeUint128(high, low); -#else - // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit - // multiply. However there are many cases where that is not necessary, and it - // is only necessary to support a 64-bit x 64-bit = 128-bit multiply. This is - // for those cases. - const uint64_t a00 = static_cast<uint32_t>(a); - const uint64_t a32 = a >> 32; - const uint64_t b00 = static_cast<uint32_t>(b); - const uint64_t b32 = b >> 32; - - const uint64_t c00 = a00 * b00; - const uint64_t c32a = a00 * b32; - const uint64_t c32b = a32 * b00; - const uint64_t c64 = a32 * b32; - - const uint32_t carry = - static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) + - static_cast<uint32_t>(c32b)) >> - 32); - - return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry, - c00 + (c32a << 32) + (c32b << 32)); -#endif -} - -// wide_multiply<T> multiplies two N-bit values to a 2N-bit result. -template <typename UIntType> -struct wide_multiply { - static constexpr size_t kN = std::numeric_limits<UIntType>::digits; - using input_type = UIntType; - using result_type = typename random_internal::unsigned_bits<kN * 2>::type; - - static result_type multiply(input_type a, input_type b) { - return static_cast<result_type>(a) * b; - } - - static input_type hi(result_type r) { return r >> kN; } - static input_type lo(result_type r) { return r; } - - static_assert(std::is_unsigned<UIntType>::value, - "Class-template wide_multiply<> argument must be unsigned."); -}; - -#ifndef ABSL_HAVE_INTRINSIC_INT128 -template <> -struct wide_multiply<uint64_t> { - using input_type = uint64_t; - using result_type = absl::uint128; - - static result_type multiply(uint64_t a, uint64_t b) { - return MultiplyU64ToU128(a, b); - } - - static uint64_t hi(result_type r) { return absl::Uint128High64(r); } - static uint64_t lo(result_type r) { return absl::Uint128Low64(r); } -}; -#endif - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_ diff --git a/third_party/abseil_cpp/absl/random/internal/wide_multiply_test.cc b/third_party/abseil_cpp/absl/random/internal/wide_multiply_test.cc deleted file mode 100644 index ca8ce923b710..000000000000 --- a/third_party/abseil_cpp/absl/random/internal/wide_multiply_test.cc +++ /dev/null @@ -1,66 +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/wide_multiply.h" - -#include "gtest/gtest.h" -#include "absl/base/internal/bits.h" -#include "absl/numeric/int128.h" - -using absl::random_internal::MultiplyU64ToU128; - -namespace { - -TEST(WideMultiplyTest, MultiplyU64ToU128Test) { - constexpr uint64_t k1 = 1; - constexpr uint64_t kMax = ~static_cast<uint64_t>(0); - - EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0)); - - // Max uint64_t - EXPECT_EQ(MultiplyU64ToU128(kMax, kMax), - absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001)); - EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1)); - EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax)); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(absl::MakeUint128(0, kMax) << i, - MultiplyU64ToU128(kMax, k1 << i)); - EXPECT_EQ(absl::MakeUint128(0, kMax) << i, - MultiplyU64ToU128(k1 << i, kMax)); - } - - // 1-bit x 1-bit. - for (int i = 0; i < 64; ++i) { - for (int j = 0; j < 64; ++j) { - EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j), - MultiplyU64ToU128(k1 << i, k1 << j)); - EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j), - MultiplyU64ToU128(k1 << i, k1 << j)); - } - } - - // Verified multiplies - EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888), - absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60)); - EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210), - absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0)); - EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420), - absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0)); - EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210), - absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320)); - EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420), - absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/log_uniform_int_distribution.h b/third_party/abseil_cpp/absl/random/log_uniform_int_distribution.h deleted file mode 100644 index 960816e2f8ff..000000000000 --- a/third_party/abseil_cpp/absl/random/log_uniform_int_distribution.h +++ /dev/null @@ -1,254 +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. - -#ifndef ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_ -#define ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_ - -#include <algorithm> -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <ostream> -#include <type_traits> - -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" -#include "absl/random/internal/traits.h" -#include "absl/random/uniform_int_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// log_uniform_int_distribution: -// -// Returns a random variate R in range [min, max] such that -// floor(log(R-min, base)) is uniformly distributed. -// We ensure uniformity by discretization using the -// boundary sets [0, 1, base, base * base, ... min(base*n, max)] -// -template <typename IntType = int> -class log_uniform_int_distribution { - private: - using unsigned_type = - typename random_internal::make_unsigned_bits<IntType>::type; - - public: - using result_type = IntType; - - class param_type { - public: - using distribution_type = log_uniform_int_distribution; - - explicit param_type( - result_type min = 0, - result_type max = (std::numeric_limits<result_type>::max)(), - result_type base = 2) - : min_(min), - max_(max), - base_(base), - range_(static_cast<unsigned_type>(max_) - - static_cast<unsigned_type>(min_)), - log_range_(0) { - assert(max_ >= min_); - assert(base_ > 1); - - if (base_ == 2) { - // Determine where the first set bit is on range(), giving a log2(range) - // value which can be used to construct bounds. - log_range_ = (std::min)(random_internal::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 >= - // 2^53, which may cause some log() computations to operate on - // different values. - // 2. The error introduced by the division will cause the result - // to differ from the expected value. - // - // Thus a result which should equal K may equal K +/- epsilon, - // which can eliminate some values depending on where the bounds fall. - const double inv_log_base = 1.0 / std::log(base_); - const double log_range = std::log(static_cast<double>(range()) + 0.5); - log_range_ = static_cast<int>(std::ceil(inv_log_base * log_range)); - } - } - - result_type(min)() const { return min_; } - result_type(max)() const { return max_; } - result_type base() const { return base_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.min_ == b.min_ && a.max_ == b.max_ && a.base_ == b.base_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class log_uniform_int_distribution; - - int log_range() const { return log_range_; } - unsigned_type range() const { return range_; } - - result_type min_; - result_type max_; - result_type base_; - unsigned_type range_; // max - min - int log_range_; // ceil(logN(range_)) - - static_assert(std::is_integral<IntType>::value, - "Class-template absl::log_uniform_int_distribution<> must be " - "parameterized using an integral type."); - }; - - log_uniform_int_distribution() : log_uniform_int_distribution(0) {} - - explicit log_uniform_int_distribution( - result_type min, - result_type max = (std::numeric_limits<result_type>::max)(), - result_type base = 2) - : param_(min, max, base) {} - - explicit log_uniform_int_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - // generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p) { - return (p.min)() + Generate(g, p); - } - - result_type(min)() const { return (param_.min)(); } - result_type(max)() const { return (param_.max)(); } - result_type base() const { return param_.base(); } - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - friend bool operator==(const log_uniform_int_distribution& a, - const log_uniform_int_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const log_uniform_int_distribution& a, - const log_uniform_int_distribution& b) { - return a.param_ != b.param_; - } - - private: - // Returns a log-uniform variate in the range [0, p.range()]. The caller - // should add min() to shift the result to the correct range. - template <typename URNG> - unsigned_type Generate(URNG& g, // NOLINT(runtime/references) - const param_type& p); - - param_type param_; -}; - -template <typename IntType> -template <typename URBG> -typename log_uniform_int_distribution<IntType>::unsigned_type -log_uniform_int_distribution<IntType>::Generate( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - // sample e over [0, log_range]. Map the results of e to this: - // 0 => 0 - // 1 => [1, b-1] - // 2 => [b, (b^2)-1] - // n => [b^(n-1)..(b^n)-1] - const int e = absl::uniform_int_distribution<int>(0, p.log_range())(g); - if (e == 0) { - return 0; - } - const int d = e - 1; - - unsigned_type base_e, top_e; - if (p.base() == 2) { - base_e = static_cast<unsigned_type>(1) << d; - - top_e = (e >= std::numeric_limits<unsigned_type>::digits) - ? (std::numeric_limits<unsigned_type>::max)() - : (static_cast<unsigned_type>(1) << e) - 1; - } else { - const double r = std::pow(p.base(), d); - const double s = (r * p.base()) - 1.0; - - base_e = - (r > static_cast<double>((std::numeric_limits<unsigned_type>::max)())) - ? (std::numeric_limits<unsigned_type>::max)() - : static_cast<unsigned_type>(r); - - top_e = - (s > static_cast<double>((std::numeric_limits<unsigned_type>::max)())) - ? (std::numeric_limits<unsigned_type>::max)() - : static_cast<unsigned_type>(s); - } - - const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e; - const unsigned_type hi = (top_e >= p.range()) ? p.range() : top_e; - - // choose uniformly over [lo, hi] - return absl::uniform_int_distribution<result_type>(lo, hi)(g); -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const log_uniform_int_distribution<IntType>& x) { - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - auto saver = random_internal::make_ostream_state_saver(os); - os << static_cast<stream_type>((x.min)()) << os.fill() - << static_cast<stream_type>((x.max)()) << os.fill() - << static_cast<stream_type>(x.base()); - return os; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - log_uniform_int_distribution<IntType>& x) { // NOLINT(runtime/references) - using param_type = typename log_uniform_int_distribution<IntType>::param_type; - using result_type = - typename log_uniform_int_distribution<IntType>::result_type; - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - - stream_type min; - stream_type max; - stream_type base; - - auto saver = random_internal::make_istream_state_saver(is); - is >> min >> max >> base; - if (!is.fail()) { - x.param(param_type(static_cast<result_type>(min), - static_cast<result_type>(max), - static_cast<result_type>(base))); - } - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_ diff --git a/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 deleted file mode 100644 index 5e780d96d306..000000000000 --- a/third_party/abseil_cpp/absl/random/log_uniform_int_distribution_test.cc +++ /dev/null @@ -1,280 +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/log_uniform_int_distribution.h" - -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <random> -#include <sstream> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -namespace { - -template <typename IntType> -class LogUniformIntDistributionTypeTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<int8_t, int16_t, int32_t, int64_t, // - uint8_t, uint16_t, uint32_t, uint64_t>; -TYPED_TEST_CASE(LogUniformIntDistributionTypeTest, IntTypes); - -TYPED_TEST(LogUniformIntDistributionTypeTest, SerializeTest) { - using param_type = - typename absl::log_uniform_int_distribution<TypeParam>::param_type; - using Limits = std::numeric_limits<TypeParam>; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - for (const auto& param : { - param_type(0, 1), // - param_type(0, 2), // - param_type(0, 2, 10), // - param_type(9, 32, 4), // - param_type(1, 101, 10), // - param_type(1, Limits::max() / 2), // - param_type(0, Limits::max() - 1), // - param_type(0, Limits::max(), 2), // - param_type(0, Limits::max(), 10), // - param_type(Limits::min(), 0), // - param_type(Limits::lowest(), Limits::max()), // - param_type(Limits::min(), Limits::max()), // - }) { - // Validate parameters. - const auto min = param.min(); - const auto max = param.max(); - const auto base = param.base(); - absl::log_uniform_int_distribution<TypeParam> before(min, max, base); - EXPECT_EQ(before.min(), param.min()); - EXPECT_EQ(before.max(), param.max()); - EXPECT_EQ(before.base(), param.base()); - - { - absl::log_uniform_int_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - } - - // Validate stream serialization. - std::stringstream ss; - ss << before; - - absl::log_uniform_int_distribution<TypeParam> after(3, 6, 17); - - EXPECT_NE(before.max(), after.max()); - EXPECT_NE(before.base(), after.base()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.min(), after.min()); - EXPECT_EQ(before.max(), after.max()); - EXPECT_EQ(before.base(), after.base()); - EXPECT_EQ(before.param(), after.param()); - EXPECT_EQ(before, after); - - // Smoke test. - auto sample_min = after.max(); - auto sample_max = after.min(); - for (int i = 0; i < kCount; i++) { - auto sample = after(gen); - EXPECT_GE(sample, after.min()); - EXPECT_LE(sample, after.max()); - if (sample > sample_max) sample_max = sample; - if (sample < sample_min) sample_min = sample; - } - ABSL_INTERNAL_LOG(INFO, - absl::StrCat("Range: ", +sample_min, ", ", +sample_max)); - } -} - -using log_uniform_i32 = absl::log_uniform_int_distribution<int32_t>; - -class LogUniformIntChiSquaredTest - : public testing::TestWithParam<log_uniform_i32::param_type> { - public: - // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for - // data generated by the log-uniform-int distribution. - double ChiSquaredTestImpl(); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -double LogUniformIntChiSquaredTest::ChiSquaredTestImpl() { - using absl::random_internal::kChiSquared; - - const auto& param = GetParam(); - - // Check the distribution of L=log(log_uniform_int_distribution, base), - // expecting that L is roughly uniformly distributed, that is: - // - // P[L=0] ~= P[L=1] ~= ... ~= P[L=log(max)] - // - // For a total of X entries, each bucket should contain some number of samples - // in the interval [X/k - a, X/k + a]. - // - // Where `a` is approximately sqrt(X/k). This is validated by bucketing - // according to the log function and using a chi-squared test for uniformity. - - const bool is_2 = (param.base() == 2); - const double base_log = 1.0 / std::log(param.base()); - const auto bucket_index = [base_log, is_2, ¶m](int32_t x) { - uint64_t y = static_cast<uint64_t>(x) - param.min(); - return (y == 0) ? 0 - : is_2 ? static_cast<int>(1 + std::log2(y)) - : static_cast<int>(1 + std::log(y) * base_log); - }; - const int max_bucket = bucket_index(param.max()); // inclusive - const size_t trials = 15 + (max_bucket + 1) * 10; - - log_uniform_i32 dist(param); - - std::vector<int64_t> buckets(max_bucket + 1); - for (size_t i = 0; i < trials; ++i) { - const auto sample = dist(rng_); - // Check the bounds. - ABSL_ASSERT(sample <= dist.max()); - ABSL_ASSERT(sample >= dist.min()); - // Convert the output of the generator to one of num_bucket buckets. - int bucket = bucket_index(sample); - ABSL_ASSERT(bucket <= max_bucket); - ++buckets[bucket]; - } - - // The null-hypothesis is that the distribution is uniform with respect to - // log-uniform-int bucketization. - const int dof = buckets.size() - 1; - const double expected = trials / static_cast<double>(buckets.size()); - - const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98); - - double chi_square = absl::random_internal::ChiSquareWithExpected( - std::begin(buckets), std::end(buckets), expected); - - const double p = absl::random_internal::ChiSquarePValue(chi_square, dof); - - if (chi_square > threshold) { - ABSL_INTERNAL_LOG(INFO, "values"); - for (size_t i = 0; i < buckets.size(); i++) { - ABSL_INTERNAL_LOG(INFO, absl::StrCat(i, ": ", buckets[i])); - } - ABSL_INTERNAL_LOG(INFO, - absl::StrFormat("trials=%d\n" - "%s(data, %d) = %f (%f)\n" - "%s @ 0.98 = %f", - trials, kChiSquared, dof, chi_square, p, - kChiSquared, threshold)); - } - return p; -} - -TEST_P(LogUniformIntChiSquaredTest, MultiTest) { - const int kTrials = 5; - int failures = 0; - for (int i = 0; i < kTrials; i++) { - double p_value = ChiSquaredTestImpl(); - if (p_value < 0.005) { - failures++; - } - } - - // There is a 0.10% chance of producing at least one failure, so raise the - // failure threshold high enough to allow for a flake rate < 10,000. - EXPECT_LE(failures, 4); -} - -// Generate the parameters for the test. -std::vector<log_uniform_i32::param_type> GenParams() { - using Param = log_uniform_i32::param_type; - using Limits = std::numeric_limits<int32_t>; - - return std::vector<Param>{ - Param{0, 1, 2}, - Param{1, 1, 2}, - Param{0, 2, 2}, - Param{0, 3, 2}, - Param{0, 4, 2}, - Param{0, 9, 10}, - Param{0, 10, 10}, - Param{0, 11, 10}, - Param{1, 10, 10}, - Param{0, (1 << 8) - 1, 2}, - Param{0, (1 << 8), 2}, - Param{0, (1 << 30) - 1, 2}, - Param{-1000, 1000, 10}, - Param{0, Limits::max(), 2}, - Param{0, Limits::max(), 3}, - Param{0, Limits::max(), 10}, - Param{Limits::min(), 0}, - Param{Limits::min(), Limits::max(), 2}, - }; -} - -std::string ParamName( - const ::testing::TestParamInfo<log_uniform_i32::param_type>& info) { - const auto& p = info.param; - std::string name = - absl::StrCat("min_", p.min(), "__max_", p.max(), "__base_", p.base()); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_SUITE_P(All, LogUniformIntChiSquaredTest, - ::testing::ValuesIn(GenParams()), ParamName); - -// NOTE: absl::log_uniform_int_distribution is not guaranteed to be stable. -TEST(LogUniformIntDistributionTest, StabilityTest) { - using testing::ElementsAre; - // absl::uniform_int_distribution stability relies on - // absl::random_internal::LeadingSetBit, std::log, std::pow. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(6); - - { - absl::log_uniform_int_distribution<int32_t> dist(0, 256); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - EXPECT_THAT(output, ElementsAre(256, 66, 4, 6, 57, 103)); - } - urbg.reset(); - { - absl::log_uniform_int_distribution<int32_t> dist(0, 256, 10); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - EXPECT_THAT(output, ElementsAre(8, 4, 0, 0, 0, 69)); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/mock_distributions.h b/third_party/abseil_cpp/absl/random/mock_distributions.h deleted file mode 100644 index 764ab370abeb..000000000000 --- a/third_party/abseil_cpp/absl/random/mock_distributions.h +++ /dev/null @@ -1,266 +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: mock_distributions.h -// ----------------------------------------------------------------------------- -// -// This file contains mock distribution functions for use alongside an -// `absl::MockingBitGen` object within the Googletest testing framework. Such -// mocks are useful to provide deterministic values as return values within -// (otherwise random) Abseil distribution functions. -// -// The return type of each function is a mock expectation object which -// is used to set the match result. -// -// More information about the Googletest testing framework is available at -// https://github.com/google/googletest -// -// EXPECT_CALL and ON_CALL need to be made within the same DLL component as -// the call to absl::Uniform and related methods, otherwise mocking will fail -// since the underlying implementation creates a type-specific pointer which -// will be distinct across different DLL boundaries. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockUniform<int>(), Call(mock, 1, 1000)) -// .WillRepeatedly(testing::ReturnRoundRobin({20, 40})); -// -// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20); -// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40); -// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20); -// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40); - -#ifndef ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_ -#define ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_ - -#include <limits> -#include <type_traits> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/random/distributions.h" -#include "absl/random/internal/mock_overload_set.h" -#include "absl/random/mocking_bit_gen.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// absl::MockUniform -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Uniform. -// -// `absl::MockUniform` is a class template used in conjunction with Googletest's -// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an -// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the -// same way one would define mocks on a Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(mock)) -// .WillOnce(Return(123456)); -// auto x = absl::Uniform<uint32_t>(mock); -// assert(x == 123456) -// -template <typename R> -using MockUniform = random_internal::MockOverloadSet< - random_internal::UniformDistributionWrapper<R>, - R(IntervalClosedOpenTag, MockingBitGen&, R, R), - R(IntervalClosedClosedTag, MockingBitGen&, R, R), - R(IntervalOpenOpenTag, MockingBitGen&, R, R), - R(IntervalOpenClosedTag, MockingBitGen&, R, R), R(MockingBitGen&, R, R), - R(MockingBitGen&)>; - -// ----------------------------------------------------------------------------- -// absl::MockBernoulli -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Bernoulli. -// -// `absl::MockBernoulli` is a class used in conjunction with Googletest's -// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an -// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the -// same way one would define mocks on a Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockBernoulli(), Call(mock, testing::_)) -// .WillOnce(Return(false)); -// assert(absl::Bernoulli(mock, 0.5) == false); -// -using MockBernoulli = - random_internal::MockOverloadSet<absl::bernoulli_distribution, - bool(MockingBitGen&, double)>; - -// ----------------------------------------------------------------------------- -// absl::MockBeta -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Beta. -// -// `absl::MockBeta` is a class used in conjunction with Googletest's `ON_CALL()` -// and `EXPECT_CALL()` macros. To use it, default-construct an instance of it -// inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the same way one -// would define mocks on a Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockBeta(), Call(mock, 3.0, 2.0)) -// .WillOnce(Return(0.567)); -// auto x = absl::Beta<double>(mock, 3.0, 2.0); -// assert(x == 0.567); -// -template <typename RealType> -using MockBeta = - random_internal::MockOverloadSet<absl::beta_distribution<RealType>, - RealType(MockingBitGen&, RealType, - RealType)>; - -// ----------------------------------------------------------------------------- -// absl::MockExponential -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Exponential. -// -// `absl::MockExponential` is a class template used in conjunction with -// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it, -// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`, -// and use `Call(...)` the same way one would define mocks on a -// Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockExponential<double>(), Call(mock, 0.5)) -// .WillOnce(Return(12.3456789)); -// auto x = absl::Exponential<double>(mock, 0.5); -// assert(x == 12.3456789) -// -template <typename RealType> -using MockExponential = - random_internal::MockOverloadSet<absl::exponential_distribution<RealType>, - RealType(MockingBitGen&, RealType)>; - -// ----------------------------------------------------------------------------- -// absl::MockGaussian -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Gaussian. -// -// `absl::MockGaussian` is a class template used in conjunction with -// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it, -// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`, -// and use `Call(...)` the same way one would define mocks on a -// Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockGaussian<double>(), Call(mock, 16.3, 3.3)) -// .WillOnce(Return(12.3456789)); -// auto x = absl::Gaussian<double>(mock, 16.3, 3.3); -// assert(x == 12.3456789) -// -template <typename RealType> -using MockGaussian = - random_internal::MockOverloadSet<absl::gaussian_distribution<RealType>, - RealType(MockingBitGen&, RealType, - RealType)>; - -// ----------------------------------------------------------------------------- -// absl::MockLogUniform -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::LogUniform. -// -// `absl::MockLogUniform` is a class template used in conjunction with -// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it, -// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`, -// and use `Call(...)` the same way one would define mocks on a -// Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockLogUniform<int>(), Call(mock, 10, 10000, 10)) -// .WillOnce(Return(1221)); -// auto x = absl::LogUniform<int>(mock, 10, 10000, 10); -// assert(x == 1221) -// -template <typename IntType> -using MockLogUniform = random_internal::MockOverloadSet< - absl::log_uniform_int_distribution<IntType>, - IntType(MockingBitGen&, IntType, IntType, IntType)>; - -// ----------------------------------------------------------------------------- -// absl::MockPoisson -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Poisson. -// -// `absl::MockPoisson` is a class template used in conjunction with Googletest's -// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an -// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the -// same way one would define mocks on a Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockPoisson<int>(), Call(mock, 2.0)) -// .WillOnce(Return(1221)); -// auto x = absl::Poisson<int>(mock, 2.0); -// assert(x == 1221) -// -template <typename IntType> -using MockPoisson = - random_internal::MockOverloadSet<absl::poisson_distribution<IntType>, - IntType(MockingBitGen&, double)>; - -// ----------------------------------------------------------------------------- -// absl::MockZipf -// ----------------------------------------------------------------------------- -// -// Matches calls to absl::Zipf. -// -// `absl::MockZipf` is a class template used in conjunction with Googletest's -// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an -// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the -// same way one would define mocks on a Googletest `MockFunction()`. -// -// Example: -// -// absl::MockingBitGen mock; -// EXPECT_CALL(absl::MockZipf<int>(), Call(mock, 1000000, 2.0, 1.0)) -// .WillOnce(Return(1221)); -// auto x = absl::Zipf<int>(mock, 1000000, 2.0, 1.0); -// assert(x == 1221) -// -template <typename IntType> -using MockZipf = - random_internal::MockOverloadSet<absl::zipf_distribution<IntType>, - IntType(MockingBitGen&, IntType, double, - double)>; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_ diff --git a/third_party/abseil_cpp/absl/random/mock_distributions_test.cc b/third_party/abseil_cpp/absl/random/mock_distributions_test.cc deleted file mode 100644 index de23bafe1e55..000000000000 --- a/third_party/abseil_cpp/absl/random/mock_distributions_test.cc +++ /dev/null @@ -1,72 +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/random/mock_distributions.h" - -#include "gtest/gtest.h" -#include "absl/random/mocking_bit_gen.h" -#include "absl/random/random.h" - -namespace { -using ::testing::Return; - -TEST(MockDistributions, Examples) { - absl::MockingBitGen gen; - - EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20); - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000)) - .WillOnce(Return(20)); - EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20); - - EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0)) - .WillOnce(Return(5.0)); - EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - - EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42); - EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0)) - .WillOnce(Return(42)); - EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42); - - EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500); - EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500)); - EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500); - - EXPECT_NE(absl::Bernoulli(gen, 0.000001), true); - EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001)) - .WillOnce(Return(true)); - EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true); - - EXPECT_NE(absl::Beta<double>(gen, 3.0, 2.0), 0.567); - EXPECT_CALL(absl::MockBeta<double>(), Call(gen, 3.0, 2.0)) - .WillOnce(Return(0.567)); - EXPECT_EQ(absl::Beta<double>(gen, 3.0, 2.0), 0.567); - - EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0)) - .WillOnce(Return(1221)); - EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - - EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0)) - .WillOnce(Return(0.001)); - EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - - EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040); - EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2)) - .WillOnce(Return(2040)); - EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/mocking_bit_gen.h b/third_party/abseil_cpp/absl/random/mocking_bit_gen.h deleted file mode 100644 index 6d2f2c836245..000000000000 --- a/third_party/abseil_cpp/absl/random/mocking_bit_gen.h +++ /dev/null @@ -1,228 +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. -// -// ----------------------------------------------------------------------------- -// mocking_bit_gen.h -// ----------------------------------------------------------------------------- -// -// This file includes an `absl::MockingBitGen` class to use as a mock within the -// Googletest testing framework. Such a mock is useful to provide deterministic -// values as return values within (otherwise random) Abseil distribution -// functions. Such determinism within a mock is useful within testing frameworks -// to test otherwise indeterminate APIs. -// -// More information about the Googletest testing framework is available at -// https://github.com/google/googletest - -#ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_ -#define ABSL_RANDOM_MOCKING_BIT_GEN_H_ - -#include <iterator> -#include <limits> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/fast_type_id.h" -#include "absl/container/flat_hash_map.h" -#include "absl/meta/type_traits.h" -#include "absl/random/distributions.h" -#include "absl/random/internal/distribution_caller.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" -#include "absl/types/span.h" -#include "absl/types/variant.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace random_internal { -template <typename> -struct DistributionCaller; -class MockHelpers; - -} // namespace random_internal -class BitGenRef; - -// MockingBitGen -// -// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class -// which can act in place of an `absl::BitGen` URBG within tests using the -// Googletest testing framework. -// -// Usage: -// -// Use an `absl::MockingBitGen` along with a mock distribution object (within -// mock_distributions.h) inside Googletest constructs such as ON_CALL(), -// EXPECT_TRUE(), etc. to produce deterministic results conforming to the -// distribution's API contract. -// -// Example: -// -// // Mock a call to an `absl::Bernoulli` distribution using Googletest -// absl::MockingBitGen bitgen; -// -// ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5)) -// .WillByDefault(testing::Return(true)); -// EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5)); -// -// // Mock a call to an `absl::Uniform` distribution within Googletest -// absl::MockingBitGen bitgen; -// -// ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_)) -// .WillByDefault([] (int low, int high) { -// return (low + high) / 2; -// }); -// -// EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5); -// EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35); -// -// At this time, only mock distributions supplied within the Abseil random -// library are officially supported. -// -// EXPECT_CALL and ON_CALL need to be made within the same DLL component as -// the call to absl::Uniform and related methods, otherwise mocking will fail -// since the underlying implementation creates a type-specific pointer which -// will be distinct across different DLL boundaries. -// -class MockingBitGen { - public: - MockingBitGen() = default; - - ~MockingBitGen() { - for (const auto& del : deleters_) del(); - } - - // URBG interface - using result_type = absl::BitGen::result_type; - - static constexpr result_type(min)() { return (absl::BitGen::min)(); } - static constexpr result_type(max)() { return (absl::BitGen::max)(); } - result_type operator()() { return gen_(); } - - private: - using match_impl_fn = void (*)(void* mock_fn, void* t_erased_arg_tuple, - void* t_erased_result); - - struct MockData { - void* mock_fn = nullptr; - match_impl_fn match_impl = nullptr; - }; - - // 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 ResultT, typename MockFnType, typename Tuple> - struct MockFnCaller; - // specialization for std::tuple. - template <typename ResultT, typename MockFnType, typename... Args> - struct MockFnCaller<ResultT, MockFnType, std::tuple<Args...>> { - MockFnType* fn; - inline ResultT operator()(Args... args) { - return fn->Call(std::move(args)...); - } - }; - - // MockingBitGen::RegisterMock - // - // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension - // point for extending the MockingBitGen framework. It provides a mechanism to - // install a mock expectation for a function like ResultT(Args...) keyed by - // type_idex onto the MockingBitGen context. The key is that the type_index - // used to register must match the type index used to call the mock. - // - // The returned MockFunction<...> type can be used to setup additional - // distribution parameters of the expectation. - template <typename ResultT, typename ArgTupleT> - auto RegisterMock(base_internal::FastTypeIdType type) - -> decltype(GetMockFnType(std::declval<ResultT>(), - std::declval<ArgTupleT>()))& { - using MockFnType = decltype( - GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>())); - auto& mock = mocks_[type]; - if (!mock.mock_fn) { - auto* mock_fn = new MockFnType; - mock.mock_fn = mock_fn; - mock.match_impl = &MatchImpl<ResultT, ArgTupleT>; - deleters_.emplace_back([mock_fn] { delete mock_fn; }); - } - return *static_cast<MockFnType*>(mock.mock_fn); - } - - // MockingBitGen::MatchImpl<> is a dispatch function which converts the - // generic type-erased parameters into a specific mock invocation call. - // 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. - template <typename ResultT, typename ArgTupleT> - static void MatchImpl(/*MockFnType<ResultT, Args...>*/ void* mock_fn, - /*ArgTupleT*/ void* args_tuple, - /*ResultT*/ void* result) { - using MockFnType = decltype( - GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>())); - *static_cast<ResultT*>(result) = absl::apply( - MockFnCaller<ResultT, MockFnType, ArgTupleT>{ - static_cast<MockFnType*>(mock_fn)}, - *static_cast<ArgTupleT*>(args_tuple)); - } - - // MockingBitGen::InvokeMock - // - // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking - // mocks registered on MockingBitGen. - // - // When no mocks are registered on the provided FastTypeIdType, returns false. - // Otherwise attempts to invoke the mock function ResultT(Args...) that - // was previously registered via the type_index. - // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...> - // used to invoke the mock function. - // Requires result to point to a ResultT, which is the result of the call. - inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple, - void* result) { - // Trigger a mock, if there exists one that matches `param`. - auto it = mocks_.find(type); - if (it == mocks_.end()) return false; - auto* mock_data = static_cast<MockData*>(&it->second); - mock_data->match_impl(mock_data->mock_fn, args_tuple, result); - return true; - } - - absl::flat_hash_map<base_internal::FastTypeIdType, MockData> mocks_; - std::vector<std::function<void()>> deleters_; - absl::BitGen gen_; - - template <typename> - friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock - friend class ::absl::BitGenRef; // for InvokeMock - friend class ::absl::random_internal::MockHelpers; // for RegisterMock, - // InvokeMock -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_ diff --git a/third_party/abseil_cpp/absl/random/mocking_bit_gen_test.cc b/third_party/abseil_cpp/absl/random/mocking_bit_gen_test.cc deleted file mode 100644 index f0ffc9ac9283..000000000000 --- a/third_party/abseil_cpp/absl/random/mocking_bit_gen_test.cc +++ /dev/null @@ -1,347 +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/random/mocking_bit_gen.h" - -#include <numeric> -#include <random> - -#include "gmock/gmock.h" -#include "gtest/gtest-spi.h" -#include "gtest/gtest.h" -#include "absl/random/bit_gen_ref.h" -#include "absl/random/mock_distributions.h" -#include "absl/random/random.h" - -namespace { -using ::testing::Ne; -using ::testing::Return; - -TEST(BasicMocking, AllDistributionsAreOverridable) { - absl::MockingBitGen gen; - - EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20); - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000)) - .WillOnce(Return(20)); - EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20); - - EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0)) - .WillOnce(Return(5.0)); - EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - - EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42); - EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0)) - .WillOnce(Return(42)); - EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42); - - EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500); - EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500)); - EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500); - - EXPECT_NE(absl::Bernoulli(gen, 0.000001), true); - EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001)) - .WillOnce(Return(true)); - EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true); - - EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0)) - .WillOnce(Return(1221)); - EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - - EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0)) - .WillOnce(Return(0.001)); - EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - - EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000); - EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2)) - .WillOnce(Return(500000)); - EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000); -} - -TEST(BasicMocking, OnDistribution) { - absl::MockingBitGen gen; - - EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20); - ON_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000)) - .WillByDefault(Return(20)); - EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20); - - EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - ON_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0)) - .WillByDefault(Return(5.0)); - EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0); - - EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42); - ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0)) - .WillByDefault(Return(42)); - EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42); - - EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500); - ON_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillByDefault(Return(500)); - EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500); - - EXPECT_NE(absl::Bernoulli(gen, 0.000001), true); - ON_CALL(absl::MockBernoulli(), Call(gen, 0.000001)) - .WillByDefault(Return(true)); - EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true); - - EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0)) - .WillByDefault(Return(1221)); - EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - - EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - ON_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0)) - .WillByDefault(Return(0.001)); - EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001); - - EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040); - ON_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2)) - .WillByDefault(Return(2040)); - EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040); -} - -TEST(BasicMocking, GMockMatchers) { - absl::MockingBitGen gen; - - EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); - ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0)) - .WillByDefault(Return(1221)); - EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221); -} - -TEST(BasicMocking, OverridesWithMultipleGMockExpectations) { - absl::MockingBitGen gen; - - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 10000)) - .WillOnce(Return(20)) - .WillOnce(Return(40)) - .WillOnce(Return(60)); - EXPECT_EQ(absl::Uniform(gen, 1, 10000), 20); - EXPECT_EQ(absl::Uniform(gen, 1, 10000), 40); - EXPECT_EQ(absl::Uniform(gen, 1, 10000), 60); -} - -TEST(BasicMocking, DefaultArgument) { - absl::MockingBitGen gen; - - ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0)) - .WillByDefault(Return(200)); - - EXPECT_EQ(absl::Exponential<double>(gen), 200); - EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 200); -} - -TEST(BasicMocking, MultipleGenerators) { - auto get_value = [](absl::BitGenRef gen_ref) { - return absl::Uniform(gen_ref, 1, 1000000); - }; - absl::MockingBitGen unmocked_generator; - absl::MockingBitGen mocked_with_3; - absl::MockingBitGen mocked_with_11; - - EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_3, 1, 1000000)) - .WillOnce(Return(3)) - .WillRepeatedly(Return(17)); - EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_11, 1, 1000000)) - .WillOnce(Return(11)) - .WillRepeatedly(Return(17)); - - // Ensure that unmocked generator generates neither value. - int unmocked_value = get_value(unmocked_generator); - EXPECT_NE(unmocked_value, 3); - EXPECT_NE(unmocked_value, 11); - // Mocked generators should generate their mocked values. - EXPECT_EQ(get_value(mocked_with_3), 3); - EXPECT_EQ(get_value(mocked_with_11), 11); - // Ensure that the mocks have expired. - EXPECT_NE(get_value(mocked_with_3), 3); - EXPECT_NE(get_value(mocked_with_11), 11); -} - -TEST(BasicMocking, MocksNotTrigeredForIncorrectTypes) { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42)); - - EXPECT_NE(absl::Uniform<uint16_t>(gen), 42); // Not mocked - EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42); // Mock triggered -} - -TEST(BasicMocking, FailsOnUnsatisfiedMocks) { - EXPECT_NONFATAL_FAILURE( - []() { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0)) - .WillOnce(Return(3.0)); - // Does not call absl::Exponential(). - }(), - "unsatisfied and active"); -} - -TEST(OnUniform, RespectsUniformIntervalSemantics) { - absl::MockingBitGen gen; - - EXPECT_CALL(absl::MockUniform<int>(), - Call(absl::IntervalClosed, gen, 1, 1000000)) - .WillOnce(Return(301)); - EXPECT_NE(absl::Uniform(gen, 1, 1000000), 301); // Not mocked - EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 1, 1000000), 301); -} - -TEST(OnUniform, RespectsNoArgUnsignedShorthand) { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42)); - EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42); -} - -TEST(RepeatedlyModifier, ForceSnakeEyesForManyDice) { - auto roll_some_dice = [](absl::BitGenRef gen_ref) { - std::vector<int> results(16); - for (auto& r : results) { - r = absl::Uniform(absl::IntervalClosed, gen_ref, 1, 6); - } - return results; - }; - std::vector<int> results; - absl::MockingBitGen gen; - - // Without any mocked calls, not all dice roll a "6". - results = roll_some_dice(gen); - EXPECT_LT(std::accumulate(std::begin(results), std::end(results), 0), - results.size() * 6); - - // Verify that we can force all "6"-rolls, with mocking. - ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, 1, 6)) - .WillByDefault(Return(6)); - results = roll_some_dice(gen); - EXPECT_EQ(std::accumulate(std::begin(results), std::end(results), 0), - results.size() * 6); -} - -TEST(WillOnce, DistinctCounters) { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000)) - .Times(3) - .WillRepeatedly(Return(0)); - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1000001, 2000000)) - .Times(3) - .WillRepeatedly(Return(1)); - EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0); - EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0); - EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0); -} - -TEST(TimesModifier, ModifierSaturatesAndExpires) { - EXPECT_NONFATAL_FAILURE( - []() { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000)) - .Times(3) - .WillRepeatedly(Return(15)) - .RetiresOnSaturation(); - - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15); - // Times(3) has expired - Should get a different value now. - - EXPECT_NE(absl::Uniform(gen, 1, 1000000), 15); - }(), - ""); -} - -TEST(TimesModifier, Times0) { - absl::MockingBitGen gen; - EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.0)).Times(0); - EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).Times(0); -} - -TEST(AnythingMatcher, MatchesAnyArgument) { - using testing::_; - - { - absl::MockingBitGen gen; - ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, _, 1000)) - .WillByDefault(Return(11)); - ON_CALL(absl::MockUniform<int>(), - Call(absl::IntervalClosed, gen, _, Ne(1000))) - .WillByDefault(Return(99)); - - EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000000), 99); - EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000), 11); - } - - { - absl::MockingBitGen gen; - ON_CALL(absl::MockUniform<int>(), Call(gen, 1, _)) - .WillByDefault(Return(25)); - ON_CALL(absl::MockUniform<int>(), Call(gen, Ne(1), _)) - .WillByDefault(Return(99)); - EXPECT_EQ(absl::Uniform(gen, 3, 1000000), 99); - EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 25); - } - - { - absl::MockingBitGen gen; - ON_CALL(absl::MockUniform<int>(), Call(gen, _, _)) - .WillByDefault(Return(145)); - EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145); - EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145); - EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145); - } -} - -TEST(AnythingMatcher, WithWillByDefault) { - using testing::_; - absl::MockingBitGen gen; - std::vector<int> values = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010}; - - ON_CALL(absl::MockUniform<size_t>(), Call(gen, 0, _)) - .WillByDefault(Return(0)); - for (int i = 0; i < 100; i++) { - auto& elem = values[absl::Uniform(gen, 0u, values.size())]; - EXPECT_EQ(elem, 11); - } -} - -TEST(BasicMocking, WillByDefaultWithArgs) { - using testing::_; - - absl::MockingBitGen gen; - ON_CALL(absl::MockPoisson<int>(), Call(gen, _)) - .WillByDefault( - [](double lambda) { return static_cast<int>(lambda * 10); }); - EXPECT_EQ(absl::Poisson<int>(gen, 1.7), 17); - EXPECT_EQ(absl::Poisson<int>(gen, 0.03), 0); -} - -TEST(MockingBitGen, InSequenceSucceedsInOrder) { - absl::MockingBitGen gen; - - testing::InSequence seq; - - EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(3)); - EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 2.0)).WillOnce(Return(4)); - - EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 3); - EXPECT_EQ(absl::Poisson<int>(gen, 2.0), 4); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/poisson_distribution.h b/third_party/abseil_cpp/absl/random/poisson_distribution.h deleted file mode 100644 index cb5f5d5d0ff7..000000000000 --- a/third_party/abseil_cpp/absl/random/poisson_distribution.h +++ /dev/null @@ -1,258 +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. - -#ifndef ABSL_RANDOM_POISSON_DISTRIBUTION_H_ -#define ABSL_RANDOM_POISSON_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <ostream> -#include <type_traits> - -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::poisson_distribution: -// Generates discrete variates conforming to a Poisson distribution. -// p(n) = (mean^n / n!) exp(-mean) -// -// Depending on the parameter, the distribution selects one of the following -// algorithms: -// * The standard algorithm, attributed to Knuth, extended using a split method -// for larger values -// * The "Ratio of Uniforms as a convenient method for sampling from classical -// discrete distributions", Stadlober, 1989. -// http://www.sciencedirect.com/science/article/pii/0377042790903495 -// -// NOTE: param_type.mean() is a double, which permits values larger than -// poisson_distribution<IntType>::max(), however this should be avoided and -// the distribution results are limited to the max() value. -// -// The goals of this implementation are to provide good performance while still -// beig thread-safe: This limits the implementation to not using lgamma provided -// by <math.h>. -// -template <typename IntType = int> -class poisson_distribution { - public: - using result_type = IntType; - - class param_type { - public: - using distribution_type = poisson_distribution; - explicit param_type(double mean = 1.0); - - double mean() const { return mean_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.mean_ == b.mean_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class poisson_distribution; - - double mean_; - double emu_; // e ^ -mean_ - double lmu_; // ln(mean_) - double s_; - double log_k_; - int split_; - - static_assert(std::is_integral<IntType>::value, - "Class-template absl::poisson_distribution<> must be " - "parameterized using an integral type."); - }; - - poisson_distribution() : poisson_distribution(1.0) {} - - explicit poisson_distribution(double mean) : param_(mean) {} - - explicit poisson_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - // generating functions - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { return 0; } - result_type(max)() const { return (std::numeric_limits<result_type>::max)(); } - - double mean() const { return param_.mean(); } - - friend bool operator==(const poisson_distribution& a, - const poisson_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const poisson_distribution& a, - const poisson_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; - random_internal::FastUniformBits<uint64_t> fast_u64_; -}; - -// ----------------------------------------------------------------------------- -// Implementation details follow -// ----------------------------------------------------------------------------- - -template <typename IntType> -poisson_distribution<IntType>::param_type::param_type(double mean) - : mean_(mean), split_(0) { - assert(mean >= 0); - assert(mean <= (std::numeric_limits<result_type>::max)()); - // As a defensive measure, avoid large values of the mean. The rejection - // algorithm used does not support very large values well. It my be worth - // changing algorithms to better deal with these cases. - assert(mean <= 1e10); - if (mean_ < 10) { - // For small lambda, use the knuth method. - split_ = 1; - emu_ = std::exp(-mean_); - } else if (mean_ <= 50) { - // Use split-knuth method. - split_ = 1 + static_cast<int>(mean_ / 10.0); - emu_ = std::exp(-mean_ / static_cast<double>(split_)); - } else { - // Use ratio of uniforms method. - constexpr double k2E = 0.7357588823428846; - constexpr double kSA = 0.4494580810294493; - - lmu_ = std::log(mean_); - double a = mean_ + 0.5; - s_ = kSA + std::sqrt(k2E * a); - const double mode = std::ceil(mean_) - 1; - log_k_ = lmu_ * mode - absl::random_internal::StirlingLogFactorial(mode); - } -} - -template <typename IntType> -template <typename URBG> -typename poisson_distribution<IntType>::result_type -poisson_distribution<IntType>::operator()( - URBG& g, // NOLINT(runtime/references) - const param_type& p) { - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - using random_internal::GenerateSignedTag; - - if (p.split_ != 0) { - // Use Knuth's algorithm with range splitting to avoid floating-point - // errors. Knuth's algorithm is: Ui is a sequence of uniform variates on - // (0,1); return the number of variates required for product(Ui) < - // exp(-lambda). - // - // The expected number of variates required for Knuth's method can be - // computed as follows: - // The expected value of U is 0.5, so solving for 0.5^n < exp(-lambda) gives - // the expected number of uniform variates - // required for a given lambda, which is: - // lambda = [2, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17] - // n = [3, 8, 13, 15, 16, 18, 19, 21, 22, 24, 25] - // - result_type n = 0; - for (int split = p.split_; split > 0; --split) { - double r = 1.0; - do { - r *= GenerateRealFromBits<double, GeneratePositiveTag, true>( - fast_u64_(g)); // U(-1, 0) - ++n; - } while (r > p.emu_); - --n; - } - return n; - } - - // Use ratio of uniforms method. - // - // Let u ~ Uniform(0, 1), v ~ Uniform(-1, 1), - // a = lambda + 1/2, - // s = 1.5 - sqrt(3/e) + sqrt(2(lambda + 1/2)/e), - // x = s * v/u + a. - // P(floor(x) = k | u^2 < f(floor(x))/k), where - // f(m) = lambda^m exp(-lambda)/ m!, for 0 <= m, and f(m) = 0 otherwise, - // and k = max(f). - const double a = p.mean_ + 0.5; - for (;;) { - const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>( - fast_u64_(g)); // U(0, 1) - const double v = GenerateRealFromBits<double, GenerateSignedTag, false>( - fast_u64_(g)); // U(-1, 1) - - const double x = std::floor(p.s_ * v / u + a); - if (x < 0) continue; // f(negative) = 0 - const double rhs = x * p.lmu_; - // clang-format off - double s = (x <= 1.0) ? 0.0 - : (x == 2.0) ? 0.693147180559945 - : absl::random_internal::StirlingLogFactorial(x); - // clang-format on - const double lhs = 2.0 * std::log(u) + p.log_k_ + s; - if (lhs < rhs) { - return x > (max)() ? (max)() - : static_cast<result_type>(x); // f(x)/k >= u^2 - } - } -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const poisson_distribution<IntType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<double>::kPrecision); - os << x.mean(); - return os; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - poisson_distribution<IntType>& x) { // NOLINT(runtime/references) - using param_type = typename poisson_distribution<IntType>::param_type; - - auto saver = random_internal::make_istream_state_saver(is); - double mean = random_internal::read_floating_point<double>(is); - if (!is.fail()) { - x.param(param_type(mean)); - } - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_POISSON_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/poisson_distribution_test.cc b/third_party/abseil_cpp/absl/random/poisson_distribution_test.cc deleted file mode 100644 index 8baabd111892..000000000000 --- a/third_party/abseil_cpp/absl/random/poisson_distribution_test.cc +++ /dev/null @@ -1,573 +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/poisson_distribution.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <random> -#include <sstream> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/container/flat_hash_map.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -// Notes about generating poisson variates: -// -// It is unlikely that any implementation of std::poisson_distribution -// will be stable over time and across library implementations. For instance -// the three different poisson variate generators listed below all differ: -// -// https://github.com/ampl/gsl/tree/master/randist/poisson.c -// * GSL uses a gamma + binomial + knuth method to compute poisson variates. -// -// https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/random.tcc -// * GCC uses the Devroye rejection algorithm, based on -// Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, -// New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!), ~p.511 -// http://www.nrbook.com/devroye/ -// -// https://github.com/llvm-mirror/libcxx/blob/master/include/random -// * CLANG uses a different rejection method, which appears to include a -// normal-distribution approximation and an exponential distribution to -// compute the threshold, including a similar factorial approximation to this -// one, but it is unclear where the algorithm comes from, exactly. -// - -namespace { - -using absl::random_internal::kChiSquared; - -// The PoissonDistributionInterfaceTest provides a basic test that -// absl::poisson_distribution conforms to the interface and serialization -// requirements imposed by [rand.req.dist] for the common integer types. - -template <typename IntType> -class PoissonDistributionInterfaceTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t, - uint8_t, uint16_t, uint32_t, uint64_t>; -TYPED_TEST_CASE(PoissonDistributionInterfaceTest, IntTypes); - -TYPED_TEST(PoissonDistributionInterfaceTest, SerializeTest) { - using param_type = typename absl::poisson_distribution<TypeParam>::param_type; - const double kMax = - std::min(1e10 /* assertion limit */, - static_cast<double>(std::numeric_limits<TypeParam>::max())); - - const double kParams[] = { - // Cases around 1. - 1, // - std::nextafter(1.0, 0.0), // 1 - epsilon - std::nextafter(1.0, 2.0), // 1 + epsilon - // Arbitrary values. - 1e-8, 1e-4, - 0.0000005, // ~7.2e-7 - 0.2, // ~0.2x - 0.5, // 0.72 - 2, // ~2.8 - 20, // 3x ~9.6 - 100, 1e4, 1e8, 1.5e9, 1e20, - // Boundary cases. - std::numeric_limits<double>::max(), - std::numeric_limits<double>::epsilon(), - std::nextafter(std::numeric_limits<double>::min(), - 1.0), // min + epsilon - std::numeric_limits<double>::min(), // smallest normal - std::numeric_limits<double>::denorm_min(), // smallest denorm - std::numeric_limits<double>::min() / 2, // denorm - std::nextafter(std::numeric_limits<double>::min(), - 0.0), // denorm_max - }; - - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - for (const double m : kParams) { - const double mean = std::min(kMax, m); - const param_type param(mean); - - // Validate parameters. - absl::poisson_distribution<TypeParam> before(mean); - EXPECT_EQ(before.mean(), param.mean()); - - { - absl::poisson_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - EXPECT_EQ(via_param.param(), before.param()); - } - - // Smoke test. - auto sample_min = before.max(); - auto sample_max = before.min(); - for (int i = 0; i < kCount; i++) { - auto sample = before(gen); - EXPECT_GE(sample, before.min()); - EXPECT_LE(sample, before.max()); - if (sample > sample_max) sample_max = sample; - if (sample < sample_min) sample_min = sample; - } - - ABSL_INTERNAL_LOG(INFO, absl::StrCat("Range {", param.mean(), "}: ", - +sample_min, ", ", +sample_max)); - - // Validate stream serialization. - std::stringstream ss; - ss << before; - - absl::poisson_distribution<TypeParam> after(3.8); - - EXPECT_NE(before.mean(), after.mean()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.mean(), after.mean()) // - << ss.str() << " " // - << (ss.good() ? "good " : "") // - << (ss.bad() ? "bad " : "") // - << (ss.eof() ? "eof " : "") // - << (ss.fail() ? "fail " : ""); - } -} - -// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm - -class PoissonModel { - public: - explicit PoissonModel(double mean) : mean_(mean) {} - - double mean() const { return mean_; } - double variance() const { return mean_; } - double stddev() const { return std::sqrt(variance()); } - double skew() const { return 1.0 / mean_; } - double kurtosis() const { return 3.0 + 1.0 / mean_; } - - // InitCDF() initializes the CDF for the distribution parameters. - void InitCDF(); - - // The InverseCDF, or the Percent-point function returns x, P(x) < v. - struct CDF { - size_t index; - double pmf; - double cdf; - }; - CDF InverseCDF(double p) { - CDF target{0, 0, p}; - auto it = std::upper_bound( - std::begin(cdf_), std::end(cdf_), target, - [](const CDF& a, const CDF& b) { return a.cdf < b.cdf; }); - return *it; - } - - void LogCDF() { - ABSL_INTERNAL_LOG(INFO, absl::StrCat("CDF (mean = ", mean_, ")")); - for (const auto c : cdf_) { - ABSL_INTERNAL_LOG(INFO, - absl::StrCat(c.index, ": pmf=", c.pmf, " cdf=", c.cdf)); - } - } - - private: - const double mean_; - - std::vector<CDF> cdf_; -}; - -// The goal is to compute an InverseCDF function, or percent point function for -// the poisson distribution, and use that to partition our output into equal -// range buckets. However there is no closed form solution for the inverse cdf -// for poisson distributions (the closest is the incomplete gamma function). -// Instead, `InitCDF` iteratively computes the PMF and the CDF. This enables -// searching for the bucket points. -void PoissonModel::InitCDF() { - if (!cdf_.empty()) { - // State already initialized. - return; - } - ABSL_ASSERT(mean_ < 201.0); - - const size_t max_i = 50 * stddev() + mean(); - const double e_neg_mean = std::exp(-mean()); - ABSL_ASSERT(e_neg_mean > 0); - - double d = 1; - double last_result = e_neg_mean; - double cumulative = e_neg_mean; - if (e_neg_mean > 1e-10) { - cdf_.push_back({0, e_neg_mean, cumulative}); - } - for (size_t i = 1; i < max_i; i++) { - d *= (mean() / i); - double result = e_neg_mean * d; - cumulative += result; - if (result < 1e-10 && result < last_result && cumulative > 0.999999) { - break; - } - if (result > 1e-7) { - cdf_.push_back({i, result, cumulative}); - } - last_result = result; - } - ABSL_ASSERT(!cdf_.empty()); -} - -// PoissonDistributionZTest implements a z-test for the poisson distribution. - -struct ZParam { - double mean; - double p_fail; // Z-Test probability of failure. - int trials; // Z-Test trials. - size_t samples; // Z-Test samples. -}; - -class PoissonDistributionZTest : public testing::TestWithParam<ZParam>, - public PoissonModel { - public: - PoissonDistributionZTest() : PoissonModel(GetParam().mean) {} - - // ZTestImpl provides a basic z-squared test of the mean vs. expected - // mean for data generated by the poisson distribution. - template <typename D> - bool SingleZTest(const double p, const size_t samples); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -template <typename D> -bool PoissonDistributionZTest::SingleZTest(const double p, - const size_t samples) { - D dis(mean()); - - absl::flat_hash_map<int32_t, int> buckets; - std::vector<double> data; - data.reserve(samples); - for (int j = 0; j < samples; j++) { - const auto x = dis(rng_); - buckets[x]++; - data.push_back(x); - } - - // The null-hypothesis is that the distribution is a poisson distribution with - // the provided mean (not estimated from the data). - const auto m = absl::random_internal::ComputeDistributionMoments(data); - const double max_err = absl::random_internal::MaxErrorTolerance(p); - const double z = absl::random_internal::ZScore(mean(), m); - const bool pass = absl::random_internal::Near("z", z, 0.0, max_err); - - if (!pass) { - ABSL_INTERNAL_LOG( - INFO, absl::StrFormat("p=%f max_err=%f\n" - " mean=%f vs. %f\n" - " stddev=%f vs. %f\n" - " skewness=%f vs. %f\n" - " kurtosis=%f vs. %f\n" - " z=%f", - p, max_err, m.mean, mean(), std::sqrt(m.variance), - stddev(), m.skewness, skew(), m.kurtosis, - kurtosis(), z)); - } - return pass; -} - -TEST_P(PoissonDistributionZTest, AbslPoissonDistribution) { - const auto& param = GetParam(); - const int expected_failures = - std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail))); - const double p = absl::random_internal::RequiredSuccessProbability( - param.p_fail, param.trials); - - int failures = 0; - for (int i = 0; i < param.trials; i++) { - failures += - SingleZTest<absl::poisson_distribution<int32_t>>(p, param.samples) ? 0 - : 1; - } - EXPECT_LE(failures, expected_failures); -} - -std::vector<ZParam> GetZParams() { - // These values have been adjusted from the "exact" computed values to reduce - // failure rates. - // - // It turns out that the actual values are not as close to the expected values - // as would be ideal. - return std::vector<ZParam>({ - // Knuth method. - ZParam{0.5, 0.01, 100, 1000}, - ZParam{1.0, 0.01, 100, 1000}, - ZParam{10.0, 0.01, 100, 5000}, - // Split-knuth method. - ZParam{20.0, 0.01, 100, 10000}, - ZParam{50.0, 0.01, 100, 10000}, - // Ratio of gaussians method. - ZParam{51.0, 0.01, 100, 10000}, - ZParam{200.0, 0.05, 10, 100000}, - ZParam{100000.0, 0.05, 10, 1000000}, - }); -} - -std::string ZParamName(const ::testing::TestParamInfo<ZParam>& info) { - const auto& p = info.param; - std::string name = absl::StrCat("mean_", absl::SixDigits(p.mean)); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionZTest, - ::testing::ValuesIn(GetZParams()), ZParamName); - -// The PoissonDistributionChiSquaredTest class provides a basic test framework -// for variates generated by a conforming poisson_distribution. -class PoissonDistributionChiSquaredTest : public testing::TestWithParam<double>, - public PoissonModel { - public: - PoissonDistributionChiSquaredTest() : PoissonModel(GetParam()) {} - - // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for data - // generated by the poisson distribution. - template <typename D> - double ChiSquaredTestImpl(); - - private: - void InitChiSquaredTest(const double buckets); - - std::vector<size_t> cutoffs_; - std::vector<double> expected_; - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -void PoissonDistributionChiSquaredTest::InitChiSquaredTest( - const double buckets) { - if (!cutoffs_.empty() && !expected_.empty()) { - return; - } - InitCDF(); - - // The code below finds cuttoffs that yield approximately equally-sized - // buckets to the extent that it is possible. However for poisson - // distributions this is particularly challenging for small mean parameters. - // Track the expected proportion of items in each bucket. - double last_cdf = 0; - const double inc = 1.0 / buckets; - for (double p = inc; p <= 1.0; p += inc) { - auto result = InverseCDF(p); - if (!cutoffs_.empty() && cutoffs_.back() == result.index) { - continue; - } - double d = result.cdf - last_cdf; - cutoffs_.push_back(result.index); - expected_.push_back(d); - last_cdf = result.cdf; - } - cutoffs_.push_back(std::numeric_limits<size_t>::max()); - expected_.push_back(std::max(0.0, 1.0 - last_cdf)); -} - -template <typename D> -double PoissonDistributionChiSquaredTest::ChiSquaredTestImpl() { - const int kSamples = 2000; - const int kBuckets = 50; - - // The poisson CDF fails for large mean values, since e^-mean exceeds the - // machine precision. For these cases, using a normal approximation would be - // appropriate. - ABSL_ASSERT(mean() <= 200); - InitChiSquaredTest(kBuckets); - - D dis(mean()); - - std::vector<int32_t> counts(cutoffs_.size(), 0); - for (int j = 0; j < kSamples; j++) { - const size_t x = dis(rng_); - auto it = std::lower_bound(std::begin(cutoffs_), std::end(cutoffs_), x); - counts[std::distance(cutoffs_.begin(), it)]++; - } - - // Normalize the counts. - std::vector<int32_t> e(expected_.size(), 0); - for (int i = 0; i < e.size(); i++) { - e[i] = kSamples * expected_[i]; - } - - // The null-hypothesis is that the distribution is a poisson distribution with - // the provided mean (not estimated from the data). - const int dof = static_cast<int>(counts.size()) - 1; - - // The threshold for logging is 1-in-50. - const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98); - - const double chi_square = absl::random_internal::ChiSquare( - std::begin(counts), std::end(counts), std::begin(e), std::end(e)); - - const double p = absl::random_internal::ChiSquarePValue(chi_square, dof); - - // Log if the chi_squared value is above the threshold. - if (chi_square > threshold) { - LogCDF(); - - ABSL_INTERNAL_LOG(INFO, absl::StrCat("VALUES buckets=", counts.size(), - " samples=", kSamples)); - for (size_t i = 0; i < counts.size(); i++) { - ABSL_INTERNAL_LOG( - INFO, absl::StrCat(cutoffs_[i], ": ", counts[i], " vs. E=", e[i])); - } - - ABSL_INTERNAL_LOG( - INFO, - absl::StrCat(kChiSquared, "(data, dof=", dof, ") = ", chi_square, " (", - p, ")\n", " vs.\n", kChiSquared, " @ 0.98 = ", threshold)); - } - return p; -} - -TEST_P(PoissonDistributionChiSquaredTest, AbslPoissonDistribution) { - const int kTrials = 20; - - // Large values are not yet supported -- this requires estimating the cdf - // using the normal distribution instead of the poisson in this case. - ASSERT_LE(mean(), 200.0); - if (mean() > 200.0) { - return; - } - - int failures = 0; - for (int i = 0; i < kTrials; i++) { - double p_value = ChiSquaredTestImpl<absl::poisson_distribution<int32_t>>(); - if (p_value < 0.005) { - failures++; - } - } - // There is a 0.10% chance of producing at least one failure, so raise the - // failure threshold high enough to allow for a flake rate < 10,000. - EXPECT_LE(failures, 4); -} - -INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionChiSquaredTest, - ::testing::Values(0.5, 1.0, 2.0, 10.0, 50.0, 51.0, - 200.0)); - -// NOTE: absl::poisson_distribution is not guaranteed to be stable. -TEST(PoissonDistributionTest, StabilityTest) { - using testing::ElementsAre; - // absl::poisson_distribution stability relies on stability of - // std::exp, std::log, std::sqrt, std::ceil, std::floor, and - // absl::FastUniformBits, absl::StirlingLogFactorial, absl::RandU64ToDouble. - absl::random_internal::sequence_urbg urbg({ - 0x035b0dc7e0a18acfull, 0x06cebe0d2653682eull, 0x0061e9b23861596bull, - 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull, - 0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull, - 0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull, - 0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull, - 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full, - 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull, - 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull, - 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull, - 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull, - 0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull, 0xffe6ea4d6edb0c73ull, - 0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull, 0xEAAD8E716B93D5A0ull, - 0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull, 0x8FF6E2FBF2122B64ull, - 0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull, 0xD1CFF191B3A8C1ADull, - 0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull, 0xE5A0CC0FB56F74E8ull, - 0x18ACF3D6CE89E299ull, 0xB4A84FE0FD13E0B7ull, 0x7CC43B81D2ADA8D9ull, - 0x165FA26680957705ull, 0x93CC7314211A1477ull, 0xE6AD206577B5FA86ull, - 0xC75442F5FB9D35CFull, 0xEBCDAF0C7B3E89A0ull, 0xD6411BD3AE1E7E49ull, - 0x00250E2D2071B35Eull, 0x226800BB57B8E0AFull, 0x2464369BF009B91Eull, - 0x5563911D59DFA6AAull, 0x78C14389D95A537Full, 0x207D5BA202E5B9C5ull, - 0x832603766295CFA9ull, 0x11C819684E734A41ull, 0xB3472DCA7B14A94Aull, - }); - - std::vector<int> output(10); - - // Method 1. - { - absl::poisson_distribution<int> dist(5); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - } - EXPECT_THAT(output, // mean = 4.2 - ElementsAre(1, 0, 0, 4, 2, 10, 3, 3, 7, 12)); - - // Method 2. - { - urbg.reset(); - absl::poisson_distribution<int> dist(25); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - } - EXPECT_THAT(output, // mean = 19.8 - ElementsAre(9, 35, 18, 10, 35, 18, 10, 35, 18, 10)); - - // Method 3. - { - urbg.reset(); - absl::poisson_distribution<int> dist(121); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - } - EXPECT_THAT(output, // mean = 124.1 - ElementsAre(161, 122, 129, 124, 112, 112, 117, 120, 130, 114)); -} - -TEST(PoissonDistributionTest, AlgorithmExpectedValue_1) { - // This tests small values of the Knuth method. - // The underlying uniform distribution will generate exactly 0.5. - absl::random_internal::sequence_urbg urbg({0x8000000000000001ull}); - absl::poisson_distribution<int> dist(5); - EXPECT_EQ(7, dist(urbg)); -} - -TEST(PoissonDistributionTest, AlgorithmExpectedValue_2) { - // This tests larger values of the Knuth method. - // The underlying uniform distribution will generate exactly 0.5. - absl::random_internal::sequence_urbg urbg({0x8000000000000001ull}); - absl::poisson_distribution<int> dist(25); - EXPECT_EQ(36, dist(urbg)); -} - -TEST(PoissonDistributionTest, AlgorithmExpectedValue_3) { - // This variant uses the ratio of uniforms method. - absl::random_internal::sequence_urbg urbg( - {0x7fffffffffffffffull, 0x8000000000000000ull}); - - absl::poisson_distribution<int> dist(121); - EXPECT_EQ(121, dist(urbg)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/random.h b/third_party/abseil_cpp/absl/random/random.h deleted file mode 100644 index 71b6309288e6..000000000000 --- a/third_party/abseil_cpp/absl/random/random.h +++ /dev/null @@ -1,189 +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. -// -// ----------------------------------------------------------------------------- -// File: random.h -// ----------------------------------------------------------------------------- -// -// This header defines the recommended Uniform Random Bit Generator (URBG) -// types for use within the Abseil Random library. These types are not -// suitable for security-related use-cases, but should suffice for most other -// uses of generating random values. -// -// The Abseil random library provides the following URBG types: -// -// * BitGen, a good general-purpose bit generator, optimized for generating -// random (but not cryptographically secure) values -// * InsecureBitGen, a slightly faster, though less random, bit generator, for -// cases where the existing BitGen is a drag on performance. - -#ifndef ABSL_RANDOM_RANDOM_H_ -#define ABSL_RANDOM_RANDOM_H_ - -#include <random> - -#include "absl/random/distributions.h" // IWYU pragma: export -#include "absl/random/internal/nonsecure_base.h" // IWYU pragma: export -#include "absl/random/internal/pcg_engine.h" // IWYU pragma: export -#include "absl/random/internal/pool_urbg.h" -#include "absl/random/internal/randen_engine.h" -#include "absl/random/seed_sequences.h" // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// absl::BitGen -// ----------------------------------------------------------------------------- -// -// `absl::BitGen` is a general-purpose random bit generator for generating -// random values for use within the Abseil random library. Typically, you use a -// bit generator in combination with a distribution to provide random values. -// -// Example: -// -// // Create an absl::BitGen. There is no need to seed this bit generator. -// absl::BitGen gen; -// -// // Generate an integer value in the closed interval [1,6] -// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen); -// -// `absl::BitGen` is seeded by default with non-deterministic data to produce -// different sequences of random values across different instances, including -// different binary invocations. This behavior is different than the standard -// library bit generators, which use golden values as their seeds. Default -// construction intentionally provides no stability guarantees, to avoid -// accidental dependence on such a property. -// -// `absl::BitGen` may be constructed with an optional seed sequence type, -// conforming to [rand.req.seed_seq], which will be mixed with additional -// non-deterministic data. -// -// Example: -// -// // Create an absl::BitGen using an std::seed_seq seed sequence -// std::seed_seq seq{1,2,3}; -// absl::BitGen gen_with_seed(seq); -// -// // Generate an integer value in the closed interval [1,6] -// int die_roll2 = absl::uniform_int_distribution<int>(1, 6)(gen_with_seed); -// -// `absl::BitGen` meets the requirements of the Uniform Random Bit Generator -// (URBG) concept as per the C++17 standard [rand.req.urng] though differs -// slightly with [rand.req.eng]. Like its standard library equivalents (e.g. -// `std::mersenne_twister_engine`) `absl::BitGen` is not cryptographically -// secure. -// -// Constructing two `absl::BitGen`s with the same seed sequence in the same -// binary will produce the same sequence of variates within the same binary, but -// need not do so across multiple binary invocations. -// -// This type has been optimized to perform better than Mersenne Twister -// (https://en.wikipedia.org/wiki/Mersenne_Twister) and many other complex URBG -// types on modern x86, ARM, and PPC architectures. -// -// This type is thread-compatible, but not thread-safe. - -// --------------------------------------------------------------------------- -// absl::BitGen member functions -// --------------------------------------------------------------------------- - -// absl::BitGen::operator()() -// -// Calls the BitGen, returning a generated value. - -// absl::BitGen::min() -// -// Returns the smallest possible value from this bit generator. - -// absl::BitGen::max() -// -// Returns the largest possible value from this bit generator. - -// absl::BitGen::discard(num) -// -// Advances the internal state of this bit generator by `num` times, and -// discards the intermediate results. -// --------------------------------------------------------------------------- - -using BitGen = random_internal::NonsecureURBGBase< - random_internal::randen_engine<uint64_t>>; - -// ----------------------------------------------------------------------------- -// absl::InsecureBitGen -// ----------------------------------------------------------------------------- -// -// `absl::InsecureBitGen` is an efficient random bit generator for generating -// random values, recommended only for performance-sensitive use cases where -// `absl::BitGen` is not satisfactory when compute-bounded by bit generation -// costs. -// -// Example: -// -// // Create an absl::InsecureBitGen -// absl::InsecureBitGen gen; -// for (size_t i = 0; i < 1000000; i++) { -// -// // Generate a bunch of random values from some complex distribution -// auto my_rnd = some_distribution(gen, 1, 1000); -// } -// -// Like `absl::BitGen`, `absl::InsecureBitGen` is seeded by default with -// non-deterministic data to produce different sequences of random values across -// different instances, including different binary invocations. (This behavior -// is different than the standard library bit generators, which use golden -// values as their seeds.) -// -// `absl::InsecureBitGen` may be constructed with an optional seed sequence -// type, conforming to [rand.req.seed_seq], which will be mixed with additional -// non-deterministic data. (See std_seed_seq.h for more information.) -// -// `absl::InsecureBitGen` meets the requirements of the Uniform Random Bit -// Generator (URBG) concept as per the C++17 standard [rand.req.urng] though -// its implementation differs slightly with [rand.req.eng]. Like its standard -// library equivalents (e.g. `std::mersenne_twister_engine`) -// `absl::InsecureBitGen` is not cryptographically secure. -// -// Prefer `absl::BitGen` over `absl::InsecureBitGen` as the general type is -// often fast enough for the vast majority of applications. - -using InsecureBitGen = - random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>; - -// --------------------------------------------------------------------------- -// absl::InsecureBitGen member functions -// --------------------------------------------------------------------------- - -// absl::InsecureBitGen::operator()() -// -// Calls the InsecureBitGen, returning a generated value. - -// absl::InsecureBitGen::min() -// -// Returns the smallest possible value from this bit generator. - -// absl::InsecureBitGen::max() -// -// Returns the largest possible value from this bit generator. - -// absl::InsecureBitGen::discard(num) -// -// Advances the internal state of this bit generator by `num` times, and -// discards the intermediate results. -// --------------------------------------------------------------------------- - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_RANDOM_H_ diff --git a/third_party/abseil_cpp/absl/random/seed_gen_exception.cc b/third_party/abseil_cpp/absl/random/seed_gen_exception.cc deleted file mode 100644 index fdcb54a86cdd..000000000000 --- a/third_party/abseil_cpp/absl/random/seed_gen_exception.cc +++ /dev/null @@ -1,46 +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/seed_gen_exception.h" - -#include <iostream> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -static constexpr const char kExceptionMessage[] = - "Failed generating seed-material for URBG."; - -SeedGenException::~SeedGenException() = default; - -const char* SeedGenException::what() const noexcept { - return kExceptionMessage; -} - -namespace random_internal { - -void ThrowSeedGenException() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw absl::SeedGenException(); -#else - std::cerr << kExceptionMessage << std::endl; - std::terminate(); -#endif -} - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/seed_gen_exception.h b/third_party/abseil_cpp/absl/random/seed_gen_exception.h deleted file mode 100644 index 535390056437..000000000000 --- a/third_party/abseil_cpp/absl/random/seed_gen_exception.h +++ /dev/null @@ -1,55 +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. -// -// ----------------------------------------------------------------------------- -// File: seed_gen_exception.h -// ----------------------------------------------------------------------------- -// -// This header defines an exception class which may be thrown if unpredictable -// events prevent the derivation of suitable seed-material for constructing a -// bit generator conforming to [rand.req.urng] (eg. entropy cannot be read from -// /dev/urandom on a Unix-based system). -// -// Note: if exceptions are disabled, `std::terminate()` is called instead. - -#ifndef ABSL_RANDOM_SEED_GEN_EXCEPTION_H_ -#define ABSL_RANDOM_SEED_GEN_EXCEPTION_H_ - -#include <exception> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -//------------------------------------------------------------------------------ -// SeedGenException -//------------------------------------------------------------------------------ -class SeedGenException : public std::exception { - public: - SeedGenException() = default; - ~SeedGenException() override; - const char* what() const noexcept override; -}; - -namespace random_internal { - -// throw delegator -[[noreturn]] void ThrowSeedGenException(); - -} // namespace random_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_ diff --git a/third_party/abseil_cpp/absl/random/seed_sequences.cc b/third_party/abseil_cpp/absl/random/seed_sequences.cc deleted file mode 100644 index 426eafd3c8de..000000000000 --- a/third_party/abseil_cpp/absl/random/seed_sequences.cc +++ /dev/null @@ -1,29 +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/seed_sequences.h" - -#include "absl/random/internal/pool_urbg.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -SeedSeq MakeSeedSeq() { - SeedSeq::result_type seed_material[8]; - random_internal::RandenPool<uint32_t>::Fill(absl::MakeSpan(seed_material)); - return SeedSeq(std::begin(seed_material), std::end(seed_material)); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/random/seed_sequences.h b/third_party/abseil_cpp/absl/random/seed_sequences.h deleted file mode 100644 index ff1340cc8eed..000000000000 --- a/third_party/abseil_cpp/absl/random/seed_sequences.h +++ /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. -// -// ----------------------------------------------------------------------------- -// File: seed_sequences.h -// ----------------------------------------------------------------------------- -// -// This header contains utilities for creating and working with seed sequences -// conforming to [rand.req.seedseq]. In general, direct construction of seed -// sequences is discouraged, but use-cases for construction of identical bit -// generators (using the same seed sequence) may be helpful (e.g. replaying a -// simulation whose state is derived from variates of a bit generator). - -#ifndef ABSL_RANDOM_SEED_SEQUENCES_H_ -#define ABSL_RANDOM_SEED_SEQUENCES_H_ - -#include <iterator> -#include <random> - -#include "absl/random/internal/salted_seed_seq.h" -#include "absl/random/internal/seed_material.h" -#include "absl/random/seed_gen_exception.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// absl::SeedSeq -// ----------------------------------------------------------------------------- -// -// `absl::SeedSeq` constructs a seed sequence according to [rand.req.seedseq] -// for use within bit generators. `absl::SeedSeq`, unlike `std::seed_seq` -// additionally salts the generated seeds with extra implementation-defined -// entropy. For that reason, you can use `absl::SeedSeq` in combination with -// standard library bit generators (e.g. `std::mt19937`) to introduce -// non-determinism in your seeds. -// -// Example: -// -// absl::SeedSeq my_seed_seq({a, b, c}); -// std::mt19937 my_bitgen(my_seed_seq); -// -using SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>; - -// ----------------------------------------------------------------------------- -// absl::CreateSeedSeqFrom(bitgen*) -// ----------------------------------------------------------------------------- -// -// Constructs a seed sequence conforming to [rand.req.seedseq] using variates -// produced by a provided bit generator. -// -// You should generally avoid direct construction of seed sequences, but -// use-cases for reuse of a seed sequence to construct identical bit generators -// may be helpful (eg. replaying a simulation whose state is derived from bit -// generator values). -// -// If bitgen == nullptr, then behavior is undefined. -// -// Example: -// -// absl::BitGen my_bitgen; -// auto seed_seq = absl::CreateSeedSeqFrom(&my_bitgen); -// absl::BitGen new_engine(seed_seq); // derived from my_bitgen, but not -// // correlated. -// -template <typename URBG> -SeedSeq CreateSeedSeqFrom(URBG* urbg) { - SeedSeq::result_type - seed_material[random_internal::kEntropyBlocksNeeded]; - - if (!random_internal::ReadSeedMaterialFromURBG( - urbg, absl::MakeSpan(seed_material))) { - random_internal::ThrowSeedGenException(); - } - return SeedSeq(std::begin(seed_material), std::end(seed_material)); -} - -// ----------------------------------------------------------------------------- -// absl::MakeSeedSeq() -// ----------------------------------------------------------------------------- -// -// Constructs an `absl::SeedSeq` salting the generated values using -// implementation-defined entropy. The returned sequence can be used to create -// equivalent bit generators correlated using this sequence. -// -// Example: -// -// auto my_seed_seq = absl::MakeSeedSeq(); -// std::mt19937 rng1(my_seed_seq); -// std::mt19937 rng2(my_seed_seq); -// EXPECT_EQ(rng1(), rng2()); -// -SeedSeq MakeSeedSeq(); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_SEED_SEQUENCES_H_ diff --git a/third_party/abseil_cpp/absl/random/seed_sequences_test.cc b/third_party/abseil_cpp/absl/random/seed_sequences_test.cc deleted file mode 100644 index fe1100bda0d5..000000000000 --- a/third_party/abseil_cpp/absl/random/seed_sequences_test.cc +++ /dev/null @@ -1,126 +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/seed_sequences.h" - -#include <iterator> -#include <random> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/random/internal/nonsecure_base.h" -#include "absl/random/random.h" -namespace { - -TEST(SeedSequences, Examples) { - { - absl::SeedSeq seed_seq({1, 2, 3}); - absl::BitGen bitgen(seed_seq); - - EXPECT_NE(0, bitgen()); - } - { - absl::BitGen engine; - auto seed_seq = absl::CreateSeedSeqFrom(&engine); - absl::BitGen bitgen(seed_seq); - - EXPECT_NE(engine(), bitgen()); - } - { - auto seed_seq = absl::MakeSeedSeq(); - std::mt19937 random(seed_seq); - - EXPECT_NE(0, random()); - } -} - -TEST(CreateSeedSeqFrom, CompatibleWithStdTypes) { - using ExampleNonsecureURBG = - absl::random_internal::NonsecureURBGBase<std::minstd_rand0>; - - // Construct a URBG instance. - ExampleNonsecureURBG rng; - - // Construct a Seed Sequence from its variates. - auto seq_from_rng = absl::CreateSeedSeqFrom(&rng); - - // Ensure that another URBG can be validly constructed from the Seed Sequence. - std::mt19937_64{seq_from_rng}; -} - -TEST(CreateSeedSeqFrom, CompatibleWithBitGenerator) { - // Construct a URBG instance. - absl::BitGen rng; - - // Construct a Seed Sequence from its variates. - auto seq_from_rng = absl::CreateSeedSeqFrom(&rng); - - // Ensure that another URBG can be validly constructed from the Seed Sequence. - std::mt19937_64{seq_from_rng}; -} - -TEST(CreateSeedSeqFrom, CompatibleWithInsecureBitGen) { - // Construct a URBG instance. - absl::InsecureBitGen rng; - - // Construct a Seed Sequence from its variates. - auto seq_from_rng = absl::CreateSeedSeqFrom(&rng); - - // Ensure that another URBG can be validly constructed from the Seed Sequence. - std::mt19937_64{seq_from_rng}; -} - -TEST(CreateSeedSeqFrom, CompatibleWithRawURBG) { - // Construct a URBG instance. - std::random_device urandom; - - // Construct a Seed Sequence from its variates, using 64b of seed-material. - auto seq_from_rng = absl::CreateSeedSeqFrom(&urandom); - - // Ensure that another URBG can be validly constructed from the Seed Sequence. - std::mt19937_64{seq_from_rng}; -} - -template <typename URBG> -void TestReproducibleVariateSequencesForNonsecureURBG() { - const size_t kNumVariates = 1000; - - URBG rng; - // Reused for both RNG instances. - auto reusable_seed = absl::CreateSeedSeqFrom(&rng); - - typename URBG::result_type variates[kNumVariates]; - { - URBG child(reusable_seed); - for (auto& variate : variates) { - variate = child(); - } - } - // Ensure that variate-sequence can be "replayed" by identical RNG. - { - URBG child(reusable_seed); - for (auto& variate : variates) { - ASSERT_EQ(variate, child()); - } - } -} - -TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForInsecureBitGen) { - TestReproducibleVariateSequencesForNonsecureURBG<absl::InsecureBitGen>(); -} - -TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForBitGenerator) { - TestReproducibleVariateSequencesForNonsecureURBG<absl::BitGen>(); -} -} // namespace diff --git a/third_party/abseil_cpp/absl/random/uniform_int_distribution.h b/third_party/abseil_cpp/absl/random/uniform_int_distribution.h deleted file mode 100644 index c1f54ccebce5..000000000000 --- a/third_party/abseil_cpp/absl/random/uniform_int_distribution.h +++ /dev/null @@ -1,275 +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. -// -// ----------------------------------------------------------------------------- -// File: uniform_int_distribution.h -// ----------------------------------------------------------------------------- -// -// This header defines a class for representing a uniform integer distribution -// over the closed (inclusive) interval [a,b]. You use this distribution in -// combination with an Abseil random bit generator to produce random values -// according to the rules of the distribution. -// -// `absl::uniform_int_distribution` is a drop-in replacement for the C++11 -// `std::uniform_int_distribution` [rand.dist.uni.int] but is considerably -// faster than the libstdc++ implementation. - -#ifndef ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_ -#define ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_ - -#include <cassert> -#include <istream> -#include <limits> -#include <type_traits> - -#include "absl/base/optimization.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/iostream_state_saver.h" -#include "absl/random/internal/traits.h" -#include "absl/random/internal/wide_multiply.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::uniform_int_distribution<T> -// -// This distribution produces random integer values uniformly distributed in the -// closed (inclusive) interval [a, b]. -// -// Example: -// -// absl::BitGen gen; -// -// // Use the distribution to produce a value between 1 and 6, inclusive. -// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen); -// -template <typename IntType = int> -class uniform_int_distribution { - private: - using unsigned_type = - typename random_internal::make_unsigned_bits<IntType>::type; - - public: - using result_type = IntType; - - class param_type { - public: - using distribution_type = uniform_int_distribution; - - explicit param_type( - result_type lo = 0, - result_type hi = (std::numeric_limits<result_type>::max)()) - : lo_(lo), - range_(static_cast<unsigned_type>(hi) - - static_cast<unsigned_type>(lo)) { - // [rand.dist.uni.int] precondition 2 - assert(lo <= hi); - } - - result_type a() const { return lo_; } - result_type b() const { - return static_cast<result_type>(static_cast<unsigned_type>(lo_) + range_); - } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.lo_ == b.lo_ && a.range_ == b.range_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class uniform_int_distribution; - unsigned_type range() const { return range_; } - - result_type lo_; - unsigned_type range_; - - static_assert(std::is_integral<result_type>::value, - "Class-template absl::uniform_int_distribution<> must be " - "parameterized using an integral type."); - }; // param_type - - uniform_int_distribution() : uniform_int_distribution(0) {} - - explicit uniform_int_distribution( - result_type lo, - result_type hi = (std::numeric_limits<result_type>::max)()) - : param_(lo, hi) {} - - explicit uniform_int_distribution(const param_type& param) : param_(param) {} - - // uniform_int_distribution<T>::reset() - // - // Resets the uniform int distribution. Note that this function has no effect - // because the distribution already produces independent values. - void reset() {} - - template <typename URBG> - result_type operator()(URBG& gen) { // NOLINT(runtime/references) - return (*this)(gen, param()); - } - - template <typename URBG> - result_type operator()( - URBG& gen, const param_type& param) { // NOLINT(runtime/references) - return param.a() + Generate(gen, param.range()); - } - - result_type a() const { return param_.a(); } - result_type b() const { return param_.b(); } - - param_type param() const { return param_; } - void param(const param_type& params) { param_ = params; } - - result_type(min)() const { return a(); } - result_type(max)() const { return b(); } - - friend bool operator==(const uniform_int_distribution& a, - const uniform_int_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const uniform_int_distribution& a, - const uniform_int_distribution& b) { - return !(a == b); - } - - private: - // Generates a value in the *closed* interval [0, R] - template <typename URBG> - unsigned_type Generate(URBG& g, // NOLINT(runtime/references) - unsigned_type R); - param_type param_; -}; - -// ----------------------------------------------------------------------------- -// Implementation details follow -// ----------------------------------------------------------------------------- -template <typename CharT, typename Traits, typename IntType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, - const uniform_int_distribution<IntType>& x) { - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - auto saver = random_internal::make_ostream_state_saver(os); - os << static_cast<stream_type>(x.a()) << os.fill() - << static_cast<stream_type>(x.b()); - return os; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, - uniform_int_distribution<IntType>& x) { - using param_type = typename uniform_int_distribution<IntType>::param_type; - using result_type = typename uniform_int_distribution<IntType>::result_type; - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - - stream_type a; - stream_type b; - - auto saver = random_internal::make_istream_state_saver(is); - is >> a >> b; - if (!is.fail()) { - x.param( - param_type(static_cast<result_type>(a), static_cast<result_type>(b))); - } - return is; -} - -template <typename IntType> -template <typename URBG> -typename random_internal::make_unsigned_bits<IntType>::type -uniform_int_distribution<IntType>::Generate( - URBG& g, // NOLINT(runtime/references) - typename random_internal::make_unsigned_bits<IntType>::type R) { - random_internal::FastUniformBits<unsigned_type> fast_bits; - unsigned_type bits = fast_bits(g); - const unsigned_type Lim = R + 1; - if ((R & Lim) == 0) { - // If the interval's length is a power of two range, just take the low bits. - return bits & R; - } - - // Generates a uniform variate on [0, Lim) using fixed-point multiplication. - // The above fast-path guarantees that Lim is representable in unsigned_type. - // - // Algorithm adapted from - // http://lemire.me/blog/2016/06/30/fast-random-shuffling/, with added - // explanation. - // - // The algorithm creates a uniform variate `bits` in the interval [0, 2^N), - // and treats it as the fractional part of a fixed-point real value in [0, 1), - // multiplied by 2^N. For example, 0.25 would be represented as 2^(N - 2), - // because 2^N * 0.25 == 2^(N - 2). - // - // Next, `bits` and `Lim` are multiplied with a wide-multiply to bring the - // value into the range [0, Lim). The integral part (the high word of the - // multiplication result) is then very nearly the desired result. However, - // this is not quite accurate; viewing the multiplication result as one - // double-width integer, the resulting values for the sample are mapped as - // follows: - // - // If the result lies in this interval: Return this value: - // [0, 2^N) 0 - // [2^N, 2 * 2^N) 1 - // ... ... - // [K * 2^N, (K + 1) * 2^N) K - // ... ... - // [(Lim - 1) * 2^N, Lim * 2^N) Lim - 1 - // - // While all of these intervals have the same size, the result of `bits * Lim` - // must be a multiple of `Lim`, and not all of these intervals contain the - // same number of multiples of `Lim`. In particular, some contain - // `F = floor(2^N / Lim)` and some contain `F + 1 = ceil(2^N / Lim)`. This - // difference produces a small nonuniformity, which is corrected by applying - // rejection sampling to one of the values in the "larger intervals" (i.e., - // the intervals containing `F + 1` multiples of `Lim`. - // - // An interval contains `F + 1` multiples of `Lim` if and only if its smallest - // value modulo 2^N is less than `2^N % Lim`. The unique value satisfying - // this property is used as the one for rejection. That is, a value of - // `bits * Lim` is rejected if `(bit * Lim) % 2^N < (2^N % Lim)`. - - using helper = random_internal::wide_multiply<unsigned_type>; - auto product = helper::multiply(bits, Lim); - - // Two optimizations here: - // * Rejection occurs with some probability less than 1/2, and for reasonable - // ranges considerably less (in particular, less than 1/(F+1)), so - // ABSL_PREDICT_FALSE is apt. - // * `Lim` is an overestimate of `threshold`, and doesn't require a divide. - if (ABSL_PREDICT_FALSE(helper::lo(product) < Lim)) { - // This quantity is exactly equal to `2^N % Lim`, but does not require high - // precision calculations: `2^N % Lim` is congruent to `(2^N - Lim) % Lim`. - // Ideally this could be expressed simply as `-X` rather than `2^N - X`, but - // for types smaller than int, this calculation is incorrect due to integer - // promotion rules. - const unsigned_type threshold = - ((std::numeric_limits<unsigned_type>::max)() - Lim + 1) % Lim; - while (helper::lo(product) < threshold) { - bits = fast_bits(g); - product = helper::multiply(bits, Lim); - } - } - - return helper::hi(product); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/uniform_int_distribution_test.cc b/third_party/abseil_cpp/absl/random/uniform_int_distribution_test.cc deleted file mode 100644 index 276d72ad2045..000000000000 --- a/third_party/abseil_cpp/absl/random/uniform_int_distribution_test.cc +++ /dev/null @@ -1,259 +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/uniform_int_distribution.h" - -#include <cmath> -#include <cstdint> -#include <iterator> -#include <random> -#include <sstream> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" - -namespace { - -template <typename IntType> -class UniformIntDistributionTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, - uint32_t, int64_t, uint64_t>; -TYPED_TEST_SUITE(UniformIntDistributionTest, IntTypes); - -TYPED_TEST(UniformIntDistributionTest, ParamSerializeTest) { - // This test essentially ensures that the parameters serialize, - // not that the values generated cover the full range. - using Limits = std::numeric_limits<TypeParam>; - using param_type = - typename absl::uniform_int_distribution<TypeParam>::param_type; - const TypeParam kMin = std::is_unsigned<TypeParam>::value ? 37 : -105; - const TypeParam kNegOneOrZero = std::is_unsigned<TypeParam>::value ? 0 : -1; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - for (const auto& param : { - param_type(), - param_type(2, 2), // Same - param_type(9, 32), - param_type(kMin, 115), - param_type(kNegOneOrZero, Limits::max()), - param_type(Limits::min(), Limits::max()), - param_type(Limits::lowest(), Limits::max()), - param_type(Limits::min() + 1, Limits::max() - 1), - }) { - const auto a = param.a(); - const auto b = param.b(); - absl::uniform_int_distribution<TypeParam> before(a, b); - EXPECT_EQ(before.a(), param.a()); - EXPECT_EQ(before.b(), param.b()); - - { - // Initialize via param_type - absl::uniform_int_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - } - - // Initialize via iostreams - std::stringstream ss; - ss << before; - - absl::uniform_int_distribution<TypeParam> after(Limits::min() + 3, - Limits::max() - 5); - - EXPECT_NE(before.a(), after.a()); - EXPECT_NE(before.b(), after.b()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.a(), after.a()); - EXPECT_EQ(before.b(), after.b()); - EXPECT_EQ(before.param(), after.param()); - EXPECT_EQ(before, after); - - // Smoke test. - auto sample_min = after.max(); - auto sample_max = after.min(); - for (int i = 0; i < kCount; i++) { - auto sample = after(gen); - EXPECT_GE(sample, after.min()); - EXPECT_LE(sample, after.max()); - if (sample > sample_max) { - sample_max = sample; - } - if (sample < sample_min) { - sample_min = sample; - } - } - std::string msg = absl::StrCat("Range: ", +sample_min, ", ", +sample_max); - ABSL_RAW_LOG(INFO, "%s", msg.c_str()); - } -} - -TYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) { -#if GTEST_HAS_DEATH_TEST - // Hi < Lo - EXPECT_DEBUG_DEATH({ absl::uniform_int_distribution<TypeParam> dist(10, 1); }, - ""); -#endif // GTEST_HAS_DEATH_TEST -#if defined(NDEBUG) - // opt-mode, for invalid parameters, will generate a garbage value, - // but should not enter an infinite loop. - absl::InsecureBitGen gen; - absl::uniform_int_distribution<TypeParam> dist(10, 1); - auto x = dist(gen); - - // Any value will generate a non-empty string. - EXPECT_FALSE(absl::StrCat(+x).empty()) << x; -#endif // NDEBUG -} - -TYPED_TEST(UniformIntDistributionTest, TestMoments) { - constexpr int kSize = 100000; - using Limits = std::numeric_limits<TypeParam>; - using param_type = - typename absl::uniform_int_distribution<TypeParam>::param_type; - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6}; - - std::vector<double> values(kSize); - for (const auto& param : - {param_type(0, Limits::max()), param_type(13, 127)}) { - absl::uniform_int_distribution<TypeParam> dist(param); - for (int i = 0; i < kSize; i++) { - const auto sample = dist(rng); - ASSERT_LE(dist.param().a(), sample); - ASSERT_GE(dist.param().b(), sample); - values[i] = sample; - } - - auto moments = absl::random_internal::ComputeDistributionMoments(values); - const double a = dist.param().a(); - const double b = dist.param().b(); - const double n = (b - a + 1); - const double mean = (a + b) / 2; - const double var = ((b - a + 1) * (b - a + 1) - 1) / 12; - const double kurtosis = 3 - 6 * (n * n + 1) / (5 * (n * n - 1)); - - // TODO(ahh): this is not the right bound - // empirically validated with --runs_per_test=10000. - EXPECT_NEAR(mean, moments.mean, 0.01 * var); - EXPECT_NEAR(var, moments.variance, 0.015 * var); - EXPECT_NEAR(0.0, moments.skewness, 0.025); - EXPECT_NEAR(kurtosis, moments.kurtosis, 0.02 * kurtosis); - } -} - -TYPED_TEST(UniformIntDistributionTest, ChiSquaredTest50) { - using absl::random_internal::kChiSquared; - - constexpr size_t kTrials = 1000; - constexpr int kBuckets = 50; // inclusive, so actally +1 - constexpr double kExpected = - static_cast<double>(kTrials) / static_cast<double>(kBuckets); - - // Empirically validated with --runs_per_test=10000. - const int kThreshold = - absl::random_internal::ChiSquareValue(kBuckets, 0.999999); - - const TypeParam min = std::is_unsigned<TypeParam>::value ? 37 : -37; - const TypeParam max = min + kBuckets; - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6}; - - absl::uniform_int_distribution<TypeParam> dist(min, max); - - std::vector<int32_t> counts(kBuckets + 1, 0); - for (size_t i = 0; i < kTrials; i++) { - auto x = dist(rng); - counts[x - min]++; - } - double chi_square = absl::random_internal::ChiSquareWithExpected( - std::begin(counts), std::end(counts), kExpected); - if (chi_square > kThreshold) { - double p_value = - absl::random_internal::ChiSquarePValue(chi_square, kBuckets); - - // Chi-squared test failed. Output does not appear to be uniform. - std::string msg; - for (const auto& a : counts) { - absl::StrAppend(&msg, a, "\n"); - } - absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n"); - absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ", - kThreshold); - ABSL_RAW_LOG(INFO, "%s", msg.c_str()); - FAIL() << msg; - } -} - -TEST(UniformIntDistributionTest, StabilityTest) { - // absl::uniform_int_distribution stability relies only on integer operations. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(12); - - { - absl::uniform_int_distribution<int32_t> dist(0, 4); - for (auto& v : output) { - v = dist(urbg); - } - } - EXPECT_EQ(12, urbg.invocations()); - EXPECT_THAT(output, testing::ElementsAre(4, 4, 3, 2, 1, 0, 1, 4, 3, 1, 3, 1)); - - { - urbg.reset(); - absl::uniform_int_distribution<int32_t> dist(0, 100); - for (auto& v : output) { - v = dist(urbg); - } - } - EXPECT_EQ(12, urbg.invocations()); - EXPECT_THAT(output, testing::ElementsAre(97, 86, 75, 41, 36, 16, 38, 92, 67, - 30, 80, 38)); - - { - urbg.reset(); - absl::uniform_int_distribution<int32_t> dist(0, 10000); - for (auto& v : output) { - v = dist(urbg); - } - } - EXPECT_EQ(12, urbg.invocations()); - EXPECT_THAT(output, testing::ElementsAre(9648, 8562, 7439, 4089, 3571, 1602, - 3813, 9195, 6641, 2986, 7956, 3765)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/uniform_real_distribution.h b/third_party/abseil_cpp/absl/random/uniform_real_distribution.h deleted file mode 100644 index 5ba17b2341cf..000000000000 --- a/third_party/abseil_cpp/absl/random/uniform_real_distribution.h +++ /dev/null @@ -1,202 +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. -// -// ----------------------------------------------------------------------------- -// File: uniform_real_distribution.h -// ----------------------------------------------------------------------------- -// -// This header defines a class for representing a uniform floating-point -// distribution over a half-open interval [a,b). You use this distribution in -// combination with an Abseil random bit generator to produce random values -// according to the rules of the distribution. -// -// `absl::uniform_real_distribution` is a drop-in replacement for the C++11 -// `std::uniform_real_distribution` [rand.dist.uni.real] but is considerably -// faster than the libstdc++ implementation. -// -// Note: the standard-library version may occasionally return `1.0` when -// default-initialized. See https://bugs.llvm.org//show_bug.cgi?id=18767 -// `absl::uniform_real_distribution` does not exhibit this behavior. - -#ifndef ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_ -#define ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <cstdint> -#include <istream> -#include <limits> -#include <type_traits> - -#include "absl/meta/type_traits.h" -#include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/generate_real.h" -#include "absl/random/internal/iostream_state_saver.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::uniform_real_distribution<T> -// -// This distribution produces random floating-point values uniformly distributed -// over the half-open interval [a, b). -// -// Example: -// -// absl::BitGen gen; -// -// // Use the distribution to produce a value between 0.0 (inclusive) -// // and 1.0 (exclusive). -// double value = absl::uniform_real_distribution<double>(0, 1)(gen); -// -template <typename RealType = double> -class uniform_real_distribution { - public: - using result_type = RealType; - - class param_type { - public: - using distribution_type = uniform_real_distribution; - - explicit param_type(result_type lo = 0, result_type hi = 1) - : lo_(lo), hi_(hi), range_(hi - lo) { - // [rand.dist.uni.real] preconditions 2 & 3 - assert(lo <= hi); - // NOTE: For integral types, we can promote the range to an unsigned type, - // which gives full width of the range. However for real (fp) types, this - // is not possible, so value generation cannot use the full range of the - // real type. - assert(range_ <= (std::numeric_limits<result_type>::max)()); - assert(std::isfinite(range_)); - } - - result_type a() const { return lo_; } - result_type b() const { return hi_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.lo_ == b.lo_ && a.hi_ == b.hi_; - } - - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class uniform_real_distribution; - result_type lo_, hi_, range_; - - static_assert(std::is_floating_point<RealType>::value, - "Class-template absl::uniform_real_distribution<> must be " - "parameterized using a floating-point type."); - }; - - uniform_real_distribution() : uniform_real_distribution(0) {} - - explicit uniform_real_distribution(result_type lo, result_type hi = 1) - : param_(lo, hi) {} - - explicit uniform_real_distribution(const param_type& param) : param_(param) {} - - // uniform_real_distribution<T>::reset() - // - // Resets the uniform real distribution. Note that this function has no effect - // because the distribution already produces independent values. - void reset() {} - - template <typename URBG> - result_type operator()(URBG& gen) { // NOLINT(runtime/references) - return operator()(gen, param_); - } - - template <typename URBG> - result_type operator()(URBG& gen, // NOLINT(runtime/references) - const param_type& p); - - result_type a() const { return param_.a(); } - result_type b() const { return param_.b(); } - - param_type param() const { return param_; } - void param(const param_type& params) { param_ = params; } - - result_type(min)() const { return a(); } - result_type(max)() const { return b(); } - - friend bool operator==(const uniform_real_distribution& a, - const uniform_real_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const uniform_real_distribution& a, - const uniform_real_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; - random_internal::FastUniformBits<uint64_t> fast_u64_; -}; - -// ----------------------------------------------------------------------------- -// Implementation details follow -// ----------------------------------------------------------------------------- -template <typename RealType> -template <typename URBG> -typename uniform_real_distribution<RealType>::result_type -uniform_real_distribution<RealType>::operator()( - URBG& gen, const param_type& p) { // NOLINT(runtime/references) - using random_internal::GeneratePositiveTag; - using random_internal::GenerateRealFromBits; - using real_type = - absl::conditional_t<std::is_same<RealType, float>::value, float, double>; - - while (true) { - const result_type sample = - GenerateRealFromBits<real_type, GeneratePositiveTag, true>( - fast_u64_(gen)); - const result_type res = p.a() + (sample * p.range_); - if (res < p.b() || p.range_ <= 0 || !std::isfinite(p.range_)) { - return res; - } - // else sample rejected, try again. - } -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const uniform_real_distribution<RealType>& x) { - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<RealType>::kPrecision); - os << x.a() << os.fill() << x.b(); - return os; -} - -template <typename CharT, typename Traits, typename RealType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - uniform_real_distribution<RealType>& x) { // NOLINT(runtime/references) - using param_type = typename uniform_real_distribution<RealType>::param_type; - using result_type = typename uniform_real_distribution<RealType>::result_type; - auto saver = random_internal::make_istream_state_saver(is); - auto a = random_internal::read_floating_point<result_type>(is); - if (is.fail()) return is; - auto b = random_internal::read_floating_point<result_type>(is); - if (!is.fail()) { - x.param(param_type(a, b)); - } - return is; -} -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/uniform_real_distribution_test.cc b/third_party/abseil_cpp/absl/random/uniform_real_distribution_test.cc deleted file mode 100644 index be107cdde467..000000000000 --- a/third_party/abseil_cpp/absl/random/uniform_real_distribution_test.cc +++ /dev/null @@ -1,343 +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/uniform_real_distribution.h" - -#include <cmath> -#include <cstdint> -#include <iterator> -#include <random> -#include <sstream> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/distribution_test_util.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" - -// NOTES: -// * Some documentation on generating random real values suggests that -// it is possible to use std::nextafter(b, DBL_MAX) to generate a value on -// the closed range [a, b]. Unfortunately, that technique is not universally -// reliable due to floating point quantization. -// -// * absl::uniform_real_distribution<float> generates between 2^28 and 2^29 -// distinct floating point values in the range [0, 1). -// -// * absl::uniform_real_distribution<float> generates at least 2^23 distinct -// floating point values in the range [1, 2). This should be the same as -// any other range covered by a single exponent in IEEE 754. -// -// * absl::uniform_real_distribution<double> generates more than 2^52 distinct -// values in the range [0, 1), and should generate at least 2^52 distinct -// values in the range of [1, 2). -// - -namespace { - -template <typename RealType> -class UniformRealDistributionTest : public ::testing::Test {}; - -#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) { - using param_type = - typename absl::uniform_real_distribution<TypeParam>::param_type; - - constexpr const TypeParam a{1152921504606846976}; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - for (const auto& param : { - param_type(), - param_type(TypeParam(2.0), TypeParam(2.0)), // Same - param_type(TypeParam(-0.1), TypeParam(0.1)), - param_type(TypeParam(0.05), TypeParam(0.12)), - param_type(TypeParam(-0.05), TypeParam(0.13)), - param_type(TypeParam(-0.05), TypeParam(-0.02)), - // double range = 0 - // 2^60 , 2^60 + 2^6 - param_type(a, TypeParam(1152921504606847040)), - // 2^60 , 2^60 + 2^7 - param_type(a, TypeParam(1152921504606847104)), - // double range = 2^8 - // 2^60 , 2^60 + 2^8 - param_type(a, TypeParam(1152921504606847232)), - // float range = 0 - // 2^60 , 2^60 + 2^36 - param_type(a, TypeParam(1152921573326323712)), - // 2^60 , 2^60 + 2^37 - param_type(a, TypeParam(1152921642045800448)), - // float range = 2^38 - // 2^60 , 2^60 + 2^38 - param_type(a, TypeParam(1152921779484753920)), - // Limits - param_type(0, std::numeric_limits<TypeParam>::max()), - param_type(std::numeric_limits<TypeParam>::lowest(), 0), - param_type(0, std::numeric_limits<TypeParam>::epsilon()), - param_type(-std::numeric_limits<TypeParam>::epsilon(), - std::numeric_limits<TypeParam>::epsilon()), - param_type(std::numeric_limits<TypeParam>::epsilon(), - 2 * std::numeric_limits<TypeParam>::epsilon()), - }) { - // Validate parameters. - const auto a = param.a(); - const auto b = param.b(); - absl::uniform_real_distribution<TypeParam> before(a, b); - EXPECT_EQ(before.a(), param.a()); - EXPECT_EQ(before.b(), param.b()); - - { - absl::uniform_real_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - } - - std::stringstream ss; - ss << before; - absl::uniform_real_distribution<TypeParam> after(TypeParam(1.0), - TypeParam(3.1)); - - EXPECT_NE(before.a(), after.a()); - EXPECT_NE(before.b(), after.b()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.a(), after.a()); - EXPECT_EQ(before.b(), after.b()); - EXPECT_EQ(before.param(), after.param()); - EXPECT_EQ(before, after); - - // Smoke test. - auto sample_min = after.max(); - auto sample_max = after.min(); - for (int i = 0; i < kCount; i++) { - auto sample = after(gen); - // Failure here indicates a bug in uniform_real_distribution::operator(), - // or bad parameters--range too large, etc. - if (after.min() == after.max()) { - EXPECT_EQ(sample, after.min()); - } else { - EXPECT_GE(sample, after.min()); - EXPECT_LT(sample, after.max()); - } - if (sample > sample_max) { - sample_max = sample; - } - if (sample < sample_min) { - sample_min = sample; - } - } - - if (!std::is_same<TypeParam, long double>::value) { - // static_cast<double>(long double) can overflow. - std::string msg = absl::StrCat("Range: ", static_cast<double>(sample_min), - ", ", static_cast<double>(sample_max)); - ABSL_RAW_LOG(INFO, "%s", msg.c_str()); - } - } -} - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4756) // Constant arithmetic overflow. -#endif -TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) { -#if GTEST_HAS_DEATH_TEST - // Hi < Lo - EXPECT_DEBUG_DEATH( - { absl::uniform_real_distribution<TypeParam> dist(10.0, 1.0); }, ""); - - // Hi - Lo > numeric_limits<>::max() - EXPECT_DEBUG_DEATH( - { - absl::uniform_real_distribution<TypeParam> dist( - std::numeric_limits<TypeParam>::lowest(), - std::numeric_limits<TypeParam>::max()); - }, - ""); -#endif // GTEST_HAS_DEATH_TEST -#if defined(NDEBUG) - // opt-mode, for invalid parameters, will generate a garbage value, - // but should not enter an infinite loop. - absl::InsecureBitGen gen; - { - absl::uniform_real_distribution<TypeParam> dist(10.0, 1.0); - auto x = dist(gen); - EXPECT_FALSE(std::isnan(x)) << x; - } - { - absl::uniform_real_distribution<TypeParam> dist( - std::numeric_limits<TypeParam>::lowest(), - std::numeric_limits<TypeParam>::max()); - auto x = dist(gen); - // Infinite result. - EXPECT_FALSE(std::isfinite(x)) << x; - } -#endif // NDEBUG -} -#ifdef _MSC_VER -#pragma warning(pop) // warning(disable:4756) -#endif - -TYPED_TEST(UniformRealDistributionTest, TestMoments) { - constexpr int kSize = 1000000; - std::vector<double> values(kSize); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6}; - - absl::uniform_real_distribution<TypeParam> dist; - for (int i = 0; i < kSize; i++) { - values[i] = dist(rng); - } - - const auto moments = - absl::random_internal::ComputeDistributionMoments(values); - EXPECT_NEAR(0.5, moments.mean, 0.01); - EXPECT_NEAR(1 / 12.0, moments.variance, 0.015); - EXPECT_NEAR(0.0, moments.skewness, 0.02); - EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.015); -} - -TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) { - using absl::random_internal::kChiSquared; - using param_type = - typename absl::uniform_real_distribution<TypeParam>::param_type; - - constexpr size_t kTrials = 100000; - constexpr int kBuckets = 50; - constexpr double kExpected = - static_cast<double>(kTrials) / static_cast<double>(kBuckets); - - // 1-in-100000 threshold, but remember, there are about 8 tests - // in this file. And the test could fail for other reasons. - // Empirically validated with --runs_per_test=10000. - const int kThreshold = - absl::random_internal::ChiSquareValue(kBuckets - 1, 0.999999); - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6}; - - for (const auto& param : {param_type(0, 1), param_type(5, 12), - param_type(-5, 13), param_type(-5, -2)}) { - const double min_val = param.a(); - const double max_val = param.b(); - const double factor = kBuckets / (max_val - min_val); - - std::vector<int32_t> counts(kBuckets, 0); - absl::uniform_real_distribution<TypeParam> dist(param); - for (size_t i = 0; i < kTrials; i++) { - auto x = dist(rng); - auto bucket = static_cast<size_t>((x - min_val) * factor); - counts[bucket]++; - } - - double chi_square = absl::random_internal::ChiSquareWithExpected( - std::begin(counts), std::end(counts), kExpected); - if (chi_square > kThreshold) { - double p_value = - absl::random_internal::ChiSquarePValue(chi_square, kBuckets); - - // Chi-squared test failed. Output does not appear to be uniform. - std::string msg; - for (const auto& a : counts) { - absl::StrAppend(&msg, a, "\n"); - } - absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n"); - absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ", - kThreshold); - ABSL_RAW_LOG(INFO, "%s", msg.c_str()); - FAIL() << msg; - } - } -} - -TYPED_TEST(UniformRealDistributionTest, StabilityTest) { - // absl::uniform_real_distribution stability relies only on - // random_internal::RandU64ToDouble and random_internal::RandU64ToFloat. - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(12); - - absl::uniform_real_distribution<TypeParam> dist; - std::generate(std::begin(output), std::end(output), [&] { - return static_cast<int>(TypeParam(1000000) * dist(urbg)); - }); - - EXPECT_THAT( - output, // - testing::ElementsAre(59, 999246, 762494, 395876, 167716, 82545, 925251, - 77341, 12527, 708791, 834451, 932808)); -} - -TEST(UniformRealDistributionTest, AlgorithmBounds) { - absl::uniform_real_distribution<double> dist; - - { - // This returns the smallest value >0 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0x0000000000000001ull}); - double a = dist(urbg); - EXPECT_EQ(a, 5.42101086242752217004e-20); - } - - { - // This returns a value very near 0.5 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull}); - double a = dist(urbg); - EXPECT_EQ(a, 0.499999999999999944489); - } - { - // This returns a value very near 0.5 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0x8000000000000000ull}); - double a = dist(urbg); - EXPECT_EQ(a, 0.5); - } - - { - // This returns the largest value <1 from absl::uniform_real_distribution. - absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFEFull}); - double a = dist(urbg); - EXPECT_EQ(a, 0.999999999999999888978); - } - { - // This *ALSO* returns the largest value <1. - absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull}); - double a = dist(urbg); - EXPECT_EQ(a, 0.999999999999999888978); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/random/zipf_distribution.h b/third_party/abseil_cpp/absl/random/zipf_distribution.h deleted file mode 100644 index 22ebc756cfef..000000000000 --- a/third_party/abseil_cpp/absl/random/zipf_distribution.h +++ /dev/null @@ -1,271 +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. - -#ifndef ABSL_RANDOM_ZIPF_DISTRIBUTION_H_ -#define ABSL_RANDOM_ZIPF_DISTRIBUTION_H_ - -#include <cassert> -#include <cmath> -#include <istream> -#include <limits> -#include <ostream> -#include <type_traits> - -#include "absl/random/internal/iostream_state_saver.h" -#include "absl/random/uniform_real_distribution.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::zipf_distribution produces random integer-values in the range [0, k], -// distributed according to the discrete probability function: -// -// P(x) = (v + x) ^ -q -// -// The parameter `v` must be greater than 0 and the parameter `q` must be -// greater than 1. If either of these parameters take invalid values then the -// behavior is undefined. -// -// IntType is the result_type generated by the generator. It must be of integral -// type; a static_assert ensures this is the case. -// -// The implementation is based on W.Hormann, G.Derflinger: -// -// "Rejection-Inversion to Generate Variates from Monotone Discrete -// Distributions" -// -// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz -// -template <typename IntType = int> -class zipf_distribution { - public: - using result_type = IntType; - - class param_type { - public: - using distribution_type = zipf_distribution; - - // Preconditions: k > 0, v > 0, q > 1 - // The precondidtions are validated when NDEBUG is not defined via - // a pair of assert() directives. - // If NDEBUG is defined and either or both of these parameters take invalid - // values, the behavior of the class is undefined. - explicit param_type(result_type k = (std::numeric_limits<IntType>::max)(), - double q = 2.0, double v = 1.0); - - result_type k() const { return k_; } - double q() const { return q_; } - double v() const { return v_; } - - friend bool operator==(const param_type& a, const param_type& b) { - return a.k_ == b.k_ && a.q_ == b.q_ && a.v_ == b.v_; - } - friend bool operator!=(const param_type& a, const param_type& b) { - return !(a == b); - } - - private: - friend class zipf_distribution; - inline double h(double x) const; - inline double hinv(double x) const; - inline double compute_s() const; - inline double pow_negative_q(double x) const; - - // Parameters here are exactly the same as the parameters of Algorithm ZRI - // in the paper. - IntType k_; - double q_; - double v_; - - double one_minus_q_; // 1-q - double s_; - double one_minus_q_inv_; // 1 / 1-q - double hxm_; // h(k + 0.5) - double hx0_minus_hxm_; // h(x0) - h(k + 0.5) - - static_assert(std::is_integral<IntType>::value, - "Class-template absl::zipf_distribution<> must be " - "parameterized using an integral type."); - }; - - zipf_distribution() - : zipf_distribution((std::numeric_limits<IntType>::max)()) {} - - explicit zipf_distribution(result_type k, double q = 2.0, double v = 1.0) - : param_(k, q, v) {} - - explicit zipf_distribution(const param_type& p) : param_(p) {} - - void reset() {} - - template <typename URBG> - result_type operator()(URBG& g) { // NOLINT(runtime/references) - return (*this)(g, param_); - } - - template <typename URBG> - result_type operator()(URBG& g, // NOLINT(runtime/references) - const param_type& p); - - result_type k() const { return param_.k(); } - double q() const { return param_.q(); } - double v() const { return param_.v(); } - - param_type param() const { return param_; } - void param(const param_type& p) { param_ = p; } - - result_type(min)() const { return 0; } - result_type(max)() const { return k(); } - - friend bool operator==(const zipf_distribution& a, - const zipf_distribution& b) { - return a.param_ == b.param_; - } - friend bool operator!=(const zipf_distribution& a, - const zipf_distribution& b) { - return a.param_ != b.param_; - } - - private: - param_type param_; -}; - -// -------------------------------------------------------------------------- -// Implementation details follow -// -------------------------------------------------------------------------- - -template <typename IntType> -zipf_distribution<IntType>::param_type::param_type( - typename zipf_distribution<IntType>::result_type k, double q, double v) - : k_(k), q_(q), v_(v), one_minus_q_(1 - q) { - assert(q > 1); - assert(v > 0); - assert(k > 0); - one_minus_q_inv_ = 1 / one_minus_q_; - - // Setup for the ZRI algorithm (pg 17 of the paper). - // Compute: h(i max) => h(k + 0.5) - constexpr double kMax = 18446744073709549568.0; - double kd = static_cast<double>(k); - // TODO(absl-team): Determine if this check is needed, and if so, add a test - // that fails for k > kMax - if (kd > kMax) { - // Ensure that our maximum value is capped to a value which will - // round-trip back through double. - kd = kMax; - } - hxm_ = h(kd + 0.5); - - // Compute: h(0) - const bool use_precomputed = (v == 1.0 && q == 2.0); - const double h0x5 = use_precomputed ? (-1.0 / 1.5) // exp(-log(1.5)) - : h(0.5); - const double elogv_q = (v_ == 1.0) ? 1 : pow_negative_q(v_); - - // h(0) = h(0.5) - exp(log(v) * -q) - hx0_minus_hxm_ = (h0x5 - elogv_q) - hxm_; - - // And s - s_ = use_precomputed ? 0.46153846153846123 : compute_s(); -} - -template <typename IntType> -double zipf_distribution<IntType>::param_type::h(double x) const { - // std::exp(one_minus_q_ * std::log(v_ + x)) * one_minus_q_inv_; - x += v_; - return (one_minus_q_ == -1.0) - ? (-1.0 / x) // -exp(-log(x)) - : (std::exp(std::log(x) * one_minus_q_) * one_minus_q_inv_); -} - -template <typename IntType> -double zipf_distribution<IntType>::param_type::hinv(double x) const { - // std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)) - v_; - return -v_ + ((one_minus_q_ == -1.0) - ? (-1.0 / x) // exp(-log(-x)) - : std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x))); -} - -template <typename IntType> -double zipf_distribution<IntType>::param_type::compute_s() const { - // 1 - hinv(h(1.5) - std::exp(std::log(v_ + 1) * -q_)); - return 1.0 - hinv(h(1.5) - pow_negative_q(v_ + 1.0)); -} - -template <typename IntType> -double zipf_distribution<IntType>::param_type::pow_negative_q(double x) const { - // std::exp(std::log(x) * -q_); - return q_ == 2.0 ? (1.0 / (x * x)) : std::exp(std::log(x) * -q_); -} - -template <typename IntType> -template <typename URBG> -typename zipf_distribution<IntType>::result_type -zipf_distribution<IntType>::operator()( - URBG& g, const param_type& p) { // NOLINT(runtime/references) - absl::uniform_real_distribution<double> uniform_double; - double k; - for (;;) { - const double v = uniform_double(g); - const double u = p.hxm_ + v * p.hx0_minus_hxm_; - const double x = p.hinv(u); - k = rint(x); // std::floor(x + 0.5); - if (k > p.k()) continue; // reject k > max_k - if (k - x <= p.s_) break; - const double h = p.h(k + 0.5); - const double r = p.pow_negative_q(p.v_ + k); - if (u >= h - r) break; - } - IntType ki = static_cast<IntType>(k); - assert(ki <= p.k_); - return ki; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_ostream<CharT, Traits>& operator<<( - std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references) - const zipf_distribution<IntType>& x) { - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - auto saver = random_internal::make_ostream_state_saver(os); - os.precision(random_internal::stream_precision_helper<double>::kPrecision); - os << static_cast<stream_type>(x.k()) << os.fill() << x.q() << os.fill() - << x.v(); - return os; -} - -template <typename CharT, typename Traits, typename IntType> -std::basic_istream<CharT, Traits>& operator>>( - std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references) - zipf_distribution<IntType>& x) { // NOLINT(runtime/references) - using result_type = typename zipf_distribution<IntType>::result_type; - using param_type = typename zipf_distribution<IntType>::param_type; - using stream_type = - typename random_internal::stream_format_type<IntType>::type; - stream_type k; - double q; - double v; - - auto saver = random_internal::make_istream_state_saver(is); - is >> k >> q >> v; - if (!is.fail()) { - x.param(param_type(static_cast<result_type>(k), q, v)); - } - return is; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_ diff --git a/third_party/abseil_cpp/absl/random/zipf_distribution_test.cc b/third_party/abseil_cpp/absl/random/zipf_distribution_test.cc deleted file mode 100644 index f8cf70e0dddf..000000000000 --- a/third_party/abseil_cpp/absl/random/zipf_distribution_test.cc +++ /dev/null @@ -1,427 +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/zipf_distribution.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <random> -#include <string> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/internal/chi_square.h" -#include "absl/random/internal/pcg_engine.h" -#include "absl/random/internal/sequence_urbg.h" -#include "absl/random/random.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/strip.h" - -namespace { - -using ::absl::random_internal::kChiSquared; -using ::testing::ElementsAre; - -template <typename IntType> -class ZipfDistributionTypedTest : public ::testing::Test {}; - -using IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t, - uint8_t, uint16_t, uint32_t, uint64_t>; -TYPED_TEST_CASE(ZipfDistributionTypedTest, IntTypes); - -TYPED_TEST(ZipfDistributionTypedTest, SerializeTest) { - using param_type = typename absl::zipf_distribution<TypeParam>::param_type; - - constexpr int kCount = 1000; - absl::InsecureBitGen gen; - for (const auto& param : { - param_type(), - param_type(32), - param_type(100, 3, 2), - param_type(std::numeric_limits<TypeParam>::max(), 4, 3), - param_type(std::numeric_limits<TypeParam>::max() / 2), - }) { - // Validate parameters. - const auto k = param.k(); - const auto q = param.q(); - const auto v = param.v(); - - absl::zipf_distribution<TypeParam> before(k, q, v); - EXPECT_EQ(before.k(), param.k()); - EXPECT_EQ(before.q(), param.q()); - EXPECT_EQ(before.v(), param.v()); - - { - absl::zipf_distribution<TypeParam> via_param(param); - EXPECT_EQ(via_param, before); - } - - // Validate stream serialization. - std::stringstream ss; - ss << before; - absl::zipf_distribution<TypeParam> after(4, 5.5, 4.4); - - EXPECT_NE(before.k(), after.k()); - EXPECT_NE(before.q(), after.q()); - EXPECT_NE(before.v(), after.v()); - EXPECT_NE(before.param(), after.param()); - EXPECT_NE(before, after); - - ss >> after; - - EXPECT_EQ(before.k(), after.k()); - EXPECT_EQ(before.q(), after.q()); - EXPECT_EQ(before.v(), after.v()); - EXPECT_EQ(before.param(), after.param()); - EXPECT_EQ(before, after); - - // Smoke test. - auto sample_min = after.max(); - auto sample_max = after.min(); - for (int i = 0; i < kCount; i++) { - auto sample = after(gen); - EXPECT_GE(sample, after.min()); - EXPECT_LE(sample, after.max()); - if (sample > sample_max) sample_max = sample; - if (sample < sample_min) sample_min = sample; - } - ABSL_INTERNAL_LOG(INFO, - absl::StrCat("Range: ", +sample_min, ", ", +sample_max)); - } -} - -class ZipfModel { - public: - ZipfModel(size_t k, double q, double v) : k_(k), q_(q), v_(v) {} - - double mean() const { return mean_; } - - // For the other moments of the Zipf distribution, see, for example, - // http://mathworld.wolfram.com/ZipfDistribution.html - - // PMF(k) = (1 / k^s) / H(N,s) - // Returns the probability that any single invocation returns k. - double PMF(size_t i) { return i >= hnq_.size() ? 0.0 : hnq_[i] / sum_hnq_; } - - // CDF = H(k, s) / H(N,s) - double CDF(size_t i) { - if (i >= hnq_.size()) { - return 1.0; - } - auto it = std::begin(hnq_); - double h = 0.0; - for (const auto end = it; it != end; it++) { - h += *it; - } - return h / sum_hnq_; - } - - // The InverseCDF returns the k values which bound p on the upper and lower - // bound. Since there is no closed-form solution, this is implemented as a - // bisction of the cdf. - std::pair<size_t, size_t> InverseCDF(double p) { - size_t min = 0; - size_t max = hnq_.size(); - while (max > min + 1) { - size_t target = (max + min) >> 1; - double x = CDF(target); - if (x > p) { - max = target; - } else { - min = target; - } - } - return {min, max}; - } - - // Compute the probability totals, which are based on the generalized harmonic - // number, H(N,s). - // H(N,s) == SUM(k=1..N, 1 / k^s) - // - // In the limit, H(N,s) == zetac(s) + 1. - // - // NOTE: The mean of a zipf distribution could be computed here as well. - // Mean := H(N, s-1) / H(N,s). - // Given the parameter v = 1, this gives the following function: - // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944 - // - void Init() { - if (!hnq_.empty()) { - return; - } - hnq_.clear(); - hnq_.reserve(std::min(k_, size_t{1000})); - - sum_hnq_ = 0; - double qm1 = q_ - 1.0; - double sum_hnq_m1 = 0; - for (size_t i = 0; i < k_; i++) { - // Partial n-th generalized harmonic number - const double x = v_ + i; - - // H(n, q-1) - const double hnqm1 = - (q_ == 2.0) ? (1.0 / x) - : (q_ == 3.0) ? (1.0 / (x * x)) : std::pow(x, -qm1); - sum_hnq_m1 += hnqm1; - - // H(n, q) - const double hnq = - (q_ == 2.0) ? (1.0 / (x * x)) - : (q_ == 3.0) ? (1.0 / (x * x * x)) : std::pow(x, -q_); - sum_hnq_ += hnq; - hnq_.push_back(hnq); - if (i > 1000 && hnq <= 1e-10) { - // The harmonic number is too small. - break; - } - } - assert(sum_hnq_ > 0); - mean_ = sum_hnq_m1 / sum_hnq_; - } - - private: - const size_t k_; - const double q_; - const double v_; - - double mean_; - std::vector<double> hnq_; - double sum_hnq_; -}; - -using zipf_u64 = absl::zipf_distribution<uint64_t>; - -class ZipfTest : public testing::TestWithParam<zipf_u64::param_type>, - public ZipfModel { - public: - ZipfTest() : ZipfModel(GetParam().k(), GetParam().q(), GetParam().v()) {} - - // We use a fixed bit generator for distribution accuracy tests. This allows - // these tests to be deterministic, while still testing the qualify of the - // implementation. - absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6}; -}; - -TEST_P(ZipfTest, ChiSquaredTest) { - const auto& param = GetParam(); - Init(); - - size_t trials = 10000; - - // Find the split-points for the buckets. - std::vector<size_t> points; - std::vector<double> expected; - { - double last_cdf = 0.0; - double min_p = 1.0; - for (double p = 0.01; p < 1.0; p += 0.01) { - auto x = InverseCDF(p); - if (points.empty() || points.back() < x.second) { - const double p = CDF(x.second); - points.push_back(x.second); - double q = p - last_cdf; - expected.push_back(q); - last_cdf = p; - if (q < min_p) { - min_p = q; - } - } - } - if (last_cdf < 0.999) { - points.push_back(std::numeric_limits<size_t>::max()); - double q = 1.0 - last_cdf; - expected.push_back(q); - if (q < min_p) { - min_p = q; - } - } else { - points.back() = std::numeric_limits<size_t>::max(); - expected.back() += (1.0 - last_cdf); - } - // The Chi-Squared score is not completely scale-invariant; it works best - // when the small values are in the small digits. - trials = static_cast<size_t>(8.0 / min_p); - } - ASSERT_GT(points.size(), 0); - - // Generate n variates and fill the counts vector with the count of their - // occurrences. - std::vector<int64_t> buckets(points.size(), 0); - double avg = 0; - { - zipf_u64 dis(param); - for (size_t i = 0; i < trials; i++) { - uint64_t x = dis(rng_); - ASSERT_LE(x, dis.max()); - ASSERT_GE(x, dis.min()); - avg += static_cast<double>(x); - auto it = std::upper_bound(std::begin(points), std::end(points), - static_cast<size_t>(x)); - buckets[std::distance(std::begin(points), it)]++; - } - avg = avg / static_cast<double>(trials); - } - - // Validate the output using the Chi-Squared test. - for (auto& e : expected) { - e *= trials; - } - - // The null-hypothesis is that the distribution is a poisson distribution with - // the provided mean (not estimated from the data). - const int dof = static_cast<int>(expected.size()) - 1; - - // NOTE: This test runs about 15x per invocation, so a value of 0.9995 is - // approximately correct for a test suite failure rate of 1 in 100. In - // practice we see failures slightly higher than that. - const double threshold = absl::random_internal::ChiSquareValue(dof, 0.9999); - - const double chi_square = absl::random_internal::ChiSquare( - std::begin(buckets), std::end(buckets), std::begin(expected), - std::end(expected)); - - const double p_actual = - absl::random_internal::ChiSquarePValue(chi_square, dof); - - // Log if the chi_squared value is above the threshold. - if (chi_square > threshold) { - ABSL_INTERNAL_LOG(INFO, "values"); - for (size_t i = 0; i < expected.size(); i++) { - ABSL_INTERNAL_LOG(INFO, absl::StrCat(points[i], ": ", buckets[i], - " vs. E=", expected[i])); - } - ABSL_INTERNAL_LOG(INFO, absl::StrCat("trials ", trials)); - ABSL_INTERNAL_LOG(INFO, - absl::StrCat("mean ", avg, " vs. expected ", mean())); - ABSL_INTERNAL_LOG(INFO, absl::StrCat(kChiSquared, "(data, ", dof, ") = ", - chi_square, " (", p_actual, ")")); - ABSL_INTERNAL_LOG(INFO, - absl::StrCat(kChiSquared, " @ 0.9995 = ", threshold)); - FAIL() << kChiSquared << " value of " << chi_square - << " is above the threshold."; - } -} - -std::vector<zipf_u64::param_type> GenParams() { - using param = zipf_u64::param_type; - const auto k = param().k(); - const auto q = param().q(); - const auto v = param().v(); - const uint64_t k2 = 1 << 10; - return std::vector<zipf_u64::param_type>{ - // Default - param(k, q, v), - // vary K - param(4, q, v), param(1 << 4, q, v), param(k2, q, v), - // vary V - param(k2, q, 0.5), param(k2, q, 1.5), param(k2, q, 2.5), param(k2, q, 10), - // vary Q - param(k2, 1.5, v), param(k2, 3, v), param(k2, 5, v), param(k2, 10, v), - // Vary V & Q - param(k2, 1.5, 0.5), param(k2, 3, 1.5), param(k, 10, 10)}; -} - -std::string ParamName( - const ::testing::TestParamInfo<zipf_u64::param_type>& info) { - const auto& p = info.param; - std::string name = absl::StrCat("k_", p.k(), "__q_", absl::SixDigits(p.q()), - "__v_", absl::SixDigits(p.v())); - return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); -} - -INSTANTIATE_TEST_SUITE_P(All, ZipfTest, ::testing::ValuesIn(GenParams()), - ParamName); - -// NOTE: absl::zipf_distribution is not guaranteed to be stable. -TEST(ZipfDistributionTest, StabilityTest) { - // absl::zipf_distribution stability relies on - // absl::uniform_real_distribution, std::log, std::exp, std::log1p - absl::random_internal::sequence_urbg urbg( - {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, - 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, - 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, - 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull}); - - std::vector<int> output(10); - - { - absl::zipf_distribution<int32_t> dist; - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - EXPECT_THAT(output, ElementsAre(10031, 0, 0, 3, 6, 0, 7, 47, 0, 0)); - } - urbg.reset(); - { - absl::zipf_distribution<int32_t> dist(std::numeric_limits<int32_t>::max(), - 3.3); - std::generate(std::begin(output), std::end(output), - [&] { return dist(urbg); }); - EXPECT_THAT(output, ElementsAre(44, 0, 0, 0, 0, 1, 0, 1, 3, 0)); - } -} - -TEST(ZipfDistributionTest, AlgorithmBounds) { - absl::zipf_distribution<int32_t> dist; - - // Small values from absl::uniform_real_distribution map to larger Zipf - // distribution values. - const std::pair<uint64_t, int32_t> kInputs[] = { - {0xffffffffffffffff, 0x0}, {0x7fffffffffffffff, 0x0}, - {0x3ffffffffffffffb, 0x1}, {0x1ffffffffffffffd, 0x4}, - {0xffffffffffffffe, 0x9}, {0x7ffffffffffffff, 0x12}, - {0x3ffffffffffffff, 0x25}, {0x1ffffffffffffff, 0x4c}, - {0xffffffffffffff, 0x99}, {0x7fffffffffffff, 0x132}, - {0x3fffffffffffff, 0x265}, {0x1fffffffffffff, 0x4cc}, - {0xfffffffffffff, 0x999}, {0x7ffffffffffff, 0x1332}, - {0x3ffffffffffff, 0x2665}, {0x1ffffffffffff, 0x4ccc}, - {0xffffffffffff, 0x9998}, {0x7fffffffffff, 0x1332f}, - {0x3fffffffffff, 0x2665a}, {0x1fffffffffff, 0x4cc9e}, - {0xfffffffffff, 0x998e0}, {0x7ffffffffff, 0x133051}, - {0x3ffffffffff, 0x265ae4}, {0x1ffffffffff, 0x4c9ed3}, - {0xffffffffff, 0x98e223}, {0x7fffffffff, 0x13058c4}, - {0x3fffffffff, 0x25b178e}, {0x1fffffffff, 0x4a062b2}, - {0xfffffffff, 0x8ee23b8}, {0x7ffffffff, 0x10b21642}, - {0x3ffffffff, 0x1d89d89d}, {0x1ffffffff, 0x2fffffff}, - {0xffffffff, 0x45d1745d}, {0x7fffffff, 0x5a5a5a5a}, - {0x3fffffff, 0x69ee5846}, {0x1fffffff, 0x73ecade3}, - {0xfffffff, 0x79a9d260}, {0x7ffffff, 0x7cc0532b}, - {0x3ffffff, 0x7e5ad146}, {0x1ffffff, 0x7f2c0bec}, - {0xffffff, 0x7f95adef}, {0x7fffff, 0x7fcac0da}, - {0x3fffff, 0x7fe55ae2}, {0x1fffff, 0x7ff2ac0e}, - {0xfffff, 0x7ff955ae}, {0x7ffff, 0x7ffcaac1}, - {0x3ffff, 0x7ffe555b}, {0x1ffff, 0x7fff2aac}, - {0xffff, 0x7fff9556}, {0x7fff, 0x7fffcaab}, - {0x3fff, 0x7fffe555}, {0x1fff, 0x7ffff2ab}, - {0xfff, 0x7ffff955}, {0x7ff, 0x7ffffcab}, - {0x3ff, 0x7ffffe55}, {0x1ff, 0x7fffff2b}, - {0xff, 0x7fffff95}, {0x7f, 0x7fffffcb}, - {0x3f, 0x7fffffe5}, {0x1f, 0x7ffffff3}, - {0xf, 0x7ffffff9}, {0x7, 0x7ffffffd}, - {0x3, 0x7ffffffe}, {0x1, 0x7fffffff}, - }; - - for (const auto& instance : kInputs) { - absl::random_internal::sequence_urbg urbg({instance.first}); - EXPECT_EQ(instance.second, dist(urbg)); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/status/BUILD.bazel b/third_party/abseil_cpp/absl/status/BUILD.bazel deleted file mode 100644 index 189bd73d0e46..000000000000 --- a/third_party/abseil_cpp/absl/status/BUILD.bazel +++ /dev/null @@ -1,103 +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 package contains `absl::Status`. -# It will expand later to have utilities around `Status` like `StatusOr`, -# `StatusBuilder` and macros. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "status", - srcs = [ - "internal/status_internal.h", - "status.cc", - "status_payload_printer.cc", - ], - hdrs = [ - "status.h", - "status_payload_printer.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base:atomic_hook", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/container:inlined_vector", - "//absl/debugging:stacktrace", - "//absl/debugging:symbolize", - "//absl/strings", - "//absl/strings:cord", - "//absl/strings:str_format", - "//absl/types:optional", - ], -) - -cc_test( - name = "status_test", - srcs = ["status_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":status", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "statusor", - srcs = [ - "internal/statusor_internal.h", - "statusor.cc", - ], - hdrs = [ - "statusor.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":status", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/types:variant", - "//absl/utility", - ], -) - -cc_test( - name = "statusor_test", - size = "small", - srcs = ["statusor_test.cc"], - deps = [ - ":status", - ":statusor", - "//absl/base", - "//absl/memory", - "//absl/types:any", - "//absl/utility", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/status/CMakeLists.txt b/third_party/abseil_cpp/absl/status/CMakeLists.txt deleted file mode 100644 index f0d798a3732d..000000000000 --- a/third_party/abseil_cpp/absl/status/CMakeLists.txt +++ /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. -# -absl_cc_library( - NAME - status - 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::raw_logging_internal - absl::inlined_vector - absl::stacktrace - absl::symbolize - absl::strings - absl::cord - absl::str_format - absl::optional - PUBLIC -) - -absl_cc_test( - NAME - status_test - SRCS - "status_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::status - absl::strings - gmock_main -) - -absl_cc_library( - NAME - statusor - HDRS - "statusor.h" - SRCS - "statusor.cc" - "internal/statusor_internal.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - 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 - 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 279f8f55bef0..000000000000 --- a/third_party/abseil_cpp/absl/status/internal/status_internal.h +++ /dev/null @@ -1,58 +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" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -enum class StatusCode : int; - -namespace status_internal { - -// Container for status payloads. -struct Payload { - std::string type_url; - absl::Cord payload; -}; - -using Payloads = absl::InlinedVector<Payload, 1>; - -// Reference-counted representation of Status data. -struct StatusRep { - StatusRep(absl::StatusCode code, std::string message, - std::unique_ptr<status_internal::Payloads> payloads) - : ref(int32_t{1}), - code(code), - message(std::move(message)), - payloads(std::move(payloads)) {} - - std::atomic<int32_t> ref; - absl::StatusCode code; - std::string message; - std::unique_ptr<status_internal::Payloads> payloads; -}; - -absl::StatusCode MapToLocalCode(int value); -} // namespace status_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ diff --git a/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 eaac2c0b14c6..000000000000 --- 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 deleted file mode 100644 index c71de846827c..000000000000 --- a/third_party/abseil_cpp/absl/status/status.cc +++ /dev/null @@ -1,442 +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/status/status.h" - -#include <cassert> - -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/symbolize.h" -#include "absl/status/status_payload_printer.h" -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_split.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -std::string StatusCodeToString(StatusCode code) { - switch (code) { - case StatusCode::kOk: - return "OK"; - case StatusCode::kCancelled: - return "CANCELLED"; - case StatusCode::kUnknown: - return "UNKNOWN"; - case StatusCode::kInvalidArgument: - return "INVALID_ARGUMENT"; - case StatusCode::kDeadlineExceeded: - return "DEADLINE_EXCEEDED"; - case StatusCode::kNotFound: - return "NOT_FOUND"; - case StatusCode::kAlreadyExists: - return "ALREADY_EXISTS"; - case StatusCode::kPermissionDenied: - return "PERMISSION_DENIED"; - case StatusCode::kUnauthenticated: - return "UNAUTHENTICATED"; - case StatusCode::kResourceExhausted: - return "RESOURCE_EXHAUSTED"; - case StatusCode::kFailedPrecondition: - return "FAILED_PRECONDITION"; - case StatusCode::kAborted: - return "ABORTED"; - case StatusCode::kOutOfRange: - return "OUT_OF_RANGE"; - case StatusCode::kUnimplemented: - return "UNIMPLEMENTED"; - case StatusCode::kInternal: - return "INTERNAL"; - case StatusCode::kUnavailable: - return "UNAVAILABLE"; - case StatusCode::kDataLoss: - return "DATA_LOSS"; - default: - return ""; - } -} - -std::ostream& operator<<(std::ostream& os, StatusCode code) { - return os << StatusCodeToString(code); -} - -namespace status_internal { - -static int FindPayloadIndexByUrl(const Payloads* payloads, - absl::string_view type_url) { - if (payloads == nullptr) return -1; - - for (size_t i = 0; i < payloads->size(); ++i) { - if ((*payloads)[i].type_url == type_url) return i; - } - - return -1; -} - -// Convert canonical code to a value known to this binary. -absl::StatusCode MapToLocalCode(int value) { - absl::StatusCode code = static_cast<absl::StatusCode>(value); - switch (code) { - case absl::StatusCode::kOk: - case absl::StatusCode::kCancelled: - case absl::StatusCode::kUnknown: - case absl::StatusCode::kInvalidArgument: - case absl::StatusCode::kDeadlineExceeded: - case absl::StatusCode::kNotFound: - case absl::StatusCode::kAlreadyExists: - case absl::StatusCode::kPermissionDenied: - case absl::StatusCode::kResourceExhausted: - case absl::StatusCode::kFailedPrecondition: - case absl::StatusCode::kAborted: - case absl::StatusCode::kOutOfRange: - case absl::StatusCode::kUnimplemented: - case absl::StatusCode::kInternal: - case absl::StatusCode::kUnavailable: - case absl::StatusCode::kDataLoss: - case absl::StatusCode::kUnauthenticated: - return code; - default: - return absl::StatusCode::kUnknown; - } -} -} // namespace status_internal - -absl::optional<absl::Cord> Status::GetPayload( - absl::string_view type_url) const { - const auto* payloads = GetPayloads(); - int index = status_internal::FindPayloadIndexByUrl(payloads, type_url); - if (index != -1) return (*payloads)[index].payload; - - return absl::nullopt; -} - -void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { - if (ok()) return; - - PrepareToModify(); - - status_internal::StatusRep* rep = RepToPointer(rep_); - if (!rep->payloads) { - rep->payloads = absl::make_unique<status_internal::Payloads>(); - } - - int index = - status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url); - if (index != -1) { - (*rep->payloads)[index].payload = std::move(payload); - return; - } - - rep->payloads->push_back({std::string(type_url), std::move(payload)}); -} - -bool Status::ErasePayload(absl::string_view type_url) { - int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url); - if (index != -1) { - PrepareToModify(); - GetPayloads()->erase(GetPayloads()->begin() + index); - if (GetPayloads()->empty() && message().empty()) { - // Special case: If this can be represented inlined, it MUST be - // inlined (EqualsSlow depends on this behavior). - StatusCode c = static_cast<StatusCode>(raw_code()); - Unref(rep_); - rep_ = CodeToInlinedRep(c); - } - return true; - } - - return false; -} - -void Status::ForEachPayload( - const std::function<void(absl::string_view, const absl::Cord&)>& visitor) - const { - if (auto* payloads = GetPayloads()) { - bool in_reverse = - payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6; - - for (size_t index = 0; index < payloads->size(); ++index) { - const auto& elem = - (*payloads)[in_reverse ? payloads->size() - 1 - index : index]; - -#ifdef NDEBUG - visitor(elem.type_url, elem.payload); -#else - // In debug mode invalidate the type url to prevent users from relying on - // this string lifetime. - - // NOLINTNEXTLINE intentional extra conversion to force temporary. - visitor(std::string(elem.type_url), elem.payload); -#endif // NDEBUG - } - } -} - -const std::string* Status::EmptyString() { - static std::string* empty_string = new std::string(); - return empty_string; -} - -constexpr const char Status::kMovedFromString[]; - -const std::string* Status::MovedFromString() { - static std::string* moved_from_string = new std::string(kMovedFromString); - return moved_from_string; -} - -void Status::UnrefNonInlined(uintptr_t rep) { - status_internal::StatusRep* r = RepToPointer(rep); - // Fast path: if ref==1, there is no need for a RefCountDec (since - // this is the only reference and therefore no other thread is - // allowed to be mucking with r). - if (r->ref.load(std::memory_order_acquire) == 1 || - r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) { - delete r; - } -} - -uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg, - std::unique_ptr<status_internal::Payloads> payloads) { - status_internal::StatusRep* rep = new status_internal::StatusRep( - code, std::string(msg.data(), msg.size()), std::move(payloads)); - return PointerToRep(rep); -} - -Status::Status(absl::StatusCode code, absl::string_view msg) - : rep_(CodeToInlinedRep(code)) { - if (code != absl::StatusCode::kOk && !msg.empty()) { - rep_ = NewRep(code, msg, nullptr); - } -} - -int Status::raw_code() const { - if (IsInlined(rep_)) { - return static_cast<int>(InlinedRepToCode(rep_)); - } - status_internal::StatusRep* rep = RepToPointer(rep_); - return static_cast<int>(rep->code); -} - -absl::StatusCode Status::code() const { - return status_internal::MapToLocalCode(raw_code()); -} - -void Status::PrepareToModify() { - ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status."); - if (IsInlined(rep_)) { - rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()), - absl::string_view(), nullptr); - return; - } - - uintptr_t rep_i = rep_; - status_internal::StatusRep* rep = RepToPointer(rep_); - if (rep->ref.load(std::memory_order_acquire) != 1) { - std::unique_ptr<status_internal::Payloads> payloads; - if (rep->payloads) { - payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads); - } - rep_ = NewRep(rep->code, message(), std::move(payloads)); - UnrefNonInlined(rep_i); - } -} - -bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) { - if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false; - if (a.message() != b.message()) return false; - if (a.raw_code() != b.raw_code()) return false; - if (a.GetPayloads() == b.GetPayloads()) return true; - - const status_internal::Payloads no_payloads; - const status_internal::Payloads* larger_payloads = - a.GetPayloads() ? a.GetPayloads() : &no_payloads; - const status_internal::Payloads* smaller_payloads = - b.GetPayloads() ? b.GetPayloads() : &no_payloads; - if (larger_payloads->size() < smaller_payloads->size()) { - std::swap(larger_payloads, smaller_payloads); - } - if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false; - // Payloads can be ordered differently, so we can't just compare payload - // vectors. - for (const auto& payload : *larger_payloads) { - - bool found = false; - for (const auto& other_payload : *smaller_payloads) { - if (payload.type_url == other_payload.type_url) { - if (payload.payload != other_payload.payload) { - return false; - } - found = true; - break; - } - } - if (!found) return false; - } - return true; -} - -std::string Status::ToStringSlow() const { - std::string text; - absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message()); - status_internal::StatusPayloadPrinter printer = - status_internal::GetStatusPayloadPrinter(); - this->ForEachPayload([&](absl::string_view type_url, - const absl::Cord& payload) { - absl::optional<std::string> result; - if (printer) result = printer(type_url, payload); - absl::StrAppend( - &text, " [", type_url, "='", - result.has_value() ? *result : absl::CHexEscape(std::string(payload)), - "']"); - }); - - return text; -} - -std::ostream& operator<<(std::ostream& os, const Status& x) { - os << x.ToString(); - return os; -} - -Status AbortedError(absl::string_view message) { - return Status(absl::StatusCode::kAborted, message); -} - -Status AlreadyExistsError(absl::string_view message) { - return Status(absl::StatusCode::kAlreadyExists, message); -} - -Status CancelledError(absl::string_view message) { - return Status(absl::StatusCode::kCancelled, message); -} - -Status DataLossError(absl::string_view message) { - return Status(absl::StatusCode::kDataLoss, message); -} - -Status DeadlineExceededError(absl::string_view message) { - return Status(absl::StatusCode::kDeadlineExceeded, message); -} - -Status FailedPreconditionError(absl::string_view message) { - return Status(absl::StatusCode::kFailedPrecondition, message); -} - -Status InternalError(absl::string_view message) { - return Status(absl::StatusCode::kInternal, message); -} - -Status InvalidArgumentError(absl::string_view message) { - return Status(absl::StatusCode::kInvalidArgument, message); -} - -Status NotFoundError(absl::string_view message) { - return Status(absl::StatusCode::kNotFound, message); -} - -Status OutOfRangeError(absl::string_view message) { - return Status(absl::StatusCode::kOutOfRange, message); -} - -Status PermissionDeniedError(absl::string_view message) { - return Status(absl::StatusCode::kPermissionDenied, message); -} - -Status ResourceExhaustedError(absl::string_view message) { - return Status(absl::StatusCode::kResourceExhausted, message); -} - -Status UnauthenticatedError(absl::string_view message) { - return Status(absl::StatusCode::kUnauthenticated, message); -} - -Status UnavailableError(absl::string_view message) { - return Status(absl::StatusCode::kUnavailable, message); -} - -Status UnimplementedError(absl::string_view message) { - return Status(absl::StatusCode::kUnimplemented, message); -} - -Status UnknownError(absl::string_view message) { - return Status(absl::StatusCode::kUnknown, message); -} - -bool IsAborted(const Status& status) { - return status.code() == absl::StatusCode::kAborted; -} - -bool IsAlreadyExists(const Status& status) { - return status.code() == absl::StatusCode::kAlreadyExists; -} - -bool IsCancelled(const Status& status) { - return status.code() == absl::StatusCode::kCancelled; -} - -bool IsDataLoss(const Status& status) { - return status.code() == absl::StatusCode::kDataLoss; -} - -bool IsDeadlineExceeded(const Status& status) { - return status.code() == absl::StatusCode::kDeadlineExceeded; -} - -bool IsFailedPrecondition(const Status& status) { - return status.code() == absl::StatusCode::kFailedPrecondition; -} - -bool IsInternal(const Status& status) { - return status.code() == absl::StatusCode::kInternal; -} - -bool IsInvalidArgument(const Status& status) { - return status.code() == absl::StatusCode::kInvalidArgument; -} - -bool IsNotFound(const Status& status) { - return status.code() == absl::StatusCode::kNotFound; -} - -bool IsOutOfRange(const Status& status) { - return status.code() == absl::StatusCode::kOutOfRange; -} - -bool IsPermissionDenied(const Status& status) { - return status.code() == absl::StatusCode::kPermissionDenied; -} - -bool IsResourceExhausted(const Status& status) { - return status.code() == absl::StatusCode::kResourceExhausted; -} - -bool IsUnauthenticated(const Status& status) { - return status.code() == absl::StatusCode::kUnauthenticated; -} - -bool IsUnavailable(const Status& status) { - return status.code() == absl::StatusCode::kUnavailable; -} - -bool IsUnimplemented(const Status& status) { - return status.code() == absl::StatusCode::kUnimplemented; -} - -bool IsUnknown(const Status& status) { - return status.code() == absl::StatusCode::kUnknown; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/status.h b/third_party/abseil_cpp/absl/status/status.h deleted file mode 100644 index c4d6fce09050..000000000000 --- a/third_party/abseil_cpp/absl/status/status.h +++ /dev/null @@ -1,817 +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. -// -// ----------------------------------------------------------------------------- -// File: status.h -// ----------------------------------------------------------------------------- -// -// This header file defines the Abseil `status` library, consisting of: -// -// * An `absl::Status` class for holding error handling information -// * A set of canonical `absl::StatusCode` error codes, and associated -// utilities for generating and propagating status codes. -// * A set of helper functions for creating status codes and checking their -// values -// -// Within Google, `absl::Status` is the primary mechanism for gracefully -// handling errors across API boundaries (and in particular across RPC -// boundaries). Some of these errors may be recoverable, but others may not. -// Most functions that can produce a recoverable error should be designed to -// return an `absl::Status` (or `absl::StatusOr`). -// -// Example: -// -// absl::Status myFunction(absl::string_view fname, ...) { -// ... -// // encounter error -// if (error condition) { -// return absl::InvalidArgumentError("bad mode"); -// } -// // else, return OK -// return absl::OkStatus(); -// } -// -// An `absl::Status` is designed to either return "OK" or one of a number of -// different error codes, corresponding to typical error conditions. -// In almost all cases, when using `absl::Status` you should use the canonical -// error codes (of type `absl::StatusCode`) enumerated in this header file. -// These canonical codes are understood across the codebase and will be -// accepted across all API and RPC boundaries. -#ifndef ABSL_STATUS_STATUS_H_ -#define ABSL_STATUS_STATUS_H_ - -#include <iostream> -#include <string> - -#include "absl/container/inlined_vector.h" -#include "absl/status/internal/status_internal.h" -#include "absl/strings/cord.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::StatusCode -// -// An `absl::StatusCode` is an enumerated type indicating either no error ("OK") -// or an error condition. In most cases, an `absl::Status` indicates a -// recoverable error, and the purpose of signalling an error is to indicate what -// action to take in response to that error. These error codes map to the proto -// RPC error codes indicated in https://cloud.google.com/apis/design/errors. -// -// The errors listed below are the canonical errors associated with -// `absl::Status` and are used throughout the codebase. As a result, these -// error codes are somewhat generic. -// -// In general, try to return the most specific error that applies if more than -// one error may pertain. For example, prefer `kOutOfRange` over -// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or -// `kAlreadyExists` over `kFailedPrecondition`. -// -// Because these errors may travel RPC boundaries, these codes are tied to the -// `google.rpc.Code` definitions within -// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -// The string value of these RPC codes is denoted within each enum below. -// -// If your error handling code requires more context, you can attach payloads -// to your status. See `absl::Status::SetPayload()` and -// `absl::Status::GetPayload()` below. -enum class StatusCode : int { - // StatusCode::kOk - // - // kOK (gRPC code "OK") does not indicate an error; this value is returned on - // success. It is typical to check for this value before proceeding on any - // given call across an API or RPC boundary. To check this value, use the - // `absl::Status::ok()` member function rather than inspecting the raw code. - kOk = 0, - - // StatusCode::kCancelled - // - // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled, - // typically by the caller. - kCancelled = 1, - - // StatusCode::kUnknown - // - // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In - // general, more specific errors should be raised, if possible. Errors raised - // by APIs that do not return enough error information may be converted to - // this error. - kUnknown = 2, - - // StatusCode::kInvalidArgument - // - // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller - // specified an invalid argument, such a malformed filename. Note that such - // errors should be narrowly limited to indicate to the invalid nature of the - // arguments themselves. Errors with validly formed arguments that may cause - // errors with the state of the receiving system should be denoted with - // `kFailedPrecondition` instead. - kInvalidArgument = 3, - - // StatusCode::kDeadlineExceeded - // - // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline - // expired before the operation could complete. For operations that may change - // state within a system, this error may be returned even if the operation has - // completed successfully. For example, a successful response from a server - // could have been delayed long enough for the deadline to expire. - kDeadlineExceeded = 4, - - // StatusCode::kNotFound - // - // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as - // a file or directory) was not found. - // - // `kNotFound` is useful if a request should be denied for an entire class of - // users, such as during a gradual feature rollout or undocumented allow list. - // If, instead, a request should be denied for specific sets of users, such as - // through user-based access control, use `kPermissionDenied` instead. - kNotFound = 5, - - // StatusCode::kAlreadyExists - // - // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a - // caller attempted to create (such as file or directory) is already present. - kAlreadyExists = 6, - - // StatusCode::kPermissionDenied - // - // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller - // does not have permission to execute the specified operation. Note that this - // error is different than an error due to an *un*authenticated user. This - // error code does not imply the request is valid or the requested entity - // exists or satisfies any other pre-conditions. - // - // `kPermissionDenied` must not be used for rejections caused by exhausting - // some resource. Instead, use `kResourceExhausted` for those errors. - // `kPermissionDenied` must not be used if the caller cannot be identified. - // Instead, use `kUnauthenticated` for those errors. - kPermissionDenied = 7, - - // StatusCode::kResourceExhausted - // - // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource - // has been exhausted, perhaps a per-user quota, or perhaps the entire file - // system is out of space. - kResourceExhausted = 8, - - // StatusCode::kFailedPrecondition - // - // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the - // operation was rejected because the system is not in a state required for - // the operation's execution. For example, a directory to be deleted may be - // non-empty, an "rmdir" operation is applied to a non-directory, etc. - // - // Some guidelines that may help a service implementer in deciding between - // `kFailedPrecondition`, `kAborted`, and `kUnavailable`: - // - // (a) Use `kUnavailable` if the client can retry just the failing call. - // (b) Use `kAborted` if the client should retry at a higher transaction - // level (such as when a client-specified test-and-set fails, indicating - // the client should restart a read-modify-write sequence). - // (c) Use `kFailedPrecondition` if the client should not retry until - // the system state has been explicitly fixed. For example, if an "rmdir" - // fails because the directory is non-empty, `kFailedPrecondition` - // should be returned since the client should not retry unless - // the files are deleted from the directory. - kFailedPrecondition = 9, - - // StatusCode::kAborted - // - // kAborted (gRPC code "ABORTED") indicates the operation was aborted, - // typically due to a concurrency issue such as a sequencer check failure or a - // failed transaction. - // - // See the guidelines above for deciding between `kFailedPrecondition`, - // `kAborted`, and `kUnavailable`. - kAborted = 10, - - // StatusCode::kOutOfRange - // - // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was - // attempted past the valid range, such as seeking or reading past an - // end-of-file. - // - // Unlike `kInvalidArgument`, this error indicates a problem that may - // be fixed if the system state changes. For example, a 32-bit file - // system will generate `kInvalidArgument` if asked to read at an - // offset that is not in the range [0,2^32-1], but it will generate - // `kOutOfRange` if asked to read from an offset past the current - // file size. - // - // There is a fair bit of overlap between `kFailedPrecondition` and - // `kOutOfRange`. We recommend using `kOutOfRange` (the more specific - // error) when it applies so that callers who are iterating through - // a space can easily look for an `kOutOfRange` error to detect when - // they are done. - kOutOfRange = 11, - - // StatusCode::kUnimplemented - // - // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not - // implemented or supported in this service. In this case, the operation - // should not be re-attempted. - kUnimplemented = 12, - - // StatusCode::kInternal - // - // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred - // and some invariants expected by the underlying system have not been - // satisfied. This error code is reserved for serious errors. - kInternal = 13, - - // StatusCode::kUnavailable - // - // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently - // unavailable and that this is most likely a transient condition. An error - // such as this can be corrected by retrying with a backoff scheme. Note that - // it is not always safe to retry non-idempotent operations. - // - // See the guidelines above for deciding between `kFailedPrecondition`, - // `kAborted`, and `kUnavailable`. - kUnavailable = 14, - - // StatusCode::kDataLoss - // - // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or - // corruption has occurred. As this error is serious, proper alerting should - // be attached to errors such as this. - kDataLoss = 15, - - // StatusCode::kUnauthenticated - // - // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request - // does not have valid authentication credentials for the operation. Correct - // the authentication and try again. - kUnauthenticated = 16, - - // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ - // - // NOTE: this error code entry should not be used and you should not rely on - // its value, which may change. - // - // The purpose of this enumerated value is to force people who handle status - // codes with `switch()` statements to *not* simply enumerate all possible - // values, but instead provide a "default:" case. Providing such a default - // case ensures that code will compile when new codes are added. - kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20 -}; - -// StatusCodeToString() -// -// Returns the name for the status code, or "" if it is an unknown value. -std::string StatusCodeToString(StatusCode code); - -// operator<< -// -// Streams StatusCodeToString(code) to `os`. -std::ostream& operator<<(std::ostream& os, StatusCode code); - -// absl::Status -// -// The `absl::Status` class is generally used to gracefully handle errors -// across API boundaries (and in particular across RPC boundaries). Some of -// these errors may be recoverable, but others may not. Most -// functions which can produce a recoverable error should be designed to return -// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds -// either an object of type `T` or an error). -// -// API developers should construct their functions to return `absl::OkStatus()` -// upon success, or an `absl::StatusCode` upon another type of error (e.g -// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience -// functions to constuct each status code. -// -// Example: -// -// absl::Status myFunction(absl::string_view fname, ...) { -// ... -// // encounter error -// if (error condition) { -// // Construct an absl::StatusCode::kInvalidArgument error -// return absl::InvalidArgumentError("bad mode"); -// } -// // else, return OK -// return absl::OkStatus(); -// } -// -// Users handling status error codes should prefer checking for an OK status -// using the `ok()` member function. Handling multiple error codes may justify -// use of switch statement, but only check for error codes you know how to -// handle; do not try to exhaustively match against all canonical error codes. -// Errors that cannot be handled should be logged and/or propagated for higher -// levels to deal with. If you do use a switch statement, make sure that you -// also provide a `default:` switch case, so that code does not break as other -// canonical codes are added to the API. -// -// Example: -// -// absl::Status result = DoSomething(); -// if (!result.ok()) { -// LOG(ERROR) << result; -// } -// -// // Provide a default if switching on multiple error codes -// switch (result.code()) { -// // The user hasn't authenticated. Ask them to reauth -// case absl::StatusCode::kUnauthenticated: -// DoReAuth(); -// break; -// // The user does not have permission. Log an error. -// case absl::StatusCode::kPermissionDenied: -// LOG(ERROR) << result; -// break; -// // Propagate the error otherwise. -// default: -// return true; -// } -// -// An `absl::Status` can optionally include a payload with more information -// about the error. Typically, this payload serves one of several purposes: -// -// * It may provide more fine-grained semantic information about the error to -// facilitate actionable remedies. -// * It may provide human-readable contexual information that is more -// appropriate to display to an end user. -// -// Example: -// -// absl::Status result = DoSomething(); -// // Inform user to retry after 30 seconds -// // See more error details in googleapis/google/rpc/error_details.proto -// if (absl::IsResourceExhausted(result)) { -// google::rpc::RetryInfo info; -// info.retry_delay().seconds() = 30; -// // Payloads require a unique key (a URL to ensure no collisions with -// // other payloads), and an `absl::Cord` to hold the encoded data. -// absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo"; -// result.SetPayload(url, info.SerializeAsCord()); -// return result; -// } -// -class ABSL_MUST_USE_RESULT Status final { - public: - // Constructors - - // This default constructor creates an OK status with no message or payload. - // Avoid this constructor and prefer explicit construction of an OK status - // with `absl::OkStatus()`. - Status(); - - // Creates a status in the canonical error space with the specified - // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, - // `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., - // by printing a warning) if it is not. - Status(absl::StatusCode code, absl::string_view msg); - - Status(const Status&); - Status& operator=(const Status& x); - - // Move operators - - // The moved-from state is valid but unspecified. - Status(Status&&) noexcept; - Status& operator=(Status&&); - - ~Status(); - - // Status::Update() - // - // Updates the existing status with `new_status` provided that `this->ok()`. - // If the existing status already contains a non-OK error, this update has no - // effect and preserves the current data. Note that this behavior may change - // in the future to augment a current non-ok status with additional - // information about `new_status`. - // - // `Update()` provides a convenient way of keeping track of the first error - // encountered. - // - // Example: - // // Instead of "if (overall_status.ok()) overall_status = new_status" - // overall_status.Update(new_status); - // - void Update(const Status& new_status); - void Update(Status&& new_status); - - // Status::ok() - // - // Returns `true` if `this->ok()`. Prefer checking for an OK status using this - // member function. - ABSL_MUST_USE_RESULT bool ok() const; - - // Status::code() - // - // Returns the canonical error code of type `absl::StatusCode` of this status. - absl::StatusCode code() const; - - // Status::raw_code() - // - // Returns a raw (canonical) error code corresponding to the enum value of - // `google.rpc.Code` definitions within - // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto. - // These values could be out of the range of canonical `absl::StatusCode` - // enum values. - // - // NOTE: This function should only be called when converting to an associated - // wire format. Use `Status::code()` for error handling. - int raw_code() const; - - // Status::message() - // - // Returns the error message associated with this error code, if available. - // Note that this message rarely describes the error code. It is not unusual - // for the error message to be the empty string. As a result, prefer - // `Status::ToString()` for debug logging. - absl::string_view message() const; - - friend bool operator==(const Status&, const Status&); - friend bool operator!=(const Status&, const Status&); - - // Status::ToString() - // - // Returns a 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() const; - - // Status::IgnoreError() - // - // Ignores any errors. This method does nothing except potentially suppress - // complaints from any tools that are checking that errors are not dropped on - // the floor. - void IgnoreError() const; - - // swap() - // - // Swap the contents of one status with another. - friend void swap(Status& a, Status& b); - - //---------------------------------------------------------------------------- - // Payload Management APIs - //---------------------------------------------------------------------------- - - // A payload may be attached to a status to provide additional context to an - // error that may not be satisifed by an existing `absl::StatusCode`. - // Typically, this payload serves one of several purposes: - // - // * It may provide more fine-grained semantic information about the error - // to facilitate actionable remedies. - // * It may provide human-readable contexual information that is more - // appropriate to display to an end user. - // - // A payload consists of a [key,value] pair, where the key is a string - // referring to a unique "type URL" and the value is an object of type - // `absl::Cord` to hold the contextual data. - // - // The "type URL" should be unique and follow the format of a URL - // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some - // documentation or schema on how to interpret its associated data. For - // example, the default type URL for a protobuf message type is - // "type.googleapis.com/packagename.messagename". Other custom wire formats - // should define the format of type URL in a similar practice so as to - // minimize the chance of conflict between type URLs. - // Users should ensure that the type URL can be mapped to a concrete - // C++ type if they want to deserialize the payload and read it effectively. - // - // To attach a payload to a status object, call `Status::SetPayload()`, - // passing it the type URL and an `absl::Cord` of associated data. Similarly, - // to extract the payload from a status, call `Status::GetPayload()`. You - // may attach multiple payloads (with differing type URLs) to any given - // status object, provided that the status is currently exhibiting an error - // code (i.e. is not OK). - - // Status::GetPayload() - // - // Gets the payload of a status given its unique `type_url` key, if present. - absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const; - - // Status::SetPayload() - // - // Sets the payload for a non-ok status using a `type_url` key, overwriting - // any existing payload for that `type_url`. - // - // NOTE: This function does nothing if the Status is ok. - void SetPayload(absl::string_view type_url, absl::Cord payload); - - // Status::ErasePayload() - // - // Erases the payload corresponding to the `type_url` key. Returns `true` if - // the payload was present. - bool ErasePayload(absl::string_view type_url); - - // Status::ForEachPayload() - // - // Iterates over the stored payloads and calls the - // `visitor(type_key, payload)` callable for each one. - // - // NOTE: The order of calls to `visitor()` is not specified and may change at - // any time. - // - // NOTE: Any mutation on the same 'absl::Status' object during visitation is - // forbidden and could result in undefined behavior. - void ForEachPayload( - const std::function<void(absl::string_view, const absl::Cord&)>& visitor) - const; - - private: - friend Status CancelledError(); - - // Creates a status in the canonical error space with the specified - // code, and an empty error message. - explicit Status(absl::StatusCode code); - - static void UnrefNonInlined(uintptr_t rep); - static void Ref(uintptr_t rep); - static void Unref(uintptr_t rep); - - // REQUIRES: !ok() - // Ensures rep_ is not shared with any other Status. - void PrepareToModify(); - - const status_internal::Payloads* GetPayloads() const; - status_internal::Payloads* GetPayloads(); - - // Takes ownership of payload. - static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg, - std::unique_ptr<status_internal::Payloads> payload); - static bool EqualsSlow(const absl::Status& a, const absl::Status& b); - - // MSVC 14.0 limitation requires the const. - static constexpr const char kMovedFromString[] = - "Status accessed after move."; - - static const std::string* EmptyString(); - static const std::string* MovedFromString(); - - // Returns whether rep contains an inlined representation. - // See rep_ for details. - static bool IsInlined(uintptr_t rep); - - // Indicates whether this Status was the rhs of a move operation. See rep_ - // for details. - static bool IsMovedFrom(uintptr_t rep); - static uintptr_t MovedFromRep(); - - // Convert between error::Code and the inlined uintptr_t representation used - // by rep_. See rep_ for details. - static uintptr_t CodeToInlinedRep(absl::StatusCode code); - static absl::StatusCode InlinedRepToCode(uintptr_t rep); - - // Converts between StatusRep* and the external uintptr_t representation used - // by rep_. See rep_ for details. - static uintptr_t PointerToRep(status_internal::StatusRep* r); - static status_internal::StatusRep* RepToPointer(uintptr_t r); - - // Returns 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. - // It uses the canonical error space, no message or payload. - // The error code is (rep_ >> 2). - // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom(). - // - When the low bit is on it is an external representation. - // In this case all the data comes from a heap allocated Rep object. - // (rep_ - 1) is a status_internal::StatusRep* pointer to that structure. - uintptr_t rep_; -}; - -// OkStatus() -// -// Returns an OK status, equivalent to a default constructed instance. Prefer -// usage of `absl::OkStatus()` when constructing such an OK status. -Status OkStatus(); - -// operator<<() -// -// Prints a human-readable representation of `x` to `os`. -std::ostream& operator<<(std::ostream& os, const Status& x); - -// IsAborted() -// IsAlreadyExists() -// IsCancelled() -// IsDataLoss() -// IsDeadlineExceeded() -// IsFailedPrecondition() -// IsInternal() -// IsInvalidArgument() -// IsNotFound() -// IsOutOfRange() -// IsPermissionDenied() -// IsResourceExhausted() -// IsUnauthenticated() -// IsUnavailable() -// IsUnimplemented() -// IsUnknown() -// -// These convenience functions return `true` if a given status matches the -// `absl::StatusCode` error code of its associated function. -ABSL_MUST_USE_RESULT bool IsAborted(const Status& status); -ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status); -ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status); -ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status); -ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status); -ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status); -ABSL_MUST_USE_RESULT bool IsInternal(const Status& status); -ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status); -ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status); -ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status); -ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status); -ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status); - -// AbortedError() -// AlreadyExistsError() -// CancelledError() -// DataLossError() -// DeadlineExceededError() -// FailedPreconditionError() -// InternalError() -// InvalidArgumentError() -// NotFoundError() -// OutOfRangeError() -// PermissionDeniedError() -// ResourceExhaustedError() -// UnauthenticatedError() -// UnavailableError() -// UnimplementedError() -// UnknownError() -// -// These convenience functions create an `absl::Status` object with an error -// code as indicated by the associated function name, using the error message -// passed in `message`. -Status AbortedError(absl::string_view message); -Status AlreadyExistsError(absl::string_view message); -Status CancelledError(absl::string_view message); -Status DataLossError(absl::string_view message); -Status DeadlineExceededError(absl::string_view message); -Status FailedPreconditionError(absl::string_view message); -Status InternalError(absl::string_view message); -Status InvalidArgumentError(absl::string_view message); -Status NotFoundError(absl::string_view message); -Status OutOfRangeError(absl::string_view message); -Status PermissionDeniedError(absl::string_view message); -Status ResourceExhaustedError(absl::string_view message); -Status UnauthenticatedError(absl::string_view message); -Status UnavailableError(absl::string_view message); -Status UnimplementedError(absl::string_view message); -Status UnknownError(absl::string_view message); - -//------------------------------------------------------------------------------ -// Implementation details follow -//------------------------------------------------------------------------------ - -inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {} - -inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {} - -inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); } - -inline Status& Status::operator=(const Status& x) { - uintptr_t old_rep = rep_; - if (x.rep_ != old_rep) { - Ref(x.rep_); - rep_ = x.rep_; - Unref(old_rep); - } - return *this; -} - -inline Status::Status(Status&& x) noexcept : rep_(x.rep_) { - x.rep_ = MovedFromRep(); -} - -inline Status& Status::operator=(Status&& x) { - uintptr_t old_rep = rep_; - rep_ = x.rep_; - x.rep_ = MovedFromRep(); - Unref(old_rep); - return *this; -} - -inline void Status::Update(const Status& new_status) { - if (ok()) { - *this = new_status; - } -} - -inline void Status::Update(Status&& new_status) { - if (ok()) { - *this = std::move(new_status); - } -} - -inline Status::~Status() { Unref(rep_); } - -inline bool Status::ok() const { - return rep_ == CodeToInlinedRep(absl::StatusCode::kOk); -} - -inline absl::string_view Status::message() const { - return !IsInlined(rep_) - ? RepToPointer(rep_)->message - : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString) - : absl::string_view()); -} - -inline bool operator==(const Status& lhs, const Status& rhs) { - return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs); -} - -inline bool operator!=(const Status& lhs, const Status& rhs) { - return !(lhs == rhs); -} - -inline std::string Status::ToString() const { - return ok() ? "OK" : ToStringSlow(); -} - -inline void Status::IgnoreError() const { - // no-op -} - -inline void swap(absl::Status& a, absl::Status& b) { - using std::swap; - swap(a.rep_, b.rep_); -} - -inline const status_internal::Payloads* Status::GetPayloads() const { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); -} - -inline status_internal::Payloads* Status::GetPayloads() { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); -} - -inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; } - -inline bool Status::IsMovedFrom(uintptr_t rep) { - return IsInlined(rep) && (rep & 2) != 0; -} - -inline uintptr_t Status::MovedFromRep() { - return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; -} - -inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { - return static_cast<uintptr_t>(code) << 2; -} - -inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { - assert(IsInlined(rep)); - return static_cast<absl::StatusCode>(rep >> 2); -} - -inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { - assert(!IsInlined(rep)); - return reinterpret_cast<status_internal::StatusRep*>(rep - 1); -} - -inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { - return reinterpret_cast<uintptr_t>(rep) + 1; -} - -inline void Status::Ref(uintptr_t rep) { - if (!IsInlined(rep)) { - RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed); - } -} - -inline void Status::Unref(uintptr_t rep) { - if (!IsInlined(rep)) { - UnrefNonInlined(rep); - } -} - -inline Status OkStatus() { return Status(); } - -// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code -// and an empty message. It is provided only for efficiency, given that -// message-less kCancelled errors are common in the infrastructure. -inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUS_H_ diff --git a/third_party/abseil_cpp/absl/status/status_payload_printer.cc b/third_party/abseil_cpp/absl/status/status_payload_printer.cc deleted file mode 100644 index a47aea11c2d3..000000000000 --- a/third_party/abseil_cpp/absl/status/status_payload_printer.cc +++ /dev/null @@ -1,38 +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/status/status_payload_printer.h" - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/internal/atomic_hook.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace status_internal { - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES -static absl::base_internal::AtomicHook<StatusPayloadPrinter> storage; - -void SetStatusPayloadPrinter(StatusPayloadPrinter printer) { - storage.Store(printer); -} - -StatusPayloadPrinter GetStatusPayloadPrinter() { - return storage.Load(); -} - -} // namespace status_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/status_payload_printer.h b/third_party/abseil_cpp/absl/status/status_payload_printer.h deleted file mode 100644 index 5e0937f67da8..000000000000 --- a/third_party/abseil_cpp/absl/status/status_payload_printer.h +++ /dev/null @@ -1,51 +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_STATUS_PAYLOAD_PRINTER_H_ -#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_ - -#include <string> - -#include "absl/strings/cord.h" -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace status_internal { - -// By default, `Status::ToString` and `operator<<(Status)` print a payload by -// dumping the type URL and the raw bytes. To help debugging, we provide an -// extension point, which is a global printer function that can be set by users -// to specify how to print payloads. The function takes the type URL and the -// payload as input, and should return a valid human-readable string on success -// or `absl::nullopt` on failure (in which case it falls back to the default -// approach of printing the raw bytes). -// NOTE: This is an internal API and the design is subject to change in the -// future in a non-backward-compatible way. Since it's only meant for debugging -// purpose, you should not rely on it in any critical logic. -using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view, - const absl::Cord&); - -// Sets the global payload printer. Only one printer should be set per process. -// If multiple printers are set, it's undefined which one will be used. -void SetStatusPayloadPrinter(StatusPayloadPrinter); - -// Returns the global payload printer if previously set, otherwise `nullptr`. -StatusPayloadPrinter GetStatusPayloadPrinter(); - -} // namespace status_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_ diff --git a/third_party/abseil_cpp/absl/status/status_test.cc b/third_party/abseil_cpp/absl/status/status_test.cc deleted file mode 100644 index ca9488ad228c..000000000000 --- a/third_party/abseil_cpp/absl/status/status_test.cc +++ /dev/null @@ -1,458 +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/status/status.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" - -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Optional; -using ::testing::UnorderedElementsAreArray; - -TEST(StatusCode, InsertionOperator) { - const absl::StatusCode code = absl::StatusCode::kUnknown; - std::ostringstream oss; - oss << code; - EXPECT_EQ(oss.str(), absl::StatusCodeToString(code)); -} - -// This structure holds the details for testing a single error code, -// its creator, and its classifier. -struct ErrorTest { - absl::StatusCode code; - using Creator = absl::Status (*)(absl::string_view); - using Classifier = bool (*)(const absl::Status&); - Creator creator; - Classifier classifier; -}; - -constexpr ErrorTest kErrorTests[]{ - {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled}, - {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown}, - {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError, - absl::IsInvalidArgument}, - {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError, - absl::IsDeadlineExceeded}, - {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound}, - {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError, - absl::IsAlreadyExists}, - {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError, - absl::IsPermissionDenied}, - {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError, - absl::IsResourceExhausted}, - {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError, - absl::IsFailedPrecondition}, - {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted}, - {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange}, - {absl::StatusCode::kUnimplemented, absl::UnimplementedError, - absl::IsUnimplemented}, - {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal}, - {absl::StatusCode::kUnavailable, absl::UnavailableError, - absl::IsUnavailable}, - {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss}, - {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError, - absl::IsUnauthenticated}, -}; - -TEST(Status, CreateAndClassify) { - for (const auto& test : kErrorTests) { - SCOPED_TRACE(absl::StatusCodeToString(test.code)); - - // Ensure that the creator does, in fact, create status objects with the - // expected error code and message. - std::string message = - absl::StrCat("error code ", test.code, " test message"); - absl::Status status = test.creator(message); - EXPECT_EQ(test.code, status.code()); - EXPECT_EQ(message, status.message()); - - // Ensure that the classifier returns true for a status produced by the - // creator. - EXPECT_TRUE(test.classifier(status)); - - // Ensure that the classifier returns false for status with a different - // code. - for (const auto& other : kErrorTests) { - if (other.code != test.code) { - EXPECT_FALSE(test.classifier(absl::Status(other.code, ""))) - << " other.code = " << other.code; - } - } - } -} - -TEST(Status, DefaultConstructor) { - absl::Status status; - EXPECT_TRUE(status.ok()); - EXPECT_EQ(absl::StatusCode::kOk, status.code()); - EXPECT_EQ("", status.message()); -} - -TEST(Status, OkStatus) { - absl::Status status = absl::OkStatus(); - EXPECT_TRUE(status.ok()); - EXPECT_EQ(absl::StatusCode::kOk, status.code()); - EXPECT_EQ("", status.message()); -} - -TEST(Status, ConstructorWithCodeMessage) { - { - absl::Status status(absl::StatusCode::kCancelled, ""); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(absl::StatusCode::kCancelled, status.code()); - EXPECT_EQ("", status.message()); - } - { - absl::Status status(absl::StatusCode::kInternal, "message"); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(absl::StatusCode::kInternal, status.code()); - EXPECT_EQ("message", status.message()); - } -} - -TEST(Status, ConstructOutOfRangeCode) { - const int kRawCode = 9999; - absl::Status status(static_cast<absl::StatusCode>(kRawCode), ""); - EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); - EXPECT_EQ(kRawCode, status.raw_code()); -} - -constexpr char kUrl1[] = "url.payload.1"; -constexpr char kUrl2[] = "url.payload.2"; -constexpr char kUrl3[] = "url.payload.3"; -constexpr char kUrl4[] = "url.payload.xx"; - -constexpr char kPayload1[] = "aaaaa"; -constexpr char kPayload2[] = "bbbbb"; -constexpr char kPayload3[] = "ccccc"; - -using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>; - -TEST(Status, TestGetSetPayload) { - absl::Status ok_status = absl::OkStatus(); - ok_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - ok_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - EXPECT_FALSE(ok_status.GetPayload(kUrl1)); - EXPECT_FALSE(ok_status.GetPayload(kUrl2)); - - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1))); - EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2))); - - EXPECT_FALSE(bad_status.GetPayload(kUrl3)); - - bad_status.SetPayload(kUrl1, absl::Cord(kPayload3)); - EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3))); - - // Testing dynamically generated type_url - bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1)); - EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")), - Optional(Eq(kPayload1))); -} - -TEST(Status, TestErasePayload) { - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status.SetPayload(kUrl3, absl::Cord(kPayload3)); - - EXPECT_FALSE(bad_status.ErasePayload(kUrl4)); - - EXPECT_TRUE(bad_status.GetPayload(kUrl2)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl2)); - EXPECT_FALSE(bad_status.GetPayload(kUrl2)); - EXPECT_FALSE(bad_status.ErasePayload(kUrl2)); - - EXPECT_TRUE(bad_status.ErasePayload(kUrl1)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl3)); - - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl1)); -} - -TEST(Status, TestComparePayloads) { - absl::Status bad_status1(absl::StatusCode::kInternal, "fail"); - bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3)); - - absl::Status bad_status2(absl::StatusCode::kInternal, "fail"); - bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3)); - bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1)); - - EXPECT_EQ(bad_status1, bad_status2); -} - -TEST(Status, TestComparePayloadsAfterErase) { - absl::Status payload_status(absl::StatusCode::kInternal, ""); - payload_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - payload_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - absl::Status empty_status(absl::StatusCode::kInternal, ""); - - // Different payloads, not equal - EXPECT_NE(payload_status, empty_status); - EXPECT_TRUE(payload_status.ErasePayload(kUrl1)); - - // Still Different payloads, still not equal. - EXPECT_NE(payload_status, empty_status); - EXPECT_TRUE(payload_status.ErasePayload(kUrl2)); - - // Both empty payloads, should be equal - EXPECT_EQ(payload_status, empty_status); -} - -PayloadsVec AllVisitedPayloads(const absl::Status& s) { - PayloadsVec result; - - s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) { - result.push_back(std::make_pair(std::string(type_url), payload)); - }); - - return result; -} - -TEST(Status, TestForEachPayload) { - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status.SetPayload(kUrl3, absl::Cord(kPayload3)); - - int count = 0; - - bad_status.ForEachPayload( - [&count](absl::string_view, const absl::Cord&) { ++count; }); - - EXPECT_EQ(count, 3); - - PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)}, - {kUrl2, absl::Cord(kPayload2)}, - {kUrl3, absl::Cord(kPayload3)}}; - - // Test that we visit all the payloads in the status. - PayloadsVec visited_payloads = AllVisitedPayloads(bad_status); - EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads)); - - // Test that visitation order is not consistent between run. - std::vector<absl::Status> scratch; - while (true) { - scratch.emplace_back(absl::StatusCode::kInternal, "fail"); - - scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1)); - scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2)); - scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3)); - - if (AllVisitedPayloads(scratch.back()) != visited_payloads) { - break; - } - } -} - -TEST(Status, ToString) { - absl::Status s(absl::StatusCode::kInternal, "fail"); - EXPECT_EQ("INTERNAL: fail", s.ToString()); - s.SetPayload("foo", absl::Cord("bar")); - EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString()); - s.SetPayload("bar", absl::Cord("\377")); - EXPECT_THAT(s.ToString(), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"))); -} - -absl::Status EraseAndReturn(const absl::Status& base) { - absl::Status copy = base; - EXPECT_TRUE(copy.ErasePayload(kUrl1)); - return copy; -} - -TEST(Status, CopyOnWriteForErasePayload) { - { - absl::Status base(absl::StatusCode::kInvalidArgument, "fail"); - base.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - absl::Status copy = EraseAndReturn(base); - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - EXPECT_FALSE(copy.GetPayload(kUrl1).has_value()); - } - { - absl::Status base(absl::StatusCode::kInvalidArgument, "fail"); - base.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy = base; - - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - EXPECT_TRUE(copy.GetPayload(kUrl1).has_value()); - - EXPECT_TRUE(base.ErasePayload(kUrl1)); - - EXPECT_FALSE(base.GetPayload(kUrl1).has_value()); - EXPECT_TRUE(copy.GetPayload(kUrl1).has_value()); - } -} - -TEST(Status, CopyConstructor) { - { - absl::Status status; - absl::Status copy(status); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - absl::Status copy(status); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy(status); - EXPECT_EQ(copy, status); - } -} - -TEST(Status, CopyAssignment) { - absl::Status assignee; - { - absl::Status status; - assignee = status; - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - assignee = status; - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - assignee = status; - EXPECT_EQ(assignee, status); - } -} - -TEST(Status, CopyAssignmentIsNotRef) { - const absl::Status status_orig(absl::StatusCode::kInvalidArgument, "message"); - absl::Status status_copy = status_orig; - EXPECT_EQ(status_orig, status_copy); - status_copy.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_NE(status_orig, status_copy); -} - -TEST(Status, MoveConstructor) { - { - absl::Status status; - absl::Status copy(absl::Status{}); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - absl::Status copy( - absl::Status(absl::StatusCode::kInvalidArgument, "message")); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy1(status); - absl::Status copy2(std::move(status)); - EXPECT_EQ(copy1, copy2); - } -} - -TEST(Status, MoveAssignment) { - absl::Status assignee; - { - absl::Status status; - assignee = absl::Status(); - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message"); - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy(status); - assignee = std::move(status); - EXPECT_EQ(assignee, copy); - } -} - -TEST(Status, Update) { - absl::Status s; - s.Update(absl::OkStatus()); - EXPECT_TRUE(s.ok()); - const absl::Status a(absl::StatusCode::kCancelled, "message"); - s.Update(a); - EXPECT_EQ(s, a); - const absl::Status b(absl::StatusCode::kInternal, "other message"); - s.Update(b); - EXPECT_EQ(s, a); - s.Update(absl::OkStatus()); - EXPECT_EQ(s, a); - EXPECT_FALSE(s.ok()); -} - -TEST(Status, Equality) { - absl::Status ok; - absl::Status no_payload = absl::CancelledError("no payload"); - absl::Status one_payload = absl::InvalidArgumentError("one payload"); - one_payload.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status two_payloads = one_payload; - two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2)); - const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload, - two_payloads}; - for (int i = 0; i < status_arr.size(); i++) { - for (int j = 0; j < status_arr.size(); j++) { - if (i == j) { - EXPECT_TRUE(status_arr[i] == status_arr[j]); - EXPECT_FALSE(status_arr[i] != status_arr[j]); - } else { - EXPECT_TRUE(status_arr[i] != status_arr[j]); - EXPECT_FALSE(status_arr[i] == status_arr[j]); - } - } - } -} - -TEST(Status, Swap) { - auto test_swap = [](const absl::Status& s1, const absl::Status& s2) { - absl::Status copy1 = s1, copy2 = s2; - swap(copy1, copy2); - EXPECT_EQ(copy1, s2); - EXPECT_EQ(copy2, s1); - }; - const absl::Status ok; - const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload"); - absl::Status with_payload(absl::StatusCode::kInternal, "with payload"); - with_payload.SetPayload(kUrl1, absl::Cord(kPayload1)); - test_swap(ok, no_payload); - test_swap(no_payload, ok); - test_swap(ok, with_payload); - test_swap(with_payload, ok); - test_swap(no_payload, with_payload); - test_swap(with_payload, no_payload); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/status/statusor.cc b/third_party/abseil_cpp/absl/status/statusor.cc deleted file mode 100644 index b954b45e32c7..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor.cc +++ /dev/null @@ -1,71 +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/internal/raw_logging.h" -#include "absl/status/status.h" -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -BadStatusOrAccess::BadStatusOrAccess(absl::Status status) - : status_(std::move(status)) {} - -BadStatusOrAccess::~BadStatusOrAccess() = default; -const char* BadStatusOrAccess::what() const noexcept { - return "Bad StatusOr access"; -} - -const absl::Status& BadStatusOrAccess::status() const { return status_; } - -namespace internal_statusor { - -void Helper::HandleInvalidStatusCtorArg(absl::Status* status) { - const char* kMessage = - "An OK status is not a valid constructor argument to StatusOr<T>"; -#ifdef NDEBUG - ABSL_INTERNAL_LOG(ERROR, kMessage); -#else - ABSL_INTERNAL_LOG(FATAL, kMessage); -#endif - // In optimized builds, we will fall back to InternalError. - *status = absl::InternalError(kMessage); -} - -void Helper::Crash(const absl::Status& status) { - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Attempting to fetch value instead of handling error ", - status.ToString())); -} - -void ThrowBadStatusOrAccess(absl::Status status) { -#ifdef ABSL_HAVE_EXCEPTIONS - throw absl::BadStatusOrAccess(std::move(status)); -#else - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Attempting to fetch value instead of handling error ", - status.ToString())); - std::abort(); -#endif -} - -} // namespace internal_statusor -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/statusor.h b/third_party/abseil_cpp/absl/status/statusor.h deleted file mode 100644 index 469d486fdd2e..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor.h +++ /dev/null @@ -1,760 +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/meta/type_traits.h" -#include "absl/status/internal/statusor_internal.h" -#include "absl/status/status.h" -#include "absl/types/variant.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// BadStatusOrAccess -// -// This class defines the type of object to throw (if exceptions are enabled), -// when accessing the value of an `absl::StatusOr<T>` object that does not -// contain a value. This behavior is analogous to that of -// `std::bad_optional_access` in the case of accessing an invalid -// `std::optional` value. -// -// Example: -// -// try { -// absl::StatusOr<int> v = FetchInt(); -// DoWork(v.value()); // Accessing value() when not "OK" may throw -// } catch (absl::BadStatusOrAccess& ex) { -// LOG(ERROR) << ex.status(); -// } -class BadStatusOrAccess : public std::exception { - public: - explicit BadStatusOrAccess(absl::Status status); - ~BadStatusOrAccess() override; - - // BadStatusOrAccess::what() - // - // Returns the associated explanatory string of the `absl::StatusOr<T>` - // object's error code. This function only returns the string literal "Bad - // StatusOr Access" for cases when evaluating general exceptions. - // - // The pointer of this string is guaranteed to be valid until any non-const - // function is invoked on the exception object. - const char* what() const noexcept override; - - // BadStatusOrAccess::status() - // - // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's - // error. - const absl::Status& status() const; - - private: - absl::Status status_; -}; - -// Returned StatusOr objects may not be ignored. -template <typename T> -class ABSL_MUST_USE_RESULT StatusOr; - -// absl::StatusOr<T> -// -// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object -// and an object of type `T`. The `absl::StatusOr<T>` models an object that is -// either a usable object, or an error (of type `absl::Status`) explaining why -// such an object is not present. An `absl::StatusOr<T>` is typically the return -// value of a function which may fail. -// -// An `absl::StatusOr<T>` can never hold an "OK" status (an -// `absl::StatusCode::kOk` value); instead, the presence of an object of type -// `T` indicates success. Instead of checking for a `kOk` value, use the -// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code -// readability, that using the `ok()` function is preferred for `absl::Status` -// as well.) -// -// Example: -// -// StatusOr<Foo> result = DoBigCalculationThatCouldFail(); -// if (result.ok()) { -// result->DoSomethingCool(); -// } else { -// LOG(ERROR) << result.status(); -// } -// -// Accessing the object held by an `absl::StatusOr<T>` should be performed via -// `operator*` or `operator->`, after a call to `ok()` confirms that the -// `absl::StatusOr<T>` holds an object of type `T`: -// -// Example: -// -// absl::StatusOr<int> i = GetCount(); -// if (i.ok()) { -// updated_total += *i -// } -// -// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will -// throw an exception if exceptions are enabled or terminate the process when -// execeptions are not enabled. -// -// Example: -// -// StatusOr<Foo> result = DoBigCalculationThatCouldFail(); -// const Foo& foo = result.value(); // Crash/exception if no value present -// foo.DoSomethingCool(); -// -// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other -// pointer value, and the result will be that `ok()` returns `true` and -// `value()` returns `nullptr`. Checking the value of pointer in an -// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a -// value is present and that value is not null: -// -// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); -// if (!result.ok()) { -// LOG(ERROR) << result.status(); -// } else if (*result == nullptr) { -// LOG(ERROR) << "Unexpected null pointer"; -// } else { -// (*result)->DoSomethingCool(); -// } -// -// Example factory implementation returning StatusOr<T>: -// -// StatusOr<Foo> FooFactory::MakeFoo(int arg) { -// if (arg <= 0) { -// return absl::Status(absl::StatusCode::kInvalidArgument, -// "Arg must be positive"); -// } -// return Foo(arg); -// } -template <typename T> -class StatusOr : private internal_statusor::StatusOrData<T>, - private internal_statusor::CopyCtorBase<T>, - private internal_statusor::MoveCtorBase<T>, - private internal_statusor::CopyAssignBase<T>, - private internal_statusor::MoveAssignBase<T> { - template <typename U> - friend class StatusOr; - - typedef internal_statusor::StatusOrData<T> Base; - - public: - // StatusOr<T>::value_type - // - // This instance data provides a generic `value_type` member for use within - // generic programming. This usage is analogous to that of - // `optional::value_type` in the case of `std::optional`. - typedef T value_type; - - // Constructors - - // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown` - // status. This constructor is marked 'explicit' to prevent usages in return - // values such as 'return {};', under the misconception that - // `absl::StatusOr<std::vector<int>>` will be initialized with an empty - // vector, instead of an `absl::StatusCode::kUnknown` error code. - explicit StatusOr(); - - // `StatusOr<T>` is copy constructible if `T` is copy constructible. - StatusOr(const StatusOr&) = default; - // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy - // assignable. - StatusOr& operator=(const StatusOr&) = default; - - // `StatusOr<T>` is move constructible if `T` is move constructible. - StatusOr(StatusOr&&) = default; - // `StatusOr<T>` is moveAssignable if `T` is move constructible and move - // assignable. - StatusOr& operator=(StatusOr&&) = default; - - // Converting Constructors - - // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T` - // is constructible from `U`. To avoid ambiguity, these constructors are - // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor - // is explicit if and only if the corresponding construction of `T` from `U` - // is explicit. (This constructor inherits its explicitness from the - // underlying constructor.) - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - std::is_convertible<const U&, T>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr(const StatusOr<U>& other) // NOLINT - : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - absl::negation<std::is_convertible<const U&, T>>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - explicit StatusOr(const StatusOr<U>& other) - : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} - - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - std::is_convertible<U&&, T>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr(StatusOr<U>&& other) // NOLINT - : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - absl::negation<std::is_convertible<U&&, T>>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - explicit StatusOr(StatusOr<U>&& other) - : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} - - // Converting Assignment Operators - - // Creates an `absl::StatusOr<T>` through assignment from an - // `absl::StatusOr<U>` when: - // - // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning - // `U` to `T` directly. - // * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error - // code by destroying `absl::StatusOr<T>`'s value and assigning from - // `absl::StatusOr<U>' - // * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is - // OK by directly initializing `T` from `U`. - // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error - // code by assigning the `Status` in `absl::StatusOr<U>` to - // `absl::StatusOr<T>` - // - // These overloads only apply if `absl::StatusOr<T>` is constructible and - // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly - // assigned from `StatusOr<U>`. - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - std::is_assignable<T, const U&>, - absl::negation< - internal_statusor:: - IsConstructibleOrConvertibleOrAssignableFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr& operator=(const StatusOr<U>& other) { - this->Assign(other); - return *this; - } - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - std::is_assignable<T, U&&>, - absl::negation< - internal_statusor:: - IsConstructibleOrConvertibleOrAssignableFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr& operator=(StatusOr<U>&& other) { - this->Assign(std::move(other)); - return *this; - } - - // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling - // this constructor, `this->ok()` will be `false` and calls to `value()` will - // crash, or produce an exception if exceptions are enabled. - // - // The constructor also takes any type `U` that is convertible to - // `absl::Status`. This constructor is explicit if an only if `U` is not of - // type `absl::Status` and the conversion from `U` to `Status` is explicit. - // - // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed. - // In optimized builds, passing absl::OkStatus() here will have the effect - // of passing absl::StatusCode::kInternal as a fallback. - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - std::is_convertible<U&&, absl::Status>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - StatusOr(U&& v) : Base(std::forward<U>(v)) {} - - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {} - - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - std::is_convertible<U&&, absl::Status>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - StatusOr& operator=(U&& v) { - this->AssignStatus(std::forward<U>(v)); - return *this; - } - - // Perfect-forwarding value assignment operator. - - // If `*this` contains a `T` value before the call, the contained value is - // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized - // from `std::forward<U>(v)`. - // This function does not participate in overload unless: - // 1. `std::is_constructible_v<T, U>` is true, - // 2. `std::is_assignable_v<T&, U>` is true. - // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false. - // 4. Assigning `U` to `T` is not ambiguous: - // If `U` is `StatusOr<V>` and `T` is constructible and assignable from - // both `StatusOr<V>` and `V`, the assignment is considered bug-prone and - // ambiguous thus will fail to compile. For example: - // StatusOr<bool> s1 = true; // s1.ok() && *s1 == true - // StatusOr<bool> s2 = false; // s2.ok() && *s2 == false - // s1 = s2; // ambiguous, `s1 = *s2` or `s1 = bool(s2)`? - template < - typename U = T, - typename = typename std::enable_if<absl::conjunction< - std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>, - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - absl::negation<internal_statusor:: - HasConversionOperatorToStatusOr<T, U&&>>>>, - internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type> - StatusOr& operator=(U&& v) { - this->Assign(std::forward<U>(v)); - return *this; - } - - // Constructs the inner value `T` in-place using the provided args, using the - // `T(args...)` constructor. - template <typename... Args> - explicit StatusOr(absl::in_place_t, Args&&... args); - template <typename U, typename... Args> - explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist, - Args&&... args); - - // Constructs the inner value `T` in-place using the provided args, using the - // `T(U)` (direct-initialization) constructor. This constructor is only valid - // if `T` can be constructed from a `U`. Can accept move or copy constructors. - // - // This constructor is explicit if `U` is not convertible to `T`. To avoid - // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J` - // is convertible to `T`. - template < - typename U = T, - absl::enable_if_t< - absl::conjunction< - internal_statusor::IsDirectInitializationValid<T, U&&>, - std::is_constructible<T, U&&>, std::is_convertible<U&&, T>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - T>, - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - absl::negation< - internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>>>::value, - int> = 0> - StatusOr(U&& u) // NOLINT - : StatusOr(absl::in_place, std::forward<U>(u)) { - } - - template < - typename U = T, - absl::enable_if_t< - absl::conjunction< - internal_statusor::IsDirectInitializationValid<T, U&&>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - T>, - absl::conjunction< - absl::negation<std::is_constructible<absl::Status, U&&>>, - absl::negation< - internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>>, - std::is_constructible<T, U&&>, - absl::negation<std::is_convertible<U&&, T>>>::value, - int> = 0> - explicit StatusOr(U&& u) // NOLINT - : StatusOr(absl::in_place, std::forward<U>(u)) { - } - - // StatusOr<T>::ok() - // - // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This - // member function is analagous to `absl::Status::ok()` and should be used - // similarly to check the status of return values. - // - // Example: - // - // StatusOr<Foo> result = DoBigCalculationThatCouldFail(); - // if (result.ok()) { - // // Handle result - // else { - // // Handle error - // } - ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); } - - // StatusOr<T>::status() - // - // Returns a reference to the current `absl::Status` contained within the - // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this - // function returns `absl::OkStatus()`. - const Status& status() const &; - Status status() &&; - - // StatusOr<T>::value() - // - // Returns a reference to the held value if `this->ok()`. Otherwise, throws - // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to - // terminate the process if exceptions are disabled. - // - // If you have already checked the status using `this->ok()`, you probably - // want to use `operator*()` or `operator->()` to access the value instead of - // `value`. - // - // Note: for value types that are cheap to copy, prefer simple code: - // - // T value = statusor.value(); - // - // Otherwise, if the value type is expensive to copy, but can be left - // in the StatusOr, simply assign to a reference: - // - // T& value = statusor.value(); // or `const T&` - // - // Otherwise, if the value type supports an efficient move, it can be - // used as follows: - // - // T value = std::move(statusor).value(); - // - // The `std::move` on statusor instead of on the whole expression enables - // warnings about possible uses of the statusor object after the move. - const T& value() const&; - T& value() &; - const T&& value() const&&; - T&& value() &&; - - // StatusOr<T>:: operator*() - // - // Returns a reference to the current value. - // - // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. - // - // Use `this->ok()` to verify that there is a current value within the - // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a - // similar API that guarantees crashing or throwing an exception if there is - // no current value. - const T& operator*() const&; - T& operator*() &; - const T&& operator*() const&&; - T&& operator*() &&; - - // StatusOr<T>::operator->() - // - // Returns a pointer to the current value. - // - // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. - // - // Use `this->ok()` to verify that there is a current value. - const T* operator->() const; - T* operator->(); - - // StatusOr<T>::value_or() - // - // Returns the current value if `this->ok() == true`. Otherwise constructs a - // value using the provided `default_value`. - // - // Unlike `value`, this function returns by value, copying the current value - // if necessary. If the value type supports an efficient move, it can be used - // as follows: - // - // T value = std::move(statusor).value_or(def); - // - // Unlike with `value`, calling `std::move()` on the result of `value_or` will - // still trigger a copy. - template <typename U> - T value_or(U&& default_value) const&; - template <typename U> - T value_or(U&& default_value) &&; - - // StatusOr<T>::IgnoreError() - // - // Ignores any errors. This method does nothing except potentially suppress - // complaints from any tools that are checking that errors are not dropped on - // the floor. - void IgnoreError() const; - - // StatusOr<T>::emplace() - // - // Reconstructs the inner value T in-place using the provided args, using the - // T(args...) constructor. Returns reference to the reconstructed `T`. - template <typename... Args> - T& emplace(Args&&... args) { - if (ok()) { - this->Clear(); - this->MakeValue(std::forward<Args>(args)...); - } else { - this->MakeValue(std::forward<Args>(args)...); - this->status_ = absl::OkStatus(); - } - return this->data_; - } - - template < - typename U, typename... Args, - absl::enable_if_t< - std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, - int> = 0> - T& emplace(std::initializer_list<U> ilist, Args&&... args) { - if (ok()) { - this->Clear(); - this->MakeValue(ilist, std::forward<Args>(args)...); - } else { - this->MakeValue(ilist, std::forward<Args>(args)...); - this->status_ = absl::OkStatus(); - } - return this->data_; - } - - private: - using internal_statusor::StatusOrData<T>::Assign; - template <typename U> - void Assign(const absl::StatusOr<U>& other); - template <typename U> - void Assign(absl::StatusOr<U>&& other); -}; - -// operator==() -// -// This operator checks the equality of two `absl::StatusOr<T>` objects. -template <typename T> -bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { - if (lhs.ok() && rhs.ok()) return *lhs == *rhs; - return lhs.status() == rhs.status(); -} - -// operator!=() -// -// This operator checks the inequality of two `absl::StatusOr<T>` objects. -template <typename T> -bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { - return !(lhs == rhs); -} - -//------------------------------------------------------------------------------ -// Implementation details for StatusOr<T> -//------------------------------------------------------------------------------ - -// TODO(sbenza): avoid the string here completely. -template <typename T> -StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {} - -template <typename T> -template <typename U> -inline void StatusOr<T>::Assign(const StatusOr<U>& other) { - if (other.ok()) { - this->Assign(*other); - } else { - this->AssignStatus(other.status()); - } -} - -template <typename T> -template <typename U> -inline void StatusOr<T>::Assign(StatusOr<U>&& other) { - if (other.ok()) { - this->Assign(*std::move(other)); - } else { - this->AssignStatus(std::move(other).status()); - } -} -template <typename T> -template <typename... Args> -StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args) - : Base(absl::in_place, std::forward<Args>(args)...) {} - -template <typename T> -template <typename U, typename... Args> -StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist, - Args&&... args) - : Base(absl::in_place, ilist, std::forward<Args>(args)...) {} - -template <typename T> -const Status& StatusOr<T>::status() const & { return this->status_; } -template <typename T> -Status StatusOr<T>::status() && { - return ok() ? OkStatus() : std::move(this->status_); -} - -template <typename T> -const T& StatusOr<T>::value() const& { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template <typename T> -T& StatusOr<T>::value() & { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template <typename T> -const T&& StatusOr<T>::value() const&& { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template <typename T> -T&& StatusOr<T>::value() && { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template <typename T> -const T& StatusOr<T>::operator*() const& { - this->EnsureOk(); - return this->data_; -} - -template <typename T> -T& StatusOr<T>::operator*() & { - this->EnsureOk(); - return this->data_; -} - -template <typename T> -const T&& StatusOr<T>::operator*() const&& { - this->EnsureOk(); - return std::move(this->data_); -} - -template <typename T> -T&& StatusOr<T>::operator*() && { - this->EnsureOk(); - return std::move(this->data_); -} - -template <typename T> -const T* StatusOr<T>::operator->() const { - this->EnsureOk(); - return &this->data_; -} - -template <typename T> -T* StatusOr<T>::operator->() { - this->EnsureOk(); - return &this->data_; -} - -template <typename T> -template <typename U> -T StatusOr<T>::value_or(U&& default_value) const& { - if (ok()) { - return this->data_; - } - return std::forward<U>(default_value); -} - -template <typename T> -template <typename U> -T StatusOr<T>::value_or(U&& default_value) && { - if (ok()) { - return std::move(this->data_); - } - return std::forward<U>(default_value); -} - -template <typename T> -void StatusOr<T>::IgnoreError() const { - // no-op -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUSOR_H_ diff --git a/third_party/abseil_cpp/absl/status/statusor_internals.h b/third_party/abseil_cpp/absl/status/statusor_internals.h deleted file mode 100644 index 5366c2840c37..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor_internals.h +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. 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 - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef ABSL_STATUS_STATUSOR_INTERNALS_H_ -#define ABSL_STATUS_STATUSOR_INTERNALS_H_ - -#include "absl/status/status.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace internal_statusor { - -class Helper { - public: - // Move type-agnostic error handling to the .cc. - static void HandleInvalidStatusCtorArg(Status*); - ABSL_ATTRIBUTE_NORETURN static void Crash(const 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> -void PlacementNew(void* p, Args&&... args) { -#if defined(__GNUC__) && !defined(__clang__) - // Teach gcc that 'p' cannot be null, fixing code size issues. - if (p == nullptr) __builtin_unreachable(); -#endif - 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(other.status_); - } - } - - template <typename U> - StatusOrData(const StatusOrData<U>& other) { - if (other.ok()) { - MakeValue(other.data_); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - template <typename U> - StatusOrData(StatusOrData<U>&& other) { - if (other.ok()) { - MakeValue(std::move(other.data_)); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - explicit StatusOrData(const T& value) : data_(value) { MakeStatus(); } - explicit StatusOrData(T&& value) : data_(std::move(value)) { MakeStatus(); } - - explicit StatusOrData(const Status& status) : status_(status) { - EnsureNotOk(); - } - explicit StatusOrData(Status&& status) : status_(std::move(status)) { - EnsureNotOk(); - } - - StatusOrData& operator=(const StatusOrData& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(other.data_); - else - Assign(other.status_); - return *this; - } - - StatusOrData& operator=(StatusOrData&& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(std::move(other.data_)); - else - Assign(std::move(other.status_)); - return *this; - } - - ~StatusOrData() { - if (ok()) { - status_.~Status(); - data_.~T(); - } else { - status_.~Status(); - } - } - - void Assign(const T& value) { - if (ok()) { - data_.~T(); - MakeValue(value); - } else { - MakeValue(value); - status_ = OkStatus(); - } - } - - void Assign(T&& value) { - if (ok()) { - data_.~T(); - MakeValue(std::move(value)); - } else { - MakeValue(std::move(value)); - status_ = OkStatus(); - } - } - - void Assign(const Status& status) { - Clear(); - status_ = status; - EnsureNotOk(); - } - - void Assign(Status&& status) { - Clear(); - // Note that we copy instead of moving the status here so that - // status.~StatusOrData() can call ok() without invoking UB. - status_ = status; - 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 (!ok()) Helper::Crash(status_); - } - - void EnsureNotOk() { - if (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 class to allow implicitly deleted constructors and assignment -// operations in StatusOr. -// TraitsBase will explicitly delete what it can't support and StatusOr will -// inherit that behavior implicitly. -template <bool Copy, bool Move> -struct TraitsBase { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = default; - TraitsBase(TraitsBase&&) = default; - TraitsBase& operator=(const TraitsBase&) = default; - TraitsBase& operator=(TraitsBase&&) = default; -}; - -template <> -struct TraitsBase<false, true> { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = delete; - TraitsBase(TraitsBase&&) = default; - TraitsBase& operator=(const TraitsBase&) = delete; - TraitsBase& operator=(TraitsBase&&) = default; -}; - -template <> -struct TraitsBase<false, false> { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = delete; - TraitsBase(TraitsBase&&) = delete; - TraitsBase& operator=(const TraitsBase&) = delete; - TraitsBase& operator=(TraitsBase&&) = delete; -}; - -} // namespace internal_statusor - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUSOR_INTERNALS_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 c2e8fb7e359e..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor_test.cc +++ /dev/null @@ -1,1811 +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 <type_traits> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/casts.h" -#include "absl/memory/memory.h" -#include "absl/status/status.h" -#include "absl/types/any.h" -#include "absl/utility/utility.h" - -namespace { - -using ::testing::AllOf; -using ::testing::AnyWith; -using ::testing::ElementsAre; -using ::testing::Field; -using ::testing::Ne; -using ::testing::Not; -using ::testing::Pointee; -using ::testing::VariantWith; - -#ifdef GTEST_HAS_STATUS_MATCHERS -using ::testing::status::IsOk; -using ::testing::status::IsOkAndHolds; -#else // GTEST_HAS_STATUS_MATCHERS -inline const ::absl::Status& GetStatus(const ::absl::Status& status) { - return status; -} - -template <typename T> -inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) { - return status.status(); -} - -// Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a -// reference to StatusOr<T>. -template <typename StatusOrType> -class IsOkAndHoldsMatcherImpl - : public ::testing::MatcherInterface<StatusOrType> { - public: - typedef - typename std::remove_reference<StatusOrType>::type::value_type value_type; - - template <typename InnerMatcher> - explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher) - : inner_matcher_(::testing::SafeMatcherCast<const value_type&>( - std::forward<InnerMatcher>(inner_matcher))) {} - - void DescribeTo(std::ostream* os) const override { - *os << "is OK and has a value that "; - inner_matcher_.DescribeTo(os); - } - - void DescribeNegationTo(std::ostream* os) const override { - *os << "isn't OK or has a value that "; - inner_matcher_.DescribeNegationTo(os); - } - - bool MatchAndExplain( - StatusOrType actual_value, - ::testing::MatchResultListener* result_listener) const override { - if (!actual_value.ok()) { - *result_listener << "which has status " << actual_value.status(); - return false; - } - - ::testing::StringMatchResultListener inner_listener; - const bool matches = - inner_matcher_.MatchAndExplain(*actual_value, &inner_listener); - const std::string inner_explanation = inner_listener.str(); - if (!inner_explanation.empty()) { - *result_listener << "which contains value " - << ::testing::PrintToString(*actual_value) << ", " - << inner_explanation; - } - return matches; - } - - private: - const ::testing::Matcher<const value_type&> inner_matcher_; -}; - -// Implements IsOkAndHolds(m) as a polymorphic matcher. -template <typename InnerMatcher> -class IsOkAndHoldsMatcher { - public: - explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher) - : inner_matcher_(std::move(inner_matcher)) {} - - // Converts this polymorphic matcher to a monomorphic matcher of the - // given type. StatusOrType can be either StatusOr<T> or a - // reference to StatusOr<T>. - template <typename StatusOrType> - operator ::testing::Matcher<StatusOrType>() const { // NOLINT - return ::testing::Matcher<StatusOrType>( - new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_)); - } - - private: - const InnerMatcher inner_matcher_; -}; - -// Monomorphic implementation of matcher IsOk() for a given type T. -// T can be Status, StatusOr<>, or a reference to either of them. -template <typename T> -class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> { - public: - void DescribeTo(std::ostream* os) const override { *os << "is OK"; } - void DescribeNegationTo(std::ostream* os) const override { - *os << "is not OK"; - } - bool MatchAndExplain(T actual_value, - ::testing::MatchResultListener*) const override { - return GetStatus(actual_value).ok(); - } -}; - -// Implements IsOk() as a polymorphic matcher. -class IsOkMatcher { - public: - template <typename T> - operator ::testing::Matcher<T>() const { // NOLINT - return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>()); - } -}; - -// Macros for testing the results of functions that return absl::Status or -// absl::StatusOr<T> (for any type T). -#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk()) - -// Returns a gMock matcher that matches a StatusOr<> whose status is -// OK and whose value matches the inner matcher. -template <typename InnerMatcher> -IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds( - InnerMatcher&& inner_matcher) { - return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>( - std::forward<InnerMatcher>(inner_matcher)); -} - -// Returns a gMock matcher that matches a Status or StatusOr<> which is OK. -inline IsOkMatcher IsOk() { return IsOkMatcher(); } -#endif // GTEST_HAS_STATUS_MATCHERS - -struct CopyDetector { - CopyDetector() = default; - explicit CopyDetector(int xx) : x(xx) {} - CopyDetector(CopyDetector&& d) noexcept - : x(d.x), copied(false), moved(true) {} - CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {} - CopyDetector& operator=(const CopyDetector& c) { - x = c.x; - copied = true; - moved = false; - return *this; - } - CopyDetector& operator=(CopyDetector&& c) noexcept { - x = c.x; - copied = false; - moved = true; - return *this; - } - int x = 0; - bool copied = false; - bool moved = false; -}; - -testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) { - return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b), - Field(&CopyDetector::copied, c)); -} - -class Base1 { - public: - virtual ~Base1() {} - int pad; -}; - -class Base2 { - public: - virtual ~Base2() {} - int yetotherpad; -}; - -class Derived : public Base1, public Base2 { - public: - virtual ~Derived() {} - int evenmorepad; -}; - -class CopyNoAssign { - public: - explicit CopyNoAssign(int value) : foo(value) {} - CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} - int foo; - - private: - const CopyNoAssign& operator=(const CopyNoAssign&); -}; - -absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() { - // Uses implicit constructor from T&& - return absl::make_unique<int>(0); -} - -TEST(StatusOr, ElementType) { - static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), ""); - static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), ""); -} - -TEST(StatusOr, TestMoveOnlyInitialization) { - absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr()); - ASSERT_TRUE(thing.ok()); - EXPECT_EQ(0, **thing); - int* previous = thing->get(); - - thing = ReturnUniquePtr(); - EXPECT_TRUE(thing.ok()); - EXPECT_EQ(0, **thing); - EXPECT_NE(previous, thing->get()); -} - -TEST(StatusOr, TestMoveOnlyValueExtraction) { - absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr()); - ASSERT_TRUE(thing.ok()); - std::unique_ptr<int> ptr = *std::move(thing); - EXPECT_EQ(0, *ptr); - - thing = std::move(ptr); - ptr = std::move(*thing); - EXPECT_EQ(0, *ptr); -} - -TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) { - std::unique_ptr<int> ptr(*ReturnUniquePtr()); - EXPECT_EQ(0, *ptr); -} - -TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) { - static_assert( - std::is_same<const int&&, - decltype( - std::declval<const absl::StatusOr<int>&&>().value())>(), - "value() for const temporaries should return const T&&"); -} - -TEST(StatusOr, TestMoveOnlyConversion) { - absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr()); - EXPECT_TRUE(const_thing.ok()); - EXPECT_EQ(0, **const_thing); - - // Test rvalue converting assignment - const int* const_previous = const_thing->get(); - const_thing = ReturnUniquePtr(); - EXPECT_TRUE(const_thing.ok()); - EXPECT_EQ(0, **const_thing); - EXPECT_NE(const_previous, const_thing->get()); -} - -TEST(StatusOr, TestMoveOnlyVector) { - // Sanity check that absl::StatusOr<MoveOnly> works in vector. - std::vector<absl::StatusOr<std::unique_ptr<int>>> vec; - vec.push_back(ReturnUniquePtr()); - vec.resize(2); - auto another_vec = std::move(vec); - EXPECT_EQ(0, **another_vec[0]); - EXPECT_EQ(absl::UnknownError(""), another_vec[1].status()); -} - -TEST(StatusOr, TestDefaultCtor) { - absl::StatusOr<int> thing; - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown); -} - -TEST(StatusOr, StatusCtorForwards) { - absl::Status status(absl::StatusCode::kInternal, "Some error"); - - EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error"); - EXPECT_EQ(status.message(), "Some error"); - - EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(), - "Some error"); - EXPECT_NE(status.message(), "Some error"); -} - -// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`, -// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether -// exceptions are enabled. -#ifdef ABSL_HAVE_EXCEPTIONS -#define EXPECT_DEATH_OR_THROW(statement, status_) \ - EXPECT_THROW( \ - { \ - try { \ - statement; \ - } catch (const absl::BadStatusOrAccess& e) { \ - EXPECT_EQ(e.status(), status_); \ - throw; \ - } \ - }, \ - absl::BadStatusOrAccess); -#else // ABSL_HAVE_EXCEPTIONS -#define EXPECT_DEATH_OR_THROW(statement, status) \ - EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString()); -#endif // ABSL_HAVE_EXCEPTIONS - -TEST(StatusOrDeathTest, TestDefaultCtorValue) { - absl::StatusOr<int> thing; - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); - const absl::StatusOr<int> thing2; - EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestValueNotOk) { - absl::StatusOr<int> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -TEST(StatusOrDeathTest, TestValueNotOkConst) { - const absl::StatusOr<int> thing(absl::UnknownError("")); - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) { - absl::StatusOr<int*> thing; - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestPointerValueNotOk) { - absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -TEST(StatusOrDeathTest, TestPointerValueNotOkConst) { - const absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -#if GTEST_HAS_DEATH_TEST -TEST(StatusOrDeathTest, TestStatusCtorStatusOk) { - EXPECT_DEBUG_DEATH( - { - // This will DCHECK - absl::StatusOr<int> thing(absl::OkStatus()); - // In optimized mode, we are actually going to get error::INTERNAL for - // status here, rather than crashing, so check that. - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal); - }, - "An OK status is not a valid constructor argument"); -} - -TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) { - EXPECT_DEBUG_DEATH( - { - absl::StatusOr<int*> thing(absl::OkStatus()); - // In optimized mode, we are actually going to get error::INTERNAL for - // status here, rather than crashing, so check that. - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal); - }, - "An OK status is not a valid constructor argument"); -} -#endif - -TEST(StatusOr, ValueAccessor) { - const int kIntValue = 110; - { - absl::StatusOr<int> status_or(kIntValue); - EXPECT_EQ(kIntValue, status_or.value()); - EXPECT_EQ(kIntValue, std::move(status_or).value()); - } - { - absl::StatusOr<CopyDetector> status_or(kIntValue); - EXPECT_THAT(status_or, - IsOkAndHolds(CopyDetectorHas(kIntValue, false, false))); - CopyDetector copy_detector = status_or.value(); - EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true)); - copy_detector = std::move(status_or).value(); - EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false)); - } -} - -TEST(StatusOr, BadValueAccess) { - const absl::Status kError = absl::CancelledError("message"); - absl::StatusOr<int> status_or(kError); - EXPECT_DEATH_OR_THROW(status_or.value(), kError); -} - -TEST(StatusOr, TestStatusCtor) { - absl::StatusOr<int> thing(absl::CancelledError()); - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled); -} - - - -TEST(StatusOr, TestValueCtor) { - const int kI = 4; - const absl::StatusOr<int> thing(kI); - EXPECT_TRUE(thing.ok()); - EXPECT_EQ(kI, *thing); -} - -struct Foo { - const int x; - explicit Foo(int y) : x(y) {} -}; - -TEST(StatusOr, InPlaceConstruction) { - EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10), - IsOkAndHolds(Field(&Foo::x, 10))); -} - -struct InPlaceHelper { - InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy) - : x(xs), y(std::move(yy)) {} - const std::vector<int> x; - std::unique_ptr<int> y; -}; - -TEST(StatusOr, InPlaceInitListConstruction) { - absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12}, - absl::make_unique<int>(13)); - EXPECT_THAT(status_or, IsOkAndHolds(AllOf( - Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)), - Field(&InPlaceHelper::y, Pointee(13))))); -} - -TEST(StatusOr, Emplace) { - absl::StatusOr<Foo> status_or_foo(10); - status_or_foo.emplace(20); - EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20))); - status_or_foo = absl::InvalidArgumentError("msg"); - EXPECT_FALSE(status_or_foo.ok()); - EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument); - EXPECT_EQ(status_or_foo.status().message(), "msg"); - status_or_foo.emplace(20); - EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20))); -} - -TEST(StatusOr, EmplaceInitializerList) { - absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12}, - absl::make_unique<int>(13)); - status_or.emplace({1, 2, 3}, absl::make_unique<int>(4)); - EXPECT_THAT(status_or, - IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)), - Field(&InPlaceHelper::y, Pointee(4))))); - status_or = absl::InvalidArgumentError("msg"); - EXPECT_FALSE(status_or.ok()); - EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument); - EXPECT_EQ(status_or.status().message(), "msg"); - status_or.emplace({1, 2, 3}, absl::make_unique<int>(4)); - EXPECT_THAT(status_or, - IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)), - Field(&InPlaceHelper::y, Pointee(4))))); -} - -TEST(StatusOr, TestCopyCtorStatusOk) { - const int kI = 4; - const absl::StatusOr<int> original(kI); - const absl::StatusOr<int> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(*original, *copy); -} - -TEST(StatusOr, TestCopyCtorStatusNotOk) { - absl::StatusOr<int> original(absl::CancelledError()); - absl::StatusOr<int> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestCopyCtorNonAssignable) { - const int kI = 4; - CopyNoAssign value(kI); - absl::StatusOr<CopyNoAssign> original(value); - absl::StatusOr<CopyNoAssign> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(original->foo, copy->foo); -} - -TEST(StatusOr, TestCopyCtorStatusOKConverting) { - const int kI = 4; - absl::StatusOr<int> original(kI); - absl::StatusOr<double> copy(original); - EXPECT_OK(copy.status()); - EXPECT_DOUBLE_EQ(*original, *copy); -} - -TEST(StatusOr, TestCopyCtorStatusNotOkConverting) { - absl::StatusOr<int> original(absl::CancelledError()); - absl::StatusOr<double> copy(original); - EXPECT_EQ(copy.status(), original.status()); -} - -TEST(StatusOr, TestAssignmentStatusOk) { - // Copy assignmment - { - const auto p = std::make_shared<int>(17); - absl::StatusOr<std::shared_ptr<int>> source(p); - - absl::StatusOr<std::shared_ptr<int>> target; - target = source; - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(p, *source); - } - - // Move asssignment - { - const auto p = std::make_shared<int>(17); - absl::StatusOr<std::shared_ptr<int>> source(p); - - absl::StatusOr<std::shared_ptr<int>> target; - target = std::move(source); - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(nullptr, *source); - } -} - -TEST(StatusOr, TestAssignmentStatusNotOk) { - // Copy assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<int> target; - target = source; - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(expected, source.status()); - } - - // Move assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<int> target; - target = std::move(source); - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal); - } -} - -TEST(StatusOr, TestAssignmentStatusOKConverting) { - // Copy assignment - { - const int kI = 4; - absl::StatusOr<int> source(kI); - - absl::StatusOr<double> target; - target = source; - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_DOUBLE_EQ(kI, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_DOUBLE_EQ(kI, *source); - } - - // Move assignment - { - const auto p = new int(17); - absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p)); - - absl::StatusOr<std::shared_ptr<int>> target; - target = std::move(source); - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, target->get()); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(nullptr, source->get()); - } -} - -struct A { - int x; -}; - -struct ImplicitConstructibleFromA { - int x; - bool moved; - ImplicitConstructibleFromA(const A& a) // NOLINT - : x(a.x), moved(false) {} - ImplicitConstructibleFromA(A&& a) // NOLINT - : x(a.x), moved(true) {} -}; - -TEST(StatusOr, ImplicitConvertingConstructor) { - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>( - absl::StatusOr<A>(A{11})), - IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11), - Field(&ImplicitConstructibleFromA::moved, true)))); - absl::StatusOr<A> a(A{12}); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a), - IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12), - Field(&ImplicitConstructibleFromA::moved, false)))); -} - -struct ExplicitConstructibleFromA { - int x; - bool moved; - explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {} - explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {} -}; - -TEST(StatusOr, ExplicitConvertingConstructor) { - EXPECT_FALSE( - (std::is_convertible<const absl::StatusOr<A>&, - absl::StatusOr<ExplicitConstructibleFromA>>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::StatusOr<A>&&, - absl::StatusOr<ExplicitConstructibleFromA>>::value)); - EXPECT_THAT( - absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})), - IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11), - Field(&ExplicitConstructibleFromA::moved, true)))); - absl::StatusOr<A> a(A{12}); - EXPECT_THAT( - absl::StatusOr<ExplicitConstructibleFromA>(a), - IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12), - Field(&ExplicitConstructibleFromA::moved, false)))); -} - -struct ImplicitConstructibleFromBool { - ImplicitConstructibleFromBool(bool y) : x(y) {} // NOLINT - bool x = false; -}; - -struct ConvertibleToBool { - explicit ConvertibleToBool(bool y) : x(y) {} - operator bool() const { return x; } // NOLINT - bool x = false; -}; - -TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>( - absl::StatusOr<bool>(false)), - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_FALSE((std::is_convertible< - absl::StatusOr<ConvertibleToBool>, - absl::StatusOr<ImplicitConstructibleFromBool>>::value)); -} - -TEST(StatusOr, BooleanConstructionWithImplicitCasts) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<bool>(false)}, - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<bool>(absl::InvalidArgumentError(""))}, - Not(IsOk())); - - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})}, - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))}, - Not(IsOk())); -} - -TEST(StatusOr, ConstImplicitCast) { - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>( - absl::StatusOr<const bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>( - absl::StatusOr<const bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>( - absl::StatusOr<bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>( - absl::StatusOr<bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>( - absl::StatusOr<std::string>("foo")), - IsOkAndHolds("foo")); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>( - absl::StatusOr<const std::string>("foo")), - IsOkAndHolds("foo")); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>( - absl::StatusOr<std::shared_ptr<std::string>>( - std::make_shared<std::string>("foo"))), - IsOkAndHolds(Pointee(std::string("foo")))); -} - -TEST(StatusOr, ConstExplicitConstruction) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)), - IsOkAndHolds(false)); -} - -struct ExplicitConstructibleFromInt { - int x; - explicit ExplicitConstructibleFromInt(int y) : x(y) {} -}; - -TEST(StatusOr, ExplicitConstruction) { - EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10), - IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10))); -} - -TEST(StatusOr, ImplicitConstruction) { - // Check implicit casting works. - auto status_or = - absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10); - EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10))); -} - -TEST(StatusOr, ImplicitConstructionFromInitliazerList) { - // Note: dropping the explicit std::initializer_list<int> is not supported - // by absl::StatusOr or absl::optional. - auto status_or = - absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}}); - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, UniquePtrImplicitConstruction) { - auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>( - absl::make_unique<Derived>()); - EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr))); -} - -TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) { - absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10); - absl::StatusOr<absl::StatusOr<CopyDetector>> status_error = - absl::InvalidArgumentError("foo"); - EXPECT_THAT(status_or, - IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error; - EXPECT_THAT(a_err, Not(IsOk())); - - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or; - absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref; // NOLINT - EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error; - absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err; // NOLINT - EXPECT_THAT(b_err, Not(IsOk())); - - absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or); - EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error); - EXPECT_THAT(c_err, Not(IsOk())); -} - -TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) { - absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10); - absl::StatusOr<absl::StatusOr<CopyDetector>> status_error = - absl::InvalidArgumentError("foo"); - absl::StatusOr<absl::StatusOr<CopyDetector>> a; - a = status_or; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - a = status_error; - EXPECT_THAT(a, Not(IsOk())); - - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or; - a = cref; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error; - a = cref_err; - EXPECT_THAT(a, Not(IsOk())); - a = std::move(status_or); - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - a = std::move(status_error); - EXPECT_THAT(a, Not(IsOk())); -} - -struct Copyable { - Copyable() {} - Copyable(const Copyable&) {} - Copyable& operator=(const Copyable&) { return *this; } -}; - -struct MoveOnly { - MoveOnly() {} - MoveOnly(MoveOnly&&) {} - MoveOnly& operator=(MoveOnly&&) { return *this; } -}; - -struct NonMovable { - NonMovable() {} - NonMovable(const NonMovable&) = delete; - NonMovable(NonMovable&&) = delete; - NonMovable& operator=(const NonMovable&) = delete; - NonMovable& operator=(NonMovable&&) = delete; -}; - -TEST(StatusOr, CopyAndMoveAbility) { - EXPECT_TRUE(std::is_copy_constructible<Copyable>::value); - EXPECT_TRUE(std::is_copy_assignable<Copyable>::value); - EXPECT_TRUE(std::is_move_constructible<Copyable>::value); - EXPECT_TRUE(std::is_move_assignable<Copyable>::value); - EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value); - EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value); - EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value); - EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value); - EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value); - EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value); - EXPECT_FALSE(std::is_move_constructible<NonMovable>::value); - EXPECT_FALSE(std::is_move_assignable<NonMovable>::value); -} - -TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) { - absl::StatusOr<absl::any> status_or = CopyDetector(10); - absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo"); - EXPECT_THAT( - status_or, - IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::any> a = status_or; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - absl::StatusOr<absl::any> a_err = status_error; - EXPECT_THAT(a_err, Not(IsOk())); - - const absl::StatusOr<absl::any>& cref = status_or; - // No lint for no-change copy. - absl::StatusOr<absl::any> b = cref; // NOLINT - EXPECT_THAT( - b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::any>& cref_err = status_error; - // No lint for no-change copy. - absl::StatusOr<absl::any> b_err = cref_err; // NOLINT - EXPECT_THAT(b_err, Not(IsOk())); - - absl::StatusOr<absl::any> c = std::move(status_or); - EXPECT_THAT( - c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::any> c_err = std::move(status_error); - EXPECT_THAT(c_err, Not(IsOk())); -} - -TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) { - absl::StatusOr<absl::any> status_or = CopyDetector(10); - absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo"); - absl::StatusOr<absl::any> a; - a = status_or; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - a = status_error; - EXPECT_THAT(a, Not(IsOk())); - - const absl::StatusOr<absl::any>& cref = status_or; - a = cref; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::any>& cref_err = status_error; - a = cref_err; - EXPECT_THAT(a, Not(IsOk())); - a = std::move(status_or); - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - a = std::move(status_error); - EXPECT_THAT(a, Not(IsOk())); -} - -TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) { - absl::StatusOr<CopyDetector> status_or(10); - ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false))); - absl::StatusOr<CopyDetector> a(status_or); - EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true))); - const absl::StatusOr<CopyDetector>& cref = status_or; - absl::StatusOr<CopyDetector> b(cref); // NOLINT - EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true))); - absl::StatusOr<CopyDetector> c(std::move(status_or)); - EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false))); -} - -TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) { - absl::StatusOr<CopyDetector> status_or(10); - ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false))); - absl::StatusOr<CopyDetector> a; - a = status_or; - EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true))); - const absl::StatusOr<CopyDetector>& cref = status_or; - absl::StatusOr<CopyDetector> b; - b = cref; - EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true))); - absl::StatusOr<CopyDetector> c; - c = std::move(status_or); - EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false))); -} - -TEST(StatusOr, AbslAnyAssignment) { - EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>, - absl::StatusOr<int>>::value)); - absl::StatusOr<absl::any> status_or; - status_or = absl::InvalidArgumentError("foo"); - EXPECT_THAT(status_or, Not(IsOk())); -} - -TEST(StatusOr, ImplicitAssignment) { - absl::StatusOr<absl::variant<int, std::string>> status_or; - status_or = 10; - EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10))); -} - -TEST(StatusOr, SelfDirectInitAssignment) { - absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}}; - status_or = *status_or; - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, ImplicitCastFromInitializerList) { - absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}}; - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, UniquePtrImplicitAssignment) { - absl::StatusOr<std::unique_ptr<Base1>> status_or; - status_or = absl::make_unique<Derived>(); - EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr))); -} - -TEST(StatusOr, Pointer) { - struct A {}; - struct B : public A {}; - struct C : private A {}; - - EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value)); - EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value)); - EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value)); - EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value)); -} - -TEST(StatusOr, TestAssignmentStatusNotOkConverting) { - // Copy assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<double> target; - target = source; - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(expected, source.status()); - } - - // Move assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<double> target; - target = std::move(source); - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal); - } -} - -TEST(StatusOr, SelfAssignment) { - // Copy-assignment, status OK - { - // A string long enough that it's likely to defeat any inline representation - // optimization. - const std::string long_str(128, 'a'); - - absl::StatusOr<std::string> so = long_str; - so = *&so; - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(long_str, *so); - } - - // Copy-assignment, error status - { - absl::StatusOr<int> so = absl::NotFoundError("taco"); - so = *&so; - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } - - // Move-assignment with copyable type, status OK - { - absl::StatusOr<int> so = 17; - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(17, *so); - } - - // Move-assignment with copyable type, error status - { - absl::StatusOr<int> so = absl::NotFoundError("taco"); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } - - // Move-assignment with non-copyable type, status OK - { - const auto raw = new int(17); - absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(raw, so->get()); - } - - // Move-assignment with non-copyable type, error status - { - absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco"); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } -} - -// These types form the overload sets of the constructors and the assignment -// operators of `MockValue`. They distinguish construction from assignment, -// lvalue from rvalue. -struct FromConstructibleAssignableLvalue {}; -struct FromConstructibleAssignableRvalue {}; -struct FromImplicitConstructibleOnly {}; -struct FromAssignableOnly {}; - -// This class is for testing the forwarding value assignments of `StatusOr`. -// `from_rvalue` indicates whether the constructor or the assignment taking -// rvalue reference is called. `from_assignment` indicates whether any -// assignment is called. -struct MockValue { - // Constructs `MockValue` from `FromConstructibleAssignableLvalue`. - MockValue(const FromConstructibleAssignableLvalue&) // NOLINT - : from_rvalue(false), assigned(false) {} - // Constructs `MockValue` from `FromConstructibleAssignableRvalue`. - MockValue(FromConstructibleAssignableRvalue&&) // NOLINT - : from_rvalue(true), assigned(false) {} - // Constructs `MockValue` from `FromImplicitConstructibleOnly`. - // `MockValue` is not assignable from `FromImplicitConstructibleOnly`. - MockValue(const FromImplicitConstructibleOnly&) // NOLINT - : from_rvalue(false), assigned(false) {} - // Assigns `FromConstructibleAssignableLvalue`. - MockValue& operator=(const FromConstructibleAssignableLvalue&) { - from_rvalue = false; - assigned = true; - return *this; - } - // Assigns `FromConstructibleAssignableRvalue` (rvalue only). - MockValue& operator=(FromConstructibleAssignableRvalue&&) { - from_rvalue = true; - assigned = true; - return *this; - } - // Assigns `FromAssignableOnly`, but not constructible from - // `FromAssignableOnly`. - MockValue& operator=(const FromAssignableOnly&) { - from_rvalue = false; - assigned = true; - return *this; - } - bool from_rvalue; - bool assigned; -}; - -// operator=(U&&) -TEST(StatusOr, PerfectForwardingAssignment) { - // U == T - constexpr int kValue1 = 10, kValue2 = 20; - absl::StatusOr<CopyDetector> status_or; - CopyDetector lvalue(kValue1); - status_or = lvalue; - EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true))); - status_or = CopyDetector(kValue2); - EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false))); - - // U != T - EXPECT_TRUE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromConstructibleAssignableLvalue&>::value)); - EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&, - FromConstructibleAssignableLvalue&&>::value)); - EXPECT_FALSE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromConstructibleAssignableRvalue&>::value)); - EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&, - FromConstructibleAssignableRvalue&&>::value)); - EXPECT_TRUE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromImplicitConstructibleOnly&>::value)); - EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&, - const FromAssignableOnly&>::value)); - - absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{}); - EXPECT_FALSE(from_lvalue->from_rvalue); - EXPECT_FALSE(from_lvalue->assigned); - from_lvalue = FromConstructibleAssignableLvalue{}; - EXPECT_FALSE(from_lvalue->from_rvalue); - EXPECT_TRUE(from_lvalue->assigned); - - absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{}); - EXPECT_TRUE(from_rvalue->from_rvalue); - EXPECT_FALSE(from_rvalue->assigned); - from_rvalue = FromConstructibleAssignableRvalue{}; - EXPECT_TRUE(from_rvalue->from_rvalue); - EXPECT_TRUE(from_rvalue->assigned); - - absl::StatusOr<MockValue> from_implicit_constructible( - FromImplicitConstructibleOnly{}); - EXPECT_FALSE(from_implicit_constructible->from_rvalue); - EXPECT_FALSE(from_implicit_constructible->assigned); - // construct a temporary `StatusOr` object and invoke the `StatusOr` move - // assignment operator. - from_implicit_constructible = FromImplicitConstructibleOnly{}; - EXPECT_FALSE(from_implicit_constructible->from_rvalue); - EXPECT_FALSE(from_implicit_constructible->assigned); -} - -TEST(StatusOr, TestStatus) { - absl::StatusOr<int> good(4); - EXPECT_TRUE(good.ok()); - absl::StatusOr<int> bad(absl::CancelledError()); - EXPECT_FALSE(bad.ok()); - EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, OperatorStarRefQualifiers) { - static_assert( - std::is_same<const int&, - decltype(*std::declval<const absl::StatusOr<int>&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<const int&&, - decltype(*std::declval<const absl::StatusOr<int>&&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(), - "Unexpected ref-qualifiers"); -} - -TEST(StatusOr, OperatorStar) { - const absl::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ("hello", *const_lvalue); - - absl::StatusOr<std::string> lvalue("hello"); - EXPECT_EQ("hello", *lvalue); - - // Note: Recall that std::move() is equivalent to a static_cast to an rvalue - // reference type. - const absl::StatusOr<std::string> const_rvalue("hello"); - EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT - - absl::StatusOr<std::string> rvalue("hello"); - EXPECT_EQ("hello", *std::move(rvalue)); -} - -TEST(StatusOr, OperatorArrowQualifiers) { - static_assert( - std::is_same< - const int*, - decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - const int*, - decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); -} - -TEST(StatusOr, OperatorArrow) { - const absl::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ(std::string("hello"), const_lvalue->c_str()); - - absl::StatusOr<std::string> lvalue("hello"); - EXPECT_EQ(std::string("hello"), lvalue->c_str()); -} - -TEST(StatusOr, RValueStatus) { - absl::StatusOr<int> so(absl::NotFoundError("taco")); - const absl::Status s = std::move(so).status(); - - EXPECT_EQ(s.code(), absl::StatusCode::kNotFound); - EXPECT_EQ(s.message(), "taco"); - - // Check that !ok() still implies !status().ok(), even after moving out of the - // object. See the note on the rvalue ref-qualified status method. - EXPECT_FALSE(so.ok()); // NOLINT - EXPECT_FALSE(so.status().ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal); - EXPECT_EQ(so.status().message(), "Status accessed after move."); -} - -TEST(StatusOr, TestValue) { - const int kI = 4; - absl::StatusOr<int> thing(kI); - EXPECT_EQ(kI, *thing); -} - -TEST(StatusOr, TestValueConst) { - const int kI = 4; - const absl::StatusOr<int> thing(kI); - EXPECT_EQ(kI, *thing); -} - -TEST(StatusOr, TestPointerDefaultCtor) { - absl::StatusOr<int*> thing; - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown); -} - - - -TEST(StatusOr, TestPointerStatusCtor) { - absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerValueCtor) { - const int kI = 4; - - // Construction from a non-null pointer - { - absl::StatusOr<const int*> so(&kI); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(&kI, *so); - } - - // Construction from a null pointer constant - { - absl::StatusOr<const int*> so(nullptr); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(nullptr, *so); - } - - // Construction from a non-literal null pointer - { - const int* const p = nullptr; - - absl::StatusOr<const int*> so(p); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(nullptr, *so); - } -} - -TEST(StatusOr, TestPointerCopyCtorStatusOk) { - const int kI = 0; - absl::StatusOr<const int*> original(&kI); - absl::StatusOr<const int*> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(*original, *copy); -} - -TEST(StatusOr, TestPointerCopyCtorStatusNotOk) { - absl::StatusOr<int*> original(absl::CancelledError()); - absl::StatusOr<int*> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) { - Derived derived; - absl::StatusOr<Derived*> original(&derived); - absl::StatusOr<Base2*> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(static_cast<const Base2*>(*original), *copy); -} - -TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) { - absl::StatusOr<Derived*> original(absl::CancelledError()); - absl::StatusOr<Base2*> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerAssignmentStatusOk) { - const int kI = 0; - absl::StatusOr<const int*> source(&kI); - absl::StatusOr<const int*> target; - target = source; - EXPECT_OK(target.status()); - EXPECT_EQ(*source, *target); -} - -TEST(StatusOr, TestPointerAssignmentStatusNotOk) { - absl::StatusOr<int*> source(absl::CancelledError()); - absl::StatusOr<int*> target; - target = source; - EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerAssignmentStatusOKConverting) { - Derived derived; - absl::StatusOr<Derived*> source(&derived); - absl::StatusOr<Base2*> target; - target = source; - EXPECT_OK(target.status()); - EXPECT_EQ(static_cast<const Base2*>(*source), *target); -} - -TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) { - absl::StatusOr<Derived*> source(absl::CancelledError()); - absl::StatusOr<Base2*> target; - target = source; - EXPECT_EQ(target.status(), source.status()); -} - -TEST(StatusOr, TestPointerStatus) { - const int kI = 0; - absl::StatusOr<const int*> good(&kI); - EXPECT_TRUE(good.ok()); - absl::StatusOr<const int*> bad(absl::CancelledError()); - EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerValue) { - const int kI = 0; - absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOr, TestPointerValueConst) { - const int kI = 0; - const absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) { - using EvilType = std::vector<std::unique_ptr<int>>; - static_assert(std::is_copy_constructible<EvilType>::value, ""); - std::vector<::absl::StatusOr<EvilType>> v(5); - v.reserve(v.capacity() + 10); - v.resize(v.capacity() + 10); -} - -TEST(StatusOr, ConstPayload) { - // A reduced version of a problematic type found in the wild. All of the - // operations below should compile. - absl::StatusOr<const int> a; - - // Copy-construction - absl::StatusOr<const int> b(a); - - // Copy-assignment - EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value); - - // Move-construction - absl::StatusOr<const int> c(std::move(a)); - - // Move-assignment - EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value); -} - -TEST(StatusOr, MapToStatusOrUniquePtr) { - // A reduced version of a problematic type found in the wild. All of the - // operations below should compile. - using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>; - - MapType a; - - // Move-construction - MapType b(std::move(a)); - - // Move-assignment - a = std::move(b); -} - -TEST(StatusOr, ValueOrOk) { - const absl::StatusOr<int> status_or = 0; - EXPECT_EQ(status_or.value_or(-1), 0); -} - -TEST(StatusOr, ValueOrDefault) { - const absl::StatusOr<int> status_or = absl::CancelledError(); - EXPECT_EQ(status_or.value_or(-1), -1); -} - -TEST(StatusOr, MoveOnlyValueOrOk) { - EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0)) - .value_or(absl::make_unique<int>(-1)), - Pointee(0)); -} - -TEST(StatusOr, MoveOnlyValueOrDefault) { - EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError()) - .value_or(absl::make_unique<int>(-1)), - Pointee(-1)); -} - -static absl::StatusOr<int> MakeStatus() { return 100; } - -TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); } - -TEST(StatusOr, EqualityOperator) { - constexpr int kNumCases = 4; - std::array<absl::StatusOr<int>, kNumCases> group1 = { - absl::StatusOr<int>(1), absl::StatusOr<int>(2), - absl::StatusOr<int>(absl::InvalidArgumentError("msg")), - absl::StatusOr<int>(absl::InternalError("msg"))}; - std::array<absl::StatusOr<int>, kNumCases> group2 = { - absl::StatusOr<int>(1), absl::StatusOr<int>(2), - absl::StatusOr<int>(absl::InvalidArgumentError("msg")), - absl::StatusOr<int>(absl::InternalError("msg"))}; - for (int i = 0; i < kNumCases; ++i) { - for (int j = 0; j < kNumCases; ++j) { - if (i == j) { - EXPECT_TRUE(group1[i] == group2[j]); - EXPECT_FALSE(group1[i] != group2[j]); - } else { - EXPECT_FALSE(group1[i] == group2[j]); - EXPECT_TRUE(group1[i] != group2[j]); - } - } - } -} - -struct MyType { - bool operator==(const MyType&) const { return true; } -}; - -enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 }; - -// This class has conversion operator to `StatusOr<T>` based on value of -// `conv_traits`. -template <typename T, ConvTraits conv_traits = ConvTraits::kNone> -struct StatusOrConversionBase {}; - -template <typename T> -struct StatusOrConversionBase<T, ConvTraits::kImplicit> { - operator absl::StatusOr<T>() const& { // NOLINT - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } - operator absl::StatusOr<T>() && { // NOLINT - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } -}; - -template <typename T> -struct StatusOrConversionBase<T, ConvTraits::kExplicit> { - explicit operator absl::StatusOr<T>() const& { - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } - explicit operator absl::StatusOr<T>() && { - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } -}; - -// This class has conversion operator to `T` based on the value of -// `conv_traits`. -template <typename T, ConvTraits conv_traits = ConvTraits::kNone> -struct ConversionBase {}; - -template <typename T> -struct ConversionBase<T, ConvTraits::kImplicit> { - operator T() const& { return t; } // NOLINT - operator T() && { return std::move(t); } // NOLINT - T t; -}; - -template <typename T> -struct ConversionBase<T, ConvTraits::kExplicit> { - explicit operator T() const& { return t; } - explicit operator T() && { return std::move(t); } - T t; -}; - -// This class has conversion operator to `absl::Status` based on the value of -// `conv_traits`. -template <ConvTraits conv_traits = ConvTraits::kNone> -struct StatusConversionBase {}; - -template <> -struct StatusConversionBase<ConvTraits::kImplicit> { - operator absl::Status() const& { // NOLINT - return absl::InternalError("conversion to Status"); - } - operator absl::Status() && { // NOLINT - return absl::InternalError("conversion to Status"); - } -}; - -template <> -struct StatusConversionBase<ConvTraits::kExplicit> { - explicit operator absl::Status() const& { // NOLINT - return absl::InternalError("conversion to Status"); - } - explicit operator absl::Status() && { // NOLINT - return absl::InternalError("conversion to Status"); - } -}; - -static constexpr int kConvToStatus = 1; -static constexpr int kConvToStatusOr = 2; -static constexpr int kConvToT = 4; -static constexpr int kConvExplicit = 8; - -constexpr ConvTraits GetConvTraits(int bit, int config) { - return (config & bit) == 0 - ? ConvTraits::kNone - : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit - : ConvTraits::kExplicit); -} - -// This class conditionally has conversion operator to `absl::Status`, `T`, -// `StatusOr<T>`, based on values of the template parameters. -template <typename T, int config> -struct CustomType - : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>, - ConversionBase<T, GetConvTraits(kConvToT, config)>, - StatusConversionBase<GetConvTraits(kConvToStatus, config)> {}; - -struct ConvertibleToAnyStatusOr { - template <typename T> - operator absl::StatusOr<T>() const { // NOLINT - return absl::InvalidArgumentError("Conversion to absl::StatusOr"); - } -}; - -// Test the rank of overload resolution for `StatusOr<T>` constructor and -// assignment, from highest to lowest: -// 1. T/Status -// 2. U that has conversion operator to absl::StatusOr<T> -// 3. U that is convertible to Status -// 4. U that is convertible to T -TEST(StatusOr, ConstructionFromT) { - // Construct absl::StatusOr<T> from T when T is convertible to - // absl::StatusOr<T> - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v); - EXPECT_TRUE(statusor.ok()); - } - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v; - EXPECT_TRUE(statusor.ok()); - } - // Construct absl::StatusOr<T> from T when T is explicitly convertible to - // Status - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor( - v); - EXPECT_TRUE(statusor.ok()); - } - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor = - v; - EXPECT_TRUE(statusor.ok()); - } -} - -// Construct absl::StatusOr<T> from U when U is explicitly convertible to T -TEST(StatusOr, ConstructionFromTypeConvertibleToT) { - { - CustomType<MyType, kConvToT | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_TRUE(statusor.ok()); - } - { - CustomType<MyType, kConvToT> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -// Construct absl::StatusOr<T> from U when U has explicit conversion operator to -// absl::StatusOr<T> -TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) { - { - CustomType<MyType, kConvToStatusOr | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, - kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit> - v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } -} - -TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) { - // Construction fails because conversion to `Status` is explicit. - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } -} - -TEST(StatusOr, AssignmentFromT) { - // Assign to absl::StatusOr<T> from T when T is convertible to - // absl::StatusOr<T> - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } - // Assign to absl::StatusOr<T> from T when T is convertible to Status - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -TEST(StatusOr, AssignmentFromTypeConvertibleToT) { - // Assign to absl::StatusOr<T> from U when U is convertible to T - { - CustomType<MyType, kConvToT> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) { - // Assign to absl::StatusOr<T> from U when U has conversion operator to - // absl::StatusOr<T> - { - CustomType<MyType, kConvToStatusOr> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } -} - -TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) { - // Assign to absl::StatusOr<T> from U when U is convertible to Status - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/BUILD.bazel b/third_party/abseil_cpp/absl/strings/BUILD.bazel deleted file mode 100644 index 30a8dd28b2d1..000000000000 --- a/third_party/abseil_cpp/absl/strings/BUILD.bazel +++ /dev/null @@ -1,788 +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. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_TEST_COPTS", -) - -package( - default_visibility = ["//visibility:public"], - features = ["parse_headers"], -) - -licenses(["notice"]) - -cc_library( - name = "strings", - srcs = [ - "ascii.cc", - "charconv.cc", - "escaping.cc", - "internal/charconv_bigint.cc", - "internal/charconv_bigint.h", - "internal/charconv_parse.cc", - "internal/charconv_parse.h", - "internal/memutil.cc", - "internal/memutil.h", - "internal/stl_type_traits.h", - "internal/str_join_internal.h", - "internal/str_split_internal.h", - "match.cc", - "numbers.cc", - "str_cat.cc", - "str_replace.cc", - "str_split.cc", - "string_view.cc", - "substitute.cc", - ], - hdrs = [ - "ascii.h", - "charconv.h", - "escaping.h", - "internal/string_constant.h", - "match.h", - "numbers.h", - "str_cat.h", - "str_join.h", - "str_replace.h", - "str_split.h", - "string_view.h", - "strip.h", - "substitute.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":internal", - "//absl/base", - "//absl/base:bits", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/base:raw_logging_internal", - "//absl/base:throw_delegate", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/numeric:int128", - ], -) - -cc_library( - name = "internal", - srcs = [ - "internal/escaping.cc", - "internal/ostringstream.cc", - "internal/utf8.cc", - ], - hdrs = [ - "internal/char_map.h", - "internal/escaping.h", - "internal/ostringstream.h", - "internal/resize_uninitialized.h", - "internal/utf8.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/base:raw_logging_internal", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "match_test", - size = "small", - srcs = ["match_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "escaping_test", - size = "small", - srcs = [ - "escaping_test.cc", - "internal/escaping_test_common.h", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":cord", - ":strings", - "//absl/base:core_headers", - "//absl/container:fixed_array", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "escaping_benchmark", - srcs = [ - "escaping_benchmark.cc", - "internal/escaping_test_common.h", - ], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:raw_logging_internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "ascii_test", - size = "small", - srcs = ["ascii_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "ascii_benchmark", - srcs = ["ascii_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "memutil_benchmark", - srcs = [ - "internal/memutil.h", - "internal/memutil_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "memutil_test", - size = "small", - srcs = [ - "internal/memutil.h", - "internal/memutil_test.cc", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "utf8_test", - size = "small", - srcs = [ - "internal/utf8_test.cc", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":internal", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -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, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "string_view_test", - size = "small", - srcs = ["string_view_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "cord_internal", - hdrs = ["internal/cord_internal.h"], - copts = ABSL_DEFAULT_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:base_internal", - "//absl/container:compressed_tuple", - "//absl/meta:type_traits", - ], -) - -cc_library( - name = "cord", - srcs = [ - "cord.cc", - ], - hdrs = [ - "cord.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":cord_internal", - ":internal", - ":str_format", - ":strings", - "//absl/base", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/base:raw_logging_internal", - "//absl/container:fixed_array", - "//absl/container:inlined_vector", - "//absl/functional:function_ref", - "//absl/meta:type_traits", - "//absl/types:optional", - ], -) - -cc_library( - name = "cord_test_helpers", - testonly = 1, - hdrs = [ - "cord_test_helpers.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":cord", - ], -) - -cc_test( - name = "cord_test", - size = "medium", - srcs = ["cord_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":cord", - ":cord_test_helpers", - ":str_format", - ":strings", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:endian", - "//absl/base:raw_logging_internal", - "//absl/container:fixed_array", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "substitute_test", - size = "small", - srcs = ["substitute_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_replace_benchmark", - srcs = ["str_replace_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:raw_logging_internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "str_replace_test", - size = "small", - srcs = ["str_replace_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_split_test", - srcs = ["str_split_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "//absl/container:flat_hash_map", - "//absl/container:node_hash_map", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_split_benchmark", - srcs = ["str_split_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:raw_logging_internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "ostringstream_test", - size = "small", - srcs = ["internal/ostringstream_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "ostringstream_benchmark", - srcs = ["internal/ostringstream_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "resize_uninitialized_test", - size = "small", - srcs = [ - "internal/resize_uninitialized.h", - "internal/resize_uninitialized_test.cc", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:core_headers", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_join_test", - size = "small", - srcs = ["str_join_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_join_benchmark", - srcs = ["str_join_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "str_cat_test", - size = "small", - srcs = ["str_cat_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_cat_benchmark", - srcs = ["str_cat_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "numbers_test", - size = "medium", - srcs = [ - "internal/numbers_test_common.h", - "numbers_test.cc", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":internal", - ":pow10_helper", - ":strings", - "//absl/base:config", - "//absl/base:raw_logging_internal", - "//absl/random", - "//absl/random:distributions", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "numbers_benchmark", - srcs = ["numbers_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:raw_logging_internal", - "//absl/random", - "//absl/random:distributions", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "strip_test", - size = "small", - srcs = ["strip_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "char_map_test", - srcs = ["internal/char_map_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "char_map_benchmark", - srcs = ["internal/char_map_benchmark.cc"], - copts = ABSL_TEST_COPTS, - tags = ["benchmark"], - deps = [ - ":internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "charconv_test", - srcs = ["charconv_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":pow10_helper", - ":str_format", - ":strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "charconv_parse_test", - srcs = [ - "internal/charconv_parse.h", - "internal/charconv_parse_test.cc", - ], - copts = ABSL_TEST_COPTS, - deps = [ - ":strings", - "//absl/base:config", - "//absl/base:raw_logging_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "charconv_bigint_test", - srcs = [ - "internal/charconv_bigint.h", - "internal/charconv_bigint_test.cc", - "internal/charconv_parse.h", - ], - copts = ABSL_TEST_COPTS, - deps = [ - ":strings", - "//absl/base:config", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "charconv_benchmark", - srcs = [ - "charconv_benchmark.cc", - ], - tags = [ - "benchmark", - ], - deps = [ - ":strings", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "str_format", - hdrs = [ - "str_format.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":str_format_internal", - ], -) - -cc_library( - name = "str_format_internal", - srcs = [ - "internal/str_format/arg.cc", - "internal/str_format/bind.cc", - "internal/str_format/extension.cc", - "internal/str_format/float_conversion.cc", - "internal/str_format/output.cc", - "internal/str_format/parser.cc", - ], - hdrs = [ - "internal/str_format/arg.h", - "internal/str_format/bind.h", - "internal/str_format/checker.h", - "internal/str_format/extension.h", - "internal/str_format/float_conversion.h", - "internal/str_format/output.h", - "internal/str_format/parser.h", - ], - copts = ABSL_DEFAULT_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":strings", - "//absl/base:bits", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/functional:function_ref", - "//absl/meta:type_traits", - "//absl/numeric:int128", - "//absl/types:optional", - "//absl/types:span", - ], -) - -cc_test( - name = "str_format_test", - srcs = ["str_format_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":cord", - ":str_format", - ":strings", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_extension_test", - srcs = [ - "internal/str_format/extension_test.cc", - ], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format", - ":str_format_internal", - ":strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_arg_test", - srcs = ["internal/str_format/arg_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format", - ":str_format_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_bind_test", - srcs = ["internal/str_format/bind_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_checker_test", - srcs = ["internal/str_format/checker_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_convert_test", - size = "medium", - srcs = ["internal/str_format/convert_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format_internal", - ":strings", - "//absl/base:raw_logging_internal", - "//absl/types:optional", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_output_test", - srcs = ["internal/str_format/output_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":cord", - ":str_format_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "str_format_parser_test", - srcs = ["internal/str_format/parser_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":str_format_internal", - "//absl/base:core_headers", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "pow10_helper", - testonly = True, - srcs = ["internal/pow10_helper.cc"], - hdrs = ["internal/pow10_helper.h"], - visibility = ["//visibility:private"], - deps = ["//absl/base:config"], -) - -cc_test( - name = "pow10_helper_test", - srcs = ["internal/pow10_helper_test.cc"], - copts = ABSL_TEST_COPTS, - visibility = ["//visibility:private"], - deps = [ - ":pow10_helper", - ":str_format", - "@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 deleted file mode 100644 index 2b994a71c07e..000000000000 --- a/third_party/abseil_cpp/absl/strings/CMakeLists.txt +++ /dev/null @@ -1,609 +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. -# - -absl_cc_library( - NAME - strings - HDRS - "ascii.h" - "charconv.h" - "escaping.h" - "internal/string_constant.h" - "match.h" - "numbers.h" - "str_cat.h" - "str_join.h" - "str_replace.h" - "str_split.h" - "string_view.h" - "strip.h" - "substitute.h" - SRCS - "ascii.cc" - "charconv.cc" - "escaping.cc" - "internal/charconv_bigint.cc" - "internal/charconv_bigint.h" - "internal/charconv_parse.cc" - "internal/charconv_parse.h" - "internal/memutil.cc" - "internal/memutil.h" - "internal/stl_type_traits.h" - "internal/str_join_internal.h" - "internal/str_split_internal.h" - "match.cc" - "numbers.cc" - "str_cat.cc" - "str_replace.cc" - "str_split.cc" - "string_view.cc" - "substitute.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::strings_internal - absl::base - absl::bits - absl::config - absl::core_headers - absl::endian - absl::int128 - absl::memory - absl::raw_logging_internal - absl::throw_delegate - absl::type_traits - PUBLIC -) - -absl_cc_library( - NAME - strings_internal - HDRS - "internal/char_map.h" - "internal/escaping.cc" - "internal/escaping.h" - "internal/ostringstream.h" - "internal/resize_uninitialized.h" - "internal/utf8.h" - SRCS - "internal/ostringstream.cc" - "internal/utf8.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::core_headers - absl::endian - absl::raw_logging_internal - absl::type_traits -) - -absl_cc_test( - NAME - match_test - SRCS - "match_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::base - gmock_main -) - -absl_cc_test( - NAME - escaping_test - SRCS - "escaping_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - absl::fixed_array - gmock_main -) - -absl_cc_test( - NAME - ascii_test - SRCS - "ascii_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - memutil_test - SRCS - "internal/memutil.h" - "internal/memutil_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - utf8_test - SRCS - "internal/utf8_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings_internal - absl::base - absl::core_headers - 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 - gmock_main -) - -absl_cc_test( - NAME - string_view_test - SRCS - "string_view_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::config - absl::core_headers - absl::dynamic_annotations - gmock_main -) - -absl_cc_test( - NAME - substitute_test - SRCS - "substitute_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - str_replace_test - SRCS - "str_replace_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - gmock_main -) - -absl_cc_test( - NAME - str_split_test - SRCS - "str_split_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::base - absl::core_headers - absl::dynamic_annotations - absl::flat_hash_map - absl::node_hash_map - gmock_main -) - -absl_cc_test( - NAME - ostringstream_test - SRCS - "internal/ostringstream_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings_internal - gmock_main -) - -absl_cc_test( - NAME - resize_uninitialized_test - SRCS - "internal/resize_uninitialized.h" - "internal/resize_uninitialized_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::core_headers - absl::type_traits - gmock_main -) - -absl_cc_test( - NAME - str_join_test - SRCS - "str_join_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::base - absl::core_headers - absl::memory - gmock_main -) - -absl_cc_test( - NAME - str_cat_test - SRCS - "str_cat_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - numbers_test - SRCS - "internal/numbers_test_common.h" - "numbers_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::core_headers - absl::pow10_helper - absl::config - absl::raw_logging_internal - absl::random_random - absl::random_distributions - absl::strings_internal - gmock_main -) - -absl_cc_test( - NAME - strip_test - SRCS - "strip_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::base - gmock_main -) - -absl_cc_test( - NAME - char_map_test - SRCS - "internal/char_map_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings_internal - gmock_main -) - -absl_cc_test( - NAME - charconv_test - SRCS - "charconv_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::str_format - absl::pow10_helper - gmock_main -) - -absl_cc_test( - NAME - charconv_parse_test - SRCS - "internal/charconv_parse.h" - "internal/charconv_parse_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::config - absl::raw_logging_internal - gmock_main -) - -absl_cc_test( - NAME - charconv_bigint_test - SRCS - "internal/charconv_bigint.h" - "internal/charconv_bigint_test.cc" - "internal/charconv_parse.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::config - gmock_main -) - -absl_cc_library( - NAME - str_format - HDRS - "str_format.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::str_format_internal - PUBLIC -) - -absl_cc_library( - NAME - str_format_internal - HDRS - "internal/str_format/arg.h" - "internal/str_format/bind.h" - "internal/str_format/checker.h" - "internal/str_format/extension.h" - "internal/str_format/float_conversion.h" - "internal/str_format/output.h" - "internal/str_format/parser.h" - SRCS - "internal/str_format/arg.cc" - "internal/str_format/bind.cc" - "internal/str_format/extension.cc" - "internal/str_format/float_conversion.cc" - "internal/str_format/output.cc" - "internal/str_format/parser.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bits - absl::strings - absl::config - absl::core_headers - absl::type_traits - absl::int128 - absl::span -) - -absl_cc_test( - NAME - str_format_test - SRCS - "str_format_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format - absl::cord - absl::strings - absl::core_headers - gmock_main -) - -absl_cc_test( - NAME - str_format_extension_test - SRCS - "internal/str_format/extension_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format - absl::str_format_internal - absl::strings - gmock_main -) - -absl_cc_test( - NAME - str_format_arg_test - SRCS - "internal/str_format/arg_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format - absl::str_format_internal - gmock_main -) - -absl_cc_test( - NAME - str_format_bind_test - SRCS - "internal/str_format/bind_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format_internal - gmock_main -) - -absl_cc_test( - NAME - str_format_checker_test - SRCS - "internal/str_format/checker_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format - gmock_main -) - -absl_cc_test( - NAME - str_format_convert_test - SRCS - "internal/str_format/convert_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::strings - absl::str_format_internal - absl::raw_logging_internal - absl::int128 - gmock_main -) - -absl_cc_test( - NAME - str_format_output_test - SRCS - "internal/str_format/output_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format_internal - absl::cord - gmock_main -) - -absl_cc_test( - NAME - str_format_parser_test - SRCS - "internal/str_format/parser_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::str_format_internal - absl::core_headers - gmock_main -) - -absl_cc_library( - NAME - pow10_helper - HDRS - "internal/pow10_helper.h" - SRCS - "internal/pow10_helper.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::config - TESTONLY -) - -absl_cc_test( - NAME - pow10_helper_test - SRCS - "internal/pow10_helper_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::pow10_helper - absl::str_format - gmock_main -) - -absl_cc_library( - NAME - cord - HDRS - "cord.h" - SRCS - "cord.cc" - "internal/cord_internal.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::base_internal - absl::compressed_tuple - absl::core_headers - absl::endian - absl::fixed_array - absl::function_ref - absl::inlined_vector - absl::optional - absl::raw_logging_internal - absl::strings - absl::strings_internal - absl::type_traits - PUBLIC -) - -absl_cc_library( - NAME - cord_test_helpers - HDRS - "cord_test_helpers.h" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::cord - TESTONLY -) - -absl_cc_test( - NAME - cord_test - SRCS - "cord_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::cord - absl::str_format - absl::strings - absl::base - absl::config - absl::core_headers - absl::endian - absl::raw_logging_internal - absl::fixed_array - gmock_main -) diff --git a/third_party/abseil_cpp/absl/strings/ascii.cc b/third_party/abseil_cpp/absl/strings/ascii.cc deleted file mode 100644 index 93bb03e95815..000000000000 --- a/third_party/abseil_cpp/absl/strings/ascii.cc +++ /dev/null @@ -1,200 +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/strings/ascii.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace ascii_internal { - -// # Table generated by this Python code (bit 0x02 is currently unused): -// TODO(mbar) Move Python code for generation of table to BUILD and link here. - -// NOTE: The kAsciiPropertyBits table used within this code was generated by -// Python code of the following form. (Bit 0x02 is currently unused and -// available.) -// -// def Hex2(n): -// return '0x' + hex(n/16)[2:] + hex(n%16)[2:] -// def IsPunct(ch): -// return (ord(ch) >= 32 and ord(ch) < 127 and -// not ch.isspace() and not ch.isalnum()) -// def IsBlank(ch): -// return ch in ' \t' -// def IsCntrl(ch): -// return ord(ch) < 32 or ord(ch) == 127 -// def IsXDigit(ch): -// return ch.isdigit() or ch.lower() in 'abcdef' -// for i in range(128): -// ch = chr(i) -// mask = ((ch.isalpha() and 0x01 or 0) | -// (ch.isalnum() and 0x04 or 0) | -// (ch.isspace() and 0x08 or 0) | -// (IsPunct(ch) and 0x10 or 0) | -// (IsBlank(ch) and 0x20 or 0) | -// (IsCntrl(ch) and 0x40 or 0) | -// (IsXDigit(ch) and 0x80 or 0)) -// print Hex2(mask) + ',', -// if i % 16 == 7: -// print ' //', Hex2(i & 0x78) -// elif i % 16 == 15: -// print - -// clang-format off -// Array of bitfields holding character information. Each bit value corresponds -// to a particular character feature. For readability, and because the value -// of these bits is tightly coupled to this implementation, the individual bits -// are not named. Note that bitfields for all characters above ASCII 127 are -// zero-initialized. -ABSL_DLL const unsigned char kPropertyBits[256] = { - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00 - 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10 - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20 - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30 - 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40 - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50 - 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60 - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70 - 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40, -}; - -// Array of characters for the ascii_tolower() function. For values 'A' -// through 'Z', return the lower-case character; otherwise, return the -// identity of the passed character. -ABSL_DLL const char kToLower[256] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', - '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', - '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', - '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', - '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', - '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', - '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', - '\x40', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', - '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', - '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', - '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', - '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', - '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', - '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', - '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf', - '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7', - '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf', - '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', - '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', - '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', - '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', - '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', - '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', - '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', - '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff', -}; - -// Array of characters for the ascii_toupper() function. For values 'a' -// through 'z', return the upper-case character; otherwise, return the -// identity of the passed character. -ABSL_DLL const char kToUpper[256] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', - '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', - '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', - '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', - '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', - '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', - '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', - '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', - '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', - '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', - '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', - '\x60', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', - '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', - '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', - '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf', - '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7', - '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf', - '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', - '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', - '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', - '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', - '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', - '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', - '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', - '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff', -}; -// clang-format on - -} // namespace ascii_internal - -void AsciiStrToLower(std::string* s) { - for (auto& ch : *s) { - ch = absl::ascii_tolower(ch); - } -} - -void AsciiStrToUpper(std::string* s) { - for (auto& ch : *s) { - ch = absl::ascii_toupper(ch); - } -} - -void RemoveExtraAsciiWhitespace(std::string* str) { - auto stripped = StripAsciiWhitespace(*str); - - if (stripped.empty()) { - str->clear(); - return; - } - - auto input_it = stripped.begin(); - auto input_end = stripped.end(); - auto output_it = &(*str)[0]; - bool is_ws = false; - - for (; input_it < input_end; ++input_it) { - if (is_ws) { - // Consecutive whitespace? Keep only the last. - is_ws = absl::ascii_isspace(*input_it); - if (is_ws) --output_it; - } else { - is_ws = absl::ascii_isspace(*input_it); - } - - *output_it = *input_it; - ++output_it; - } - - str->erase(output_it - &(*str)[0]); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/ascii.h b/third_party/abseil_cpp/absl/strings/ascii.h deleted file mode 100644 index b46bc71f35b9..000000000000 --- a/third_party/abseil_cpp/absl/strings/ascii.h +++ /dev/null @@ -1,242 +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. -// -// ----------------------------------------------------------------------------- -// File: ascii.h -// ----------------------------------------------------------------------------- -// -// This package contains functions operating on characters and strings -// restricted to standard ASCII. These include character classification -// functions analogous to those found in the ANSI C Standard Library <ctype.h> -// header file. -// -// C++ implementations provide <ctype.h> functionality based on their -// C environment locale. In general, reliance on such a locale is not ideal, as -// the locale standard is problematic (and may not return invariant information -// for the same character set, for example). These `ascii_*()` functions are -// hard-wired for standard ASCII, much faster, and guaranteed to behave -// consistently. They will never be overloaded, nor will their function -// signature change. -// -// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`, -// `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`, -// `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`, -// `ascii_isxdigit()` -// Analogous to the <ctype.h> functions with similar names, these -// functions take an unsigned char and return a bool, based on whether the -// character matches the condition specified. -// -// If the input character has a numerical value greater than 127, these -// functions return `false`. -// -// `ascii_tolower()`, `ascii_toupper()` -// Analogous to the <ctype.h> functions with similar names, these functions -// take an unsigned char and return a char. -// -// If the input character is not an ASCII {lower,upper}-case letter (including -// numerical values greater than 127) then the functions return the same value -// as the input character. - -#ifndef ABSL_STRINGS_ASCII_H_ -#define ABSL_STRINGS_ASCII_H_ - -#include <algorithm> -#include <string> - -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace ascii_internal { - -// Declaration for an array of bitfields holding character information. -ABSL_DLL extern const unsigned char kPropertyBits[256]; - -// Declaration for the array of characters to upper-case characters. -ABSL_DLL extern const char kToUpper[256]; - -// Declaration for the array of characters to lower-case characters. -ABSL_DLL extern const char kToLower[256]; - -} // namespace ascii_internal - -// ascii_isalpha() -// -// Determines whether the given character is an alphabetic character. -inline bool ascii_isalpha(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x01) != 0; -} - -// ascii_isalnum() -// -// Determines whether the given character is an alphanumeric character. -inline bool ascii_isalnum(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x04) != 0; -} - -// ascii_isspace() -// -// Determines whether the given character is a whitespace character (space, -// tab, vertical tab, formfeed, linefeed, or carriage return). -inline bool ascii_isspace(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x08) != 0; -} - -// ascii_ispunct() -// -// Determines whether the given character is a punctuation character. -inline bool ascii_ispunct(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x10) != 0; -} - -// ascii_isblank() -// -// Determines whether the given character is a blank character (tab or space). -inline bool ascii_isblank(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x20) != 0; -} - -// ascii_iscntrl() -// -// Determines whether the given character is a control character. -inline bool ascii_iscntrl(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x40) != 0; -} - -// ascii_isxdigit() -// -// Determines whether the given character can be represented as a hexadecimal -// digit character (i.e. {0-9} or {A-F}). -inline bool ascii_isxdigit(unsigned char c) { - return (ascii_internal::kPropertyBits[c] & 0x80) != 0; -} - -// ascii_isdigit() -// -// Determines whether the given character can be represented as a decimal -// digit character (i.e. {0-9}). -inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; } - -// ascii_isprint() -// -// Determines whether the given character is printable, including whitespace. -inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; } - -// ascii_isgraph() -// -// Determines whether the given character has a graphical representation. -inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; } - -// ascii_isupper() -// -// Determines whether the given character is uppercase. -inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; } - -// ascii_islower() -// -// Determines whether the given character is lowercase. -inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; } - -// ascii_isascii() -// -// Determines whether the given character is ASCII. -inline bool ascii_isascii(unsigned char c) { return c < 128; } - -// ascii_tolower() -// -// Returns an ASCII character, converting to lowercase if uppercase is -// passed. Note that character values > 127 are simply returned. -inline char ascii_tolower(unsigned char c) { - return ascii_internal::kToLower[c]; -} - -// Converts the characters in `s` to lowercase, changing the contents of `s`. -void AsciiStrToLower(std::string* s); - -// Creates a lowercase string from a given absl::string_view. -ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) { - std::string result(s); - absl::AsciiStrToLower(&result); - return result; -} - -// ascii_toupper() -// -// Returns the ASCII character, converting to upper-case if lower-case is -// passed. Note that characters values > 127 are simply returned. -inline char ascii_toupper(unsigned char c) { - return ascii_internal::kToUpper[c]; -} - -// Converts the characters in `s` to uppercase, changing the contents of `s`. -void AsciiStrToUpper(std::string* s); - -// Creates an uppercase string from a given absl::string_view. -ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) { - std::string result(s); - absl::AsciiStrToUpper(&result); - return result; -} - -// Returns absl::string_view with whitespace stripped from the beginning of the -// given string_view. -ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace( - absl::string_view str) { - auto it = std::find_if_not(str.begin(), str.end(), absl::ascii_isspace); - return str.substr(it - str.begin()); -} - -// Strips in place whitespace from the beginning of the given string. -inline void StripLeadingAsciiWhitespace(std::string* str) { - auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace); - str->erase(str->begin(), it); -} - -// Returns absl::string_view with whitespace stripped from the end of the given -// string_view. -ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace( - absl::string_view str) { - auto it = std::find_if_not(str.rbegin(), str.rend(), absl::ascii_isspace); - return str.substr(0, str.rend() - it); -} - -// Strips in place whitespace from the end of the given string -inline void StripTrailingAsciiWhitespace(std::string* str) { - auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace); - str->erase(str->rend() - it); -} - -// Returns absl::string_view with whitespace stripped from both ends of the -// given string_view. -ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace( - absl::string_view str) { - return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str)); -} - -// Strips in place whitespace from both ends of the given string -inline void StripAsciiWhitespace(std::string* str) { - StripTrailingAsciiWhitespace(str); - StripLeadingAsciiWhitespace(str); -} - -// Removes leading, trailing, and consecutive internal whitespace. -void RemoveExtraAsciiWhitespace(std::string*); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_ASCII_H_ diff --git a/third_party/abseil_cpp/absl/strings/ascii_benchmark.cc b/third_party/abseil_cpp/absl/strings/ascii_benchmark.cc deleted file mode 100644 index aca458c8042f..000000000000 --- a/third_party/abseil_cpp/absl/strings/ascii_benchmark.cc +++ /dev/null @@ -1,120 +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/strings/ascii.h" - -#include <cctype> -#include <string> -#include <array> -#include <random> - -#include "benchmark/benchmark.h" - -namespace { - -std::array<unsigned char, 256> MakeShuffledBytes() { - std::array<unsigned char, 256> bytes; - for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i); - std::random_device rd; - std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); - std::mt19937 g(seed); - std::shuffle(bytes.begin(), bytes.end(), g); - return bytes; -} - -template <typename Function> -void AsciiBenchmark(benchmark::State& state, Function f) { - std::array<unsigned char, 256> bytes = MakeShuffledBytes(); - size_t sum = 0; - for (auto _ : state) { - for (unsigned char b : bytes) sum += f(b) ? 1 : 0; - } - // Make a copy of `sum` before calling `DoNotOptimize` to make sure that `sum` - // can be put in a CPU register and not degrade performance in the loop above. - size_t sum2 = sum; - benchmark::DoNotOptimize(sum2); - state.SetBytesProcessed(state.iterations() * bytes.size()); -} - -using StdAsciiFunction = int (*)(int); -template <StdAsciiFunction f> -void BM_Ascii(benchmark::State& state) { - AsciiBenchmark(state, f); -} - -using AbslAsciiIsFunction = bool (*)(unsigned char); -template <AbslAsciiIsFunction f> -void BM_Ascii(benchmark::State& state) { - AsciiBenchmark(state, f); -} - -using AbslAsciiToFunction = char (*)(unsigned char); -template <AbslAsciiToFunction f> -void BM_Ascii(benchmark::State& state) { - AsciiBenchmark(state, f); -} - -inline char Noop(unsigned char b) { return static_cast<char>(b); } - -BENCHMARK_TEMPLATE(BM_Ascii, Noop); -BENCHMARK_TEMPLATE(BM_Ascii, std::isalpha); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha); -BENCHMARK_TEMPLATE(BM_Ascii, std::isdigit); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit); -BENCHMARK_TEMPLATE(BM_Ascii, std::isalnum); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum); -BENCHMARK_TEMPLATE(BM_Ascii, std::isspace); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace); -BENCHMARK_TEMPLATE(BM_Ascii, std::ispunct); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct); -BENCHMARK_TEMPLATE(BM_Ascii, std::isblank); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank); -BENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl); -BENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit); -BENCHMARK_TEMPLATE(BM_Ascii, std::isprint); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint); -BENCHMARK_TEMPLATE(BM_Ascii, std::isgraph); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph); -BENCHMARK_TEMPLATE(BM_Ascii, std::isupper); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper); -BENCHMARK_TEMPLATE(BM_Ascii, std::islower); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower); -BENCHMARK_TEMPLATE(BM_Ascii, isascii); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii); -BENCHMARK_TEMPLATE(BM_Ascii, std::tolower); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower); -BENCHMARK_TEMPLATE(BM_Ascii, std::toupper); -BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper); - -static void BM_StrToLower(benchmark::State& state) { - const int size = state.range(0); - std::string s(size, 'X'); - for (auto _ : state) { - benchmark::DoNotOptimize(absl::AsciiStrToLower(s)); - } -} -BENCHMARK(BM_StrToLower)->Range(1, 1 << 20); - -static void BM_StrToUpper(benchmark::State& state) { - const int size = state.range(0); - std::string s(size, 'x'); - for (auto _ : state) { - benchmark::DoNotOptimize(absl::AsciiStrToUpper(s)); - } -} -BENCHMARK(BM_StrToUpper)->Range(1, 1 << 20); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/ascii_test.cc b/third_party/abseil_cpp/absl/strings/ascii_test.cc deleted file mode 100644 index 5ecd23f8697d..000000000000 --- a/third_party/abseil_cpp/absl/strings/ascii_test.cc +++ /dev/null @@ -1,361 +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/strings/ascii.h" - -#include <cctype> -#include <clocale> -#include <cstring> -#include <string> - -#include "gtest/gtest.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" - -namespace { - -TEST(AsciiIsFoo, All) { - for (int i = 0; i < 256; i++) { - if ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) - EXPECT_TRUE(absl::ascii_isalpha(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isalpha(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if ((i >= '0' && i <= '9')) - EXPECT_TRUE(absl::ascii_isdigit(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isdigit(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (absl::ascii_isalpha(i) || absl::ascii_isdigit(i)) - EXPECT_TRUE(absl::ascii_isalnum(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isalnum(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i != '\0' && strchr(" \r\n\t\v\f", i)) - EXPECT_TRUE(absl::ascii_isspace(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isspace(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i >= 32 && i < 127) - EXPECT_TRUE(absl::ascii_isprint(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isprint(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (absl::ascii_isprint(i) && !absl::ascii_isspace(i) && - !absl::ascii_isalnum(i)) - EXPECT_TRUE(absl::ascii_ispunct(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_ispunct(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i == ' ' || i == '\t') - EXPECT_TRUE(absl::ascii_isblank(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isblank(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i < 32 || i == 127) - EXPECT_TRUE(absl::ascii_iscntrl(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_iscntrl(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (absl::ascii_isdigit(i) || (i >= 'A' && i <= 'F') || - (i >= 'a' && i <= 'f')) - EXPECT_TRUE(absl::ascii_isxdigit(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isxdigit(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i > 32 && i < 127) - EXPECT_TRUE(absl::ascii_isgraph(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isgraph(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i >= 'A' && i <= 'Z') - EXPECT_TRUE(absl::ascii_isupper(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_isupper(i)) << ": failed on " << i; - } - for (int i = 0; i < 256; i++) { - if (i >= 'a' && i <= 'z') - EXPECT_TRUE(absl::ascii_islower(i)) << ": failed on " << i; - else - EXPECT_TRUE(!absl::ascii_islower(i)) << ": failed on " << i; - } - for (int i = 0; i < 128; i++) { - EXPECT_TRUE(absl::ascii_isascii(i)) << ": failed on " << i; - } - for (int i = 128; i < 256; i++) { - EXPECT_TRUE(!absl::ascii_isascii(i)) << ": failed on " << i; - } - - // The official is* functions don't accept negative signed chars, but - // our absl::ascii_is* functions do. - for (int i = 0; i < 256; i++) { - signed char sc = static_cast<signed char>(static_cast<unsigned char>(i)); - EXPECT_EQ(absl::ascii_isalpha(i), absl::ascii_isalpha(sc)) << i; - EXPECT_EQ(absl::ascii_isdigit(i), absl::ascii_isdigit(sc)) << i; - EXPECT_EQ(absl::ascii_isalnum(i), absl::ascii_isalnum(sc)) << i; - EXPECT_EQ(absl::ascii_isspace(i), absl::ascii_isspace(sc)) << i; - EXPECT_EQ(absl::ascii_ispunct(i), absl::ascii_ispunct(sc)) << i; - EXPECT_EQ(absl::ascii_isblank(i), absl::ascii_isblank(sc)) << i; - EXPECT_EQ(absl::ascii_iscntrl(i), absl::ascii_iscntrl(sc)) << i; - EXPECT_EQ(absl::ascii_isxdigit(i), absl::ascii_isxdigit(sc)) << i; - EXPECT_EQ(absl::ascii_isprint(i), absl::ascii_isprint(sc)) << i; - EXPECT_EQ(absl::ascii_isgraph(i), absl::ascii_isgraph(sc)) << i; - EXPECT_EQ(absl::ascii_isupper(i), absl::ascii_isupper(sc)) << i; - EXPECT_EQ(absl::ascii_islower(i), absl::ascii_islower(sc)) << i; - EXPECT_EQ(absl::ascii_isascii(i), absl::ascii_isascii(sc)) << i; - } -} - -// Checks that absl::ascii_isfoo returns the same value as isfoo in the C -// locale. -TEST(AsciiIsFoo, SameAsIsFoo) { -#ifndef __ANDROID__ - // temporarily change locale to C. It should already be C, but just for safety - const char* old_locale = setlocale(LC_CTYPE, "C"); - ASSERT_TRUE(old_locale != nullptr); -#endif - - for (int i = 0; i < 256; i++) { - EXPECT_EQ(isalpha(i) != 0, absl::ascii_isalpha(i)) << i; - EXPECT_EQ(isdigit(i) != 0, absl::ascii_isdigit(i)) << i; - EXPECT_EQ(isalnum(i) != 0, absl::ascii_isalnum(i)) << i; - EXPECT_EQ(isspace(i) != 0, absl::ascii_isspace(i)) << i; - EXPECT_EQ(ispunct(i) != 0, absl::ascii_ispunct(i)) << i; - EXPECT_EQ(isblank(i) != 0, absl::ascii_isblank(i)) << i; - EXPECT_EQ(iscntrl(i) != 0, absl::ascii_iscntrl(i)) << i; - EXPECT_EQ(isxdigit(i) != 0, absl::ascii_isxdigit(i)) << i; - EXPECT_EQ(isprint(i) != 0, absl::ascii_isprint(i)) << i; - EXPECT_EQ(isgraph(i) != 0, absl::ascii_isgraph(i)) << i; - EXPECT_EQ(isupper(i) != 0, absl::ascii_isupper(i)) << i; - EXPECT_EQ(islower(i) != 0, absl::ascii_islower(i)) << i; - EXPECT_EQ(isascii(i) != 0, absl::ascii_isascii(i)) << i; - } - -#ifndef __ANDROID__ - // restore the old locale. - ASSERT_TRUE(setlocale(LC_CTYPE, old_locale)); -#endif -} - -TEST(AsciiToFoo, All) { -#ifndef __ANDROID__ - // temporarily change locale to C. It should already be C, but just for safety - const char* old_locale = setlocale(LC_CTYPE, "C"); - ASSERT_TRUE(old_locale != nullptr); -#endif - - for (int i = 0; i < 256; i++) { - if (absl::ascii_islower(i)) - EXPECT_EQ(absl::ascii_toupper(i), 'A' + (i - 'a')) << i; - else - EXPECT_EQ(absl::ascii_toupper(i), static_cast<char>(i)) << i; - - if (absl::ascii_isupper(i)) - EXPECT_EQ(absl::ascii_tolower(i), 'a' + (i - 'A')) << i; - else - EXPECT_EQ(absl::ascii_tolower(i), static_cast<char>(i)) << i; - - // These CHECKs only hold in a C locale. - EXPECT_EQ(static_cast<char>(tolower(i)), absl::ascii_tolower(i)) << i; - EXPECT_EQ(static_cast<char>(toupper(i)), absl::ascii_toupper(i)) << i; - - // The official to* functions don't accept negative signed chars, but - // our absl::ascii_to* functions do. - signed char sc = static_cast<signed char>(static_cast<unsigned char>(i)); - EXPECT_EQ(absl::ascii_tolower(i), absl::ascii_tolower(sc)) << i; - EXPECT_EQ(absl::ascii_toupper(i), absl::ascii_toupper(sc)) << i; - } -#ifndef __ANDROID__ - // restore the old locale. - ASSERT_TRUE(setlocale(LC_CTYPE, old_locale)); -#endif -} - -TEST(AsciiStrTo, Lower) { - const char buf[] = "ABCDEF"; - const std::string str("GHIJKL"); - const std::string str2("MNOPQR"); - const absl::string_view sp(str2); - - EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf)); - EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str)); - EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp)); - - char mutable_buf[] = "Mutable"; - std::transform(mutable_buf, mutable_buf + strlen(mutable_buf), - mutable_buf, absl::ascii_tolower); - EXPECT_STREQ("mutable", mutable_buf); -} - -TEST(AsciiStrTo, Upper) { - const char buf[] = "abcdef"; - const std::string str("ghijkl"); - const std::string str2("mnopqr"); - const absl::string_view sp(str2); - - EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf)); - EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str)); - EXPECT_EQ("MNOPQR", absl::AsciiStrToUpper(sp)); - - char mutable_buf[] = "Mutable"; - std::transform(mutable_buf, mutable_buf + strlen(mutable_buf), - mutable_buf, absl::ascii_toupper); - EXPECT_STREQ("MUTABLE", mutable_buf); -} - -TEST(StripLeadingAsciiWhitespace, FromStringView) { - EXPECT_EQ(absl::string_view{}, - absl::StripLeadingAsciiWhitespace(absl::string_view{})); - EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"foo"})); - EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo"})); - EXPECT_EQ("foo foo\n ", - absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo foo\n "})); - EXPECT_EQ(absl::string_view{}, absl::StripLeadingAsciiWhitespace( - {"\t \n\f\r\v\n\t \n\f\r\v\n"})); -} - -TEST(StripLeadingAsciiWhitespace, InPlace) { - std::string str; - - absl::StripLeadingAsciiWhitespace(&str); - EXPECT_EQ("", str); - - str = "foo"; - absl::StripLeadingAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = "\t \n\f\r\n\vfoo"; - absl::StripLeadingAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = "\t \n\f\r\n\vfoo foo\n "; - absl::StripLeadingAsciiWhitespace(&str); - EXPECT_EQ("foo foo\n ", str); - - str = "\t \n\f\r\v\n\t \n\f\r\v\n"; - absl::StripLeadingAsciiWhitespace(&str); - EXPECT_EQ(absl::string_view{}, str); -} - -TEST(StripTrailingAsciiWhitespace, FromStringView) { - EXPECT_EQ(absl::string_view{}, - absl::StripTrailingAsciiWhitespace(absl::string_view{})); - EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo"})); - EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo\t \n\f\r\n\v"})); - EXPECT_EQ(" \nfoo foo", - absl::StripTrailingAsciiWhitespace({" \nfoo foo\t \n\f\r\n\v"})); - EXPECT_EQ(absl::string_view{}, absl::StripTrailingAsciiWhitespace( - {"\t \n\f\r\v\n\t \n\f\r\v\n"})); -} - -TEST(StripTrailingAsciiWhitespace, InPlace) { - std::string str; - - absl::StripTrailingAsciiWhitespace(&str); - EXPECT_EQ("", str); - - str = "foo"; - absl::StripTrailingAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = "foo\t \n\f\r\n\v"; - absl::StripTrailingAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = " \nfoo foo\t \n\f\r\n\v"; - absl::StripTrailingAsciiWhitespace(&str); - EXPECT_EQ(" \nfoo foo", str); - - str = "\t \n\f\r\v\n\t \n\f\r\v\n"; - absl::StripTrailingAsciiWhitespace(&str); - EXPECT_EQ(absl::string_view{}, str); -} - -TEST(StripAsciiWhitespace, FromStringView) { - EXPECT_EQ(absl::string_view{}, - absl::StripAsciiWhitespace(absl::string_view{})); - EXPECT_EQ("foo", absl::StripAsciiWhitespace({"foo"})); - EXPECT_EQ("foo", - absl::StripAsciiWhitespace({"\t \n\f\r\n\vfoo\t \n\f\r\n\v"})); - EXPECT_EQ("foo foo", absl::StripAsciiWhitespace( - {"\t \n\f\r\n\vfoo foo\t \n\f\r\n\v"})); - EXPECT_EQ(absl::string_view{}, - absl::StripAsciiWhitespace({"\t \n\f\r\v\n\t \n\f\r\v\n"})); -} - -TEST(StripAsciiWhitespace, InPlace) { - std::string str; - - absl::StripAsciiWhitespace(&str); - EXPECT_EQ("", str); - - str = "foo"; - absl::StripAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = "\t \n\f\r\n\vfoo\t \n\f\r\n\v"; - absl::StripAsciiWhitespace(&str); - EXPECT_EQ("foo", str); - - str = "\t \n\f\r\n\vfoo foo\t \n\f\r\n\v"; - absl::StripAsciiWhitespace(&str); - EXPECT_EQ("foo foo", str); - - str = "\t \n\f\r\v\n\t \n\f\r\v\n"; - absl::StripAsciiWhitespace(&str); - EXPECT_EQ(absl::string_view{}, str); -} - -TEST(RemoveExtraAsciiWhitespace, InPlace) { - const char* inputs[] = {"No extra space", - " Leading whitespace", - "Trailing whitespace ", - " Leading and trailing ", - " Whitespace \t in\v middle ", - "'Eeeeep! \n Newlines!\n", - "nospaces", - "", - "\n\t a\t\n\nb \t\n"}; - - const char* outputs[] = { - "No extra space", - "Leading whitespace", - "Trailing whitespace", - "Leading and trailing", - "Whitespace in middle", - "'Eeeeep! Newlines!", - "nospaces", - "", - "a\nb", - }; - const int NUM_TESTS = ABSL_ARRAYSIZE(inputs); - - for (int i = 0; i < NUM_TESTS; i++) { - std::string s(inputs[i]); - absl::RemoveExtraAsciiWhitespace(&s); - EXPECT_EQ(outputs[i], s); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/charconv.cc b/third_party/abseil_cpp/absl/strings/charconv.cc deleted file mode 100644 index 3613a6528665..000000000000 --- a/third_party/abseil_cpp/absl/strings/charconv.cc +++ /dev/null @@ -1,984 +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/strings/charconv.h" - -#include <algorithm> -#include <cassert> -#include <cmath> -#include <cstring> - -#include "absl/base/casts.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" - -// The macro ABSL_BIT_PACK_FLOATS is defined on x86-64, where IEEE floating -// point numbers have the same endianness in memory as a bitfield struct -// containing the corresponding parts. -// -// When set, we replace calls to ldexp() with manual bit packing, which is -// faster and is unaffected by floating point environment. -#ifdef ABSL_BIT_PACK_FLOATS -#error ABSL_BIT_PACK_FLOATS cannot be directly set -#elif defined(__x86_64__) || defined(_M_X64) -#define ABSL_BIT_PACK_FLOATS 1 -#endif - -// A note about subnormals: -// -// The code below talks about "normals" and "subnormals". A normal IEEE float -// has a fixed-width mantissa and power of two exponent. For example, a normal -// `double` has a 53-bit mantissa. Because the high bit is always 1, it is not -// stored in the representation. The implicit bit buys an extra bit of -// resolution in the datatype. -// -// The downside of this scheme is that there is a large gap between DBL_MIN and -// zero. (Large, at least, relative to the different between DBL_MIN and the -// next representable number). This gap is softened by the "subnormal" numbers, -// which have the same power-of-two exponent as DBL_MIN, but no implicit 53rd -// bit. An all-bits-zero exponent in the encoding represents subnormals. (Zero -// is represented as a subnormal with an all-bits-zero mantissa.) -// -// The code below, in calculations, represents the mantissa as a uint64_t. The -// end result normally has the 53rd bit set. It represents subnormals by using -// narrower mantissas. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -template <typename FloatType> -struct FloatTraits; - -template <> -struct FloatTraits<double> { - // The number of mantissa bits in the given float type. This includes the - // implied high bit. - static constexpr int kTargetMantissaBits = 53; - - // The largest supported IEEE exponent, in our integral mantissa - // representation. - // - // If `m` is the largest possible int kTargetMantissaBits bits wide, then - // m * 2**kMaxExponent is exactly equal to DBL_MAX. - static constexpr int kMaxExponent = 971; - - // The smallest supported IEEE normal exponent, in our integral mantissa - // representation. - // - // If `m` is the smallest possible int kTargetMantissaBits bits wide, then - // m * 2**kMinNormalExponent is exactly equal to DBL_MIN. - static constexpr int kMinNormalExponent = -1074; - - static double MakeNan(const char* tagp) { - // Support nan no matter which namespace it's in. Some platforms - // incorrectly don't put it in namespace std. - using namespace std; // NOLINT - return nan(tagp); - } - - // Builds a nonzero floating point number out of the provided parts. - // - // This is intended to do the same operation as ldexp(mantissa, exponent), - // but using purely integer math, to avoid -ffastmath and floating - // point environment issues. Using type punning is also faster. We fall back - // to ldexp on a per-platform basis for portability. - // - // `exponent` must be between kMinNormalExponent and kMaxExponent. - // - // `mantissa` must either be exactly kTargetMantissaBits wide, in which case - // a normal value is made, or it must be less narrow than that, in which case - // `exponent` must be exactly kMinNormalExponent, and a subnormal value is - // made. - static double Make(uint64_t mantissa, int exponent, bool sign) { -#ifndef ABSL_BIT_PACK_FLOATS - // Support ldexp no matter which namespace it's in. Some platforms - // incorrectly don't put it in namespace std. - using namespace std; // NOLINT - return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent); -#else - constexpr uint64_t kMantissaMask = - (uint64_t(1) << (kTargetMantissaBits - 1)) - 1; - uint64_t dbl = static_cast<uint64_t>(sign) << 63; - if (mantissa > kMantissaMask) { - // Normal value. - // Adjust by 1023 for the exponent representation bias, and an additional - // 52 due to the implied decimal point in the IEEE mantissa represenation. - dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52; - mantissa &= kMantissaMask; - } else { - // subnormal value - assert(exponent == kMinNormalExponent); - } - dbl += mantissa; - return absl::bit_cast<double>(dbl); -#endif // ABSL_BIT_PACK_FLOATS - } -}; - -// Specialization of floating point traits for the `float` type. See the -// FloatTraits<double> specialization above for meaning of each of the following -// members and methods. -template <> -struct FloatTraits<float> { - static constexpr int kTargetMantissaBits = 24; - static constexpr int kMaxExponent = 104; - static constexpr int kMinNormalExponent = -149; - static float MakeNan(const char* tagp) { - // Support nanf no matter which namespace it's in. Some platforms - // incorrectly don't put it in namespace std. - using namespace std; // NOLINT - return nanf(tagp); - } - static float Make(uint32_t mantissa, int exponent, bool sign) { -#ifndef ABSL_BIT_PACK_FLOATS - // Support ldexpf no matter which namespace it's in. Some platforms - // incorrectly don't put it in namespace std. - using namespace std; // NOLINT - return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent); -#else - constexpr uint32_t kMantissaMask = - (uint32_t(1) << (kTargetMantissaBits - 1)) - 1; - uint32_t flt = static_cast<uint32_t>(sign) << 31; - if (mantissa > kMantissaMask) { - // Normal value. - // Adjust by 127 for the exponent representation bias, and an additional - // 23 due to the implied decimal point in the IEEE mantissa represenation. - flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23; - mantissa &= kMantissaMask; - } else { - // subnormal value - assert(exponent == kMinNormalExponent); - } - flt += mantissa; - return absl::bit_cast<float>(flt); -#endif // ABSL_BIT_PACK_FLOATS - } -}; - -// Decimal-to-binary conversions require coercing powers of 10 into a mantissa -// and a power of 2. The two helper functions Power10Mantissa(n) and -// Power10Exponent(n) perform this task. Together, these represent a hand- -// rolled floating point value which is equal to or just less than 10**n. -// -// The return values satisfy two range guarantees: -// -// Power10Mantissa(n) * 2**Power10Exponent(n) <= 10**n -// < (Power10Mantissa(n) + 1) * 2**Power10Exponent(n) -// -// 2**63 <= Power10Mantissa(n) < 2**64. -// -// Lookups into the power-of-10 table must first check the Power10Overflow() and -// Power10Underflow() functions, to avoid out-of-bounds table access. -// -// Indexes into these tables are biased by -kPower10TableMin, and the table has -// values in the range [kPower10TableMin, kPower10TableMax]. -extern const uint64_t kPower10MantissaTable[]; -extern const int16_t kPower10ExponentTable[]; - -// The smallest allowed value for use with the Power10Mantissa() and -// Power10Exponent() functions below. (If a smaller exponent is needed in -// calculations, the end result is guaranteed to underflow.) -constexpr int kPower10TableMin = -342; - -// The largest allowed value for use with the Power10Mantissa() and -// Power10Exponent() functions below. (If a smaller exponent is needed in -// calculations, the end result is guaranteed to overflow.) -constexpr int kPower10TableMax = 308; - -uint64_t Power10Mantissa(int n) { - return kPower10MantissaTable[n - kPower10TableMin]; -} - -int Power10Exponent(int n) { - return kPower10ExponentTable[n - kPower10TableMin]; -} - -// Returns true if n is large enough that 10**n always results in an IEEE -// overflow. -bool Power10Overflow(int n) { return n > kPower10TableMax; } - -// Returns true if n is small enough that 10**n times a ParsedFloat mantissa -// always results in an IEEE underflow. -bool Power10Underflow(int n) { return n < kPower10TableMin; } - -// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal -// to 10**n numerically. Put another way, this returns true if there is no -// truncation error in Power10Mantissa(n). -bool Power10Exact(int n) { return n >= 0 && n <= 27; } - -// Sentinel exponent values for representing numbers too large or too close to -// zero to represent in a double. -constexpr int kOverflow = 99999; -constexpr int kUnderflow = -99999; - -// Struct representing the calculated conversion result of a positive (nonzero) -// floating point number. -// -// The calculated number is mantissa * 2**exponent (mantissa is treated as an -// integer.) `mantissa` is chosen to be the correct width for the IEEE float -// representation being calculated. (`mantissa` will always have the same bit -// width for normal values, and narrower bit widths for subnormals.) -// -// If the result of conversion was an underflow or overflow, exponent is set -// to kUnderflow or kOverflow. -struct CalculatedFloat { - uint64_t mantissa = 0; - int exponent = 0; -}; - -// Returns the bit width of the given uint128. (Equivalently, returns 128 -// minus the number of leading zero bits.) -int BitWidth(uint128 value) { - if (Uint128High64(value) == 0) { - return 64 - base_internal::CountLeadingZeros64(Uint128Low64(value)); - } - return 128 - base_internal::CountLeadingZeros64(Uint128High64(value)); -} - -// Calculates how far to the right a mantissa needs to be shifted to create a -// properly adjusted mantissa for an IEEE floating point number. -// -// `mantissa_width` is the bit width of the mantissa to be shifted, and -// `binary_exponent` is the exponent of the number before the shift. -// -// This accounts for subnormal values, and will return a larger-than-normal -// shift if binary_exponent would otherwise be too low. -template <typename FloatType> -int NormalizedShiftSize(int mantissa_width, int binary_exponent) { - const int normal_shift = - mantissa_width - FloatTraits<FloatType>::kTargetMantissaBits; - const int minimum_shift = - FloatTraits<FloatType>::kMinNormalExponent - binary_exponent; - return std::max(normal_shift, minimum_shift); -} - -// Right shifts a uint128 so that it has the requested bit width. (The -// resulting value will have 128 - bit_width leading zeroes.) The initial -// `value` must be wider than the requested bit width. -// -// Returns the number of bits shifted. -int TruncateToBitWidth(int bit_width, uint128* value) { - const int current_bit_width = BitWidth(*value); - const int shift = current_bit_width - bit_width; - *value >>= shift; - return shift; -} - -// Checks if the given ParsedFloat represents one of the edge cases that are -// not dependent on number base: zero, infinity, or NaN. If so, sets *value -// the appropriate double, and returns true. -template <typename FloatType> -bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, - FloatType* value) { - if (input.type == strings_internal::FloatType::kNan) { - // A bug in both clang and gcc would cause the compiler to optimize away the - // buffer we are building below. Declaring the buffer volatile avoids the - // issue, and has no measurable performance impact in microbenchmarks. - // - // https://bugs.llvm.org/show_bug.cgi?id=37778 - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113 - constexpr ptrdiff_t kNanBufferSize = 128; - volatile char n_char_sequence[kNanBufferSize]; - if (input.subrange_begin == nullptr) { - n_char_sequence[0] = '\0'; - } else { - ptrdiff_t nan_size = input.subrange_end - input.subrange_begin; - nan_size = std::min(nan_size, kNanBufferSize - 1); - std::copy_n(input.subrange_begin, nan_size, n_char_sequence); - n_char_sequence[nan_size] = '\0'; - } - char* nan_argument = const_cast<char*>(n_char_sequence); - *value = negative ? -FloatTraits<FloatType>::MakeNan(nan_argument) - : FloatTraits<FloatType>::MakeNan(nan_argument); - return true; - } - if (input.type == strings_internal::FloatType::kInfinity) { - *value = negative ? -std::numeric_limits<FloatType>::infinity() - : std::numeric_limits<FloatType>::infinity(); - return true; - } - if (input.mantissa == 0) { - *value = negative ? -0.0 : 0.0; - return true; - } - return false; -} - -// Given a CalculatedFloat result of a from_chars conversion, generate the -// correct output values. -// -// CalculatedFloat can represent an underflow or overflow, in which case the -// error code in *result is set. Otherwise, the calculated floating point -// number is stored in *value. -template <typename FloatType> -void EncodeResult(const CalculatedFloat& calculated, bool negative, - absl::from_chars_result* result, FloatType* value) { - if (calculated.exponent == kOverflow) { - result->ec = std::errc::result_out_of_range; - *value = negative ? -std::numeric_limits<FloatType>::max() - : std::numeric_limits<FloatType>::max(); - return; - } else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) { - result->ec = std::errc::result_out_of_range; - *value = negative ? -0.0 : 0.0; - return; - } - *value = FloatTraits<FloatType>::Make(calculated.mantissa, - calculated.exponent, negative); -} - -// Returns the given uint128 shifted to the right by `shift` bits, and rounds -// the remaining bits using round_to_nearest logic. The value is returned as a -// uint64_t, since this is the type used by this library for storing calculated -// floating point mantissas. -// -// It is expected that the width of the input value shifted by `shift` will -// be the correct bit-width for the target mantissa, which is strictly narrower -// than a uint64_t. -// -// If `input_exact` is false, then a nonzero error epsilon is assumed. For -// rounding purposes, the true value being rounded is strictly greater than the -// input value. The error may represent a single lost carry bit. -// -// When input_exact, shifted bits of the form 1000000... represent a tie, which -// is broken by rounding to even -- the rounding direction is chosen so the low -// bit of the returned value is 0. -// -// When !input_exact, shifted bits of the form 10000000... represent a value -// strictly greater than one half (due to the error epsilon), and so ties are -// always broken by rounding up. -// -// When !input_exact, shifted bits of the form 01111111... are uncertain; -// the true value may or may not be greater than 10000000..., due to the -// possible lost carry bit. The correct rounding direction is unknown. In this -// case, the result is rounded down, and `output_exact` is set to false. -// -// Zero and negative values of `shift` are accepted, in which case the word is -// shifted left, as necessary. -uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact, - bool* output_exact) { - if (shift <= 0) { - *output_exact = input_exact; - return static_cast<uint64_t>(value << -shift); - } - if (shift >= 128) { - // Exponent is so small that we are shifting away all significant bits. - // Answer will not be representable, even as a subnormal, so return a zero - // mantissa (which represents underflow). - *output_exact = true; - return 0; - } - - *output_exact = true; - const uint128 shift_mask = (uint128(1) << shift) - 1; - const uint128 halfway_point = uint128(1) << (shift - 1); - - const uint128 shifted_bits = value & shift_mask; - value >>= shift; - if (shifted_bits > halfway_point) { - // Shifted bits greater than 10000... require rounding up. - return static_cast<uint64_t>(value + 1); - } - if (shifted_bits == halfway_point) { - // In exact mode, shifted bits of 10000... mean we're exactly halfway - // between two numbers, and we must round to even. So only round up if - // the low bit of `value` is set. - // - // In inexact mode, the nonzero error means the actual value is greater - // than the halfway point and we must alway round up. - if ((value & 1) == 1 || !input_exact) { - ++value; - } - return static_cast<uint64_t>(value); - } - if (!input_exact && shifted_bits == halfway_point - 1) { - // Rounding direction is unclear, due to error. - *output_exact = false; - } - // Otherwise, round down. - return static_cast<uint64_t>(value); -} - -// Checks if a floating point guess needs to be rounded up, using high precision -// math. -// -// `guess_mantissa` and `guess_exponent` represent a candidate guess for the -// number represented by `parsed_decimal`. -// -// The exact number represented by `parsed_decimal` must lie between the two -// numbers: -// A = `guess_mantissa * 2**guess_exponent` -// B = `(guess_mantissa + 1) * 2**guess_exponent` -// -// This function returns false if `A` is the better guess, and true if `B` is -// the better guess, with rounding ties broken by rounding to even. -bool MustRoundUp(uint64_t guess_mantissa, int guess_exponent, - const strings_internal::ParsedFloat& parsed_decimal) { - // 768 is the number of digits needed in the worst case. We could determine a - // better limit dynamically based on the value of parsed_decimal.exponent. - // This would optimize pathological input cases only. (Sane inputs won't have - // hundreds of digits of mantissa.) - absl::strings_internal::BigUnsigned<84> exact_mantissa; - int exact_exponent = exact_mantissa.ReadFloatMantissa(parsed_decimal, 768); - - // Adjust the `guess` arguments to be halfway between A and B. - guess_mantissa = guess_mantissa * 2 + 1; - guess_exponent -= 1; - - // In our comparison: - // lhs = exact = exact_mantissa * 10**exact_exponent - // = exact_mantissa * 5**exact_exponent * 2**exact_exponent - // rhs = guess = guess_mantissa * 2**guess_exponent - // - // Because we are doing integer math, we can't directly deal with negative - // exponents. We instead move these to the other side of the inequality. - absl::strings_internal::BigUnsigned<84>& lhs = exact_mantissa; - int comparison; - if (exact_exponent >= 0) { - lhs.MultiplyByFiveToTheNth(exact_exponent); - absl::strings_internal::BigUnsigned<84> rhs(guess_mantissa); - // There are powers of 2 on both sides of the inequality; reduce this to - // a single bit-shift. - if (exact_exponent > guess_exponent) { - lhs.ShiftLeft(exact_exponent - guess_exponent); - } else { - rhs.ShiftLeft(guess_exponent - exact_exponent); - } - comparison = Compare(lhs, rhs); - } else { - // Move the power of 5 to the other side of the equation, giving us: - // lhs = exact_mantissa * 2**exact_exponent - // rhs = guess_mantissa * 5**(-exact_exponent) * 2**guess_exponent - absl::strings_internal::BigUnsigned<84> rhs = - absl::strings_internal::BigUnsigned<84>::FiveToTheNth(-exact_exponent); - rhs.MultiplyBy(guess_mantissa); - if (exact_exponent > guess_exponent) { - lhs.ShiftLeft(exact_exponent - guess_exponent); - } else { - rhs.ShiftLeft(guess_exponent - exact_exponent); - } - comparison = Compare(lhs, rhs); - } - if (comparison < 0) { - return false; - } else if (comparison > 0) { - return true; - } else { - // When lhs == rhs, the decimal input is exactly between A and B. - // Round towards even -- round up only if the low bit of the initial - // `guess_mantissa` was a 1. We shifted guess_mantissa left 1 bit at - // the beginning of this function, so test the 2nd bit here. - return (guess_mantissa & 2) == 2; - } -} - -// Constructs a CalculatedFloat from a given mantissa and exponent, but -// with the following normalizations applied: -// -// If rounding has caused mantissa to increase just past the allowed bit -// width, shift and adjust exponent. -// -// If exponent is too high, sets kOverflow. -// -// If mantissa is zero (representing a non-zero value not representable, even -// as a subnormal), sets kUnderflow. -template <typename FloatType> -CalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) { - CalculatedFloat result; - if (mantissa == uint64_t(1) << FloatTraits<FloatType>::kTargetMantissaBits) { - mantissa >>= 1; - exponent += 1; - } - if (exponent > FloatTraits<FloatType>::kMaxExponent) { - result.exponent = kOverflow; - } else if (mantissa == 0) { - result.exponent = kUnderflow; - } else { - result.exponent = exponent; - result.mantissa = mantissa; - } - return result; -} - -template <typename FloatType> -CalculatedFloat CalculateFromParsedHexadecimal( - const strings_internal::ParsedFloat& parsed_hex) { - uint64_t mantissa = parsed_hex.mantissa; - int exponent = parsed_hex.exponent; - int mantissa_width = 64 - base_internal::CountLeadingZeros64(mantissa); - const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent); - bool result_exact; - exponent += shift; - mantissa = ShiftRightAndRound(mantissa, shift, - /* input exact= */ true, &result_exact); - // ParseFloat handles rounding in the hexadecimal case, so we don't have to - // check `result_exact` here. - return CalculatedFloatFromRawValues<FloatType>(mantissa, exponent); -} - -template <typename FloatType> -CalculatedFloat CalculateFromParsedDecimal( - const strings_internal::ParsedFloat& parsed_decimal) { - CalculatedFloat result; - - // Large or small enough decimal exponents will always result in overflow - // or underflow. - if (Power10Underflow(parsed_decimal.exponent)) { - result.exponent = kUnderflow; - return result; - } else if (Power10Overflow(parsed_decimal.exponent)) { - result.exponent = kOverflow; - return result; - } - - // Otherwise convert our power of 10 into a power of 2 times an integer - // mantissa, and multiply this by our parsed decimal mantissa. - uint128 wide_binary_mantissa = parsed_decimal.mantissa; - wide_binary_mantissa *= Power10Mantissa(parsed_decimal.exponent); - int binary_exponent = Power10Exponent(parsed_decimal.exponent); - - // Discard bits that are inaccurate due to truncation error. The magic - // `mantissa_width` constants below are justified in - // https://abseil.io/about/design/charconv. They represent the number of bits - // in `wide_binary_mantissa` that are guaranteed to be unaffected by error - // propagation. - bool mantissa_exact; - int mantissa_width; - if (parsed_decimal.subrange_begin) { - // Truncated mantissa - mantissa_width = 58; - mantissa_exact = false; - binary_exponent += - TruncateToBitWidth(mantissa_width, &wide_binary_mantissa); - } else if (!Power10Exact(parsed_decimal.exponent)) { - // Exact mantissa, truncated power of ten - mantissa_width = 63; - mantissa_exact = false; - binary_exponent += - TruncateToBitWidth(mantissa_width, &wide_binary_mantissa); - } else { - // Product is exact - mantissa_width = BitWidth(wide_binary_mantissa); - mantissa_exact = true; - } - - // Shift into an FloatType-sized mantissa, and round to nearest. - const int shift = - NormalizedShiftSize<FloatType>(mantissa_width, binary_exponent); - bool result_exact; - binary_exponent += shift; - uint64_t binary_mantissa = ShiftRightAndRound(wide_binary_mantissa, shift, - mantissa_exact, &result_exact); - if (!result_exact) { - // We could not determine the rounding direction using int128 math. Use - // full resolution math instead. - if (MustRoundUp(binary_mantissa, binary_exponent, parsed_decimal)) { - binary_mantissa += 1; - } - } - - return CalculatedFloatFromRawValues<FloatType>(binary_mantissa, - binary_exponent); -} - -template <typename FloatType> -from_chars_result FromCharsImpl(const char* first, const char* last, - FloatType& value, chars_format fmt_flags) { - from_chars_result result; - result.ptr = first; // overwritten on successful parse - result.ec = std::errc(); - - bool negative = false; - if (first != last && *first == '-') { - ++first; - negative = true; - } - // If the `hex` flag is *not* set, then we will accept a 0x prefix and try - // to parse a hexadecimal float. - if ((fmt_flags & chars_format::hex) == chars_format{} && last - first >= 2 && - *first == '0' && (first[1] == 'x' || first[1] == 'X')) { - const char* hex_first = first + 2; - strings_internal::ParsedFloat hex_parse = - strings_internal::ParseFloat<16>(hex_first, last, fmt_flags); - if (hex_parse.end == nullptr || - hex_parse.type != strings_internal::FloatType::kNumber) { - // 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 - // 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.) - if (fmt_flags == chars_format::scientific) { - result.ec = std::errc::invalid_argument; - } else { - result.ptr = first + 1; - value = negative ? -0.0 : 0.0; - } - return result; - } - // We matched a value. - result.ptr = hex_parse.end; - if (HandleEdgeCase(hex_parse, negative, &value)) { - return result; - } - CalculatedFloat calculated = - CalculateFromParsedHexadecimal<FloatType>(hex_parse); - EncodeResult(calculated, negative, &result, &value); - return result; - } - // Otherwise, we choose the number base based on the flags. - if ((fmt_flags & chars_format::hex) == chars_format::hex) { - strings_internal::ParsedFloat hex_parse = - strings_internal::ParseFloat<16>(first, last, fmt_flags); - if (hex_parse.end == nullptr) { - result.ec = std::errc::invalid_argument; - return result; - } - result.ptr = hex_parse.end; - if (HandleEdgeCase(hex_parse, negative, &value)) { - return result; - } - CalculatedFloat calculated = - CalculateFromParsedHexadecimal<FloatType>(hex_parse); - EncodeResult(calculated, negative, &result, &value); - return result; - } else { - strings_internal::ParsedFloat decimal_parse = - strings_internal::ParseFloat<10>(first, last, fmt_flags); - if (decimal_parse.end == nullptr) { - result.ec = std::errc::invalid_argument; - return result; - } - result.ptr = decimal_parse.end; - if (HandleEdgeCase(decimal_parse, negative, &value)) { - return result; - } - CalculatedFloat calculated = - CalculateFromParsedDecimal<FloatType>(decimal_parse); - EncodeResult(calculated, negative, &result, &value); - return result; - } -} -} // namespace - -from_chars_result from_chars(const char* first, const char* last, double& value, - chars_format fmt) { - return FromCharsImpl(first, last, value, fmt); -} - -from_chars_result from_chars(const char* first, const char* last, float& value, - chars_format fmt) { - return FromCharsImpl(first, last, value, fmt); -} - -namespace { - -// Table of powers of 10, from kPower10TableMin to kPower10TableMax. -// -// kPower10MantissaTable[i - kPower10TableMin] stores the 64-bit mantissa (high -// bit always on), and kPower10ExponentTable[i - kPower10TableMin] stores the -// power-of-two exponent. For a given number i, this gives the unique mantissa -// and exponent such that mantissa * 2**exponent <= 10**i < (mantissa + 1) * -// 2**exponent. - -const uint64_t kPower10MantissaTable[] = { - 0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U, - 0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U, - 0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU, - 0xde8b2b66b3bc4723U, 0x8b16fb203055ac76U, 0xaddcb9e83c6b1793U, - 0xd953e8624b85dd78U, 0x87d4713d6f33aa6bU, 0xa9c98d8ccb009506U, - 0xd43bf0effdc0ba48U, 0x84a57695fe98746dU, 0xa5ced43b7e3e9188U, - 0xcf42894a5dce35eaU, 0x818995ce7aa0e1b2U, 0xa1ebfb4219491a1fU, - 0xca66fa129f9b60a6U, 0xfd00b897478238d0U, 0x9e20735e8cb16382U, - 0xc5a890362fddbc62U, 0xf712b443bbd52b7bU, 0x9a6bb0aa55653b2dU, - 0xc1069cd4eabe89f8U, 0xf148440a256e2c76U, 0x96cd2a865764dbcaU, - 0xbc807527ed3e12bcU, 0xeba09271e88d976bU, 0x93445b8731587ea3U, - 0xb8157268fdae9e4cU, 0xe61acf033d1a45dfU, 0x8fd0c16206306babU, - 0xb3c4f1ba87bc8696U, 0xe0b62e2929aba83cU, 0x8c71dcd9ba0b4925U, - 0xaf8e5410288e1b6fU, 0xdb71e91432b1a24aU, 0x892731ac9faf056eU, - 0xab70fe17c79ac6caU, 0xd64d3d9db981787dU, 0x85f0468293f0eb4eU, - 0xa76c582338ed2621U, 0xd1476e2c07286faaU, 0x82cca4db847945caU, - 0xa37fce126597973cU, 0xcc5fc196fefd7d0cU, 0xff77b1fcbebcdc4fU, - 0x9faacf3df73609b1U, 0xc795830d75038c1dU, 0xf97ae3d0d2446f25U, - 0x9becce62836ac577U, 0xc2e801fb244576d5U, 0xf3a20279ed56d48aU, - 0x9845418c345644d6U, 0xbe5691ef416bd60cU, 0xedec366b11c6cb8fU, - 0x94b3a202eb1c3f39U, 0xb9e08a83a5e34f07U, 0xe858ad248f5c22c9U, - 0x91376c36d99995beU, 0xb58547448ffffb2dU, 0xe2e69915b3fff9f9U, - 0x8dd01fad907ffc3bU, 0xb1442798f49ffb4aU, 0xdd95317f31c7fa1dU, - 0x8a7d3eef7f1cfc52U, 0xad1c8eab5ee43b66U, 0xd863b256369d4a40U, - 0x873e4f75e2224e68U, 0xa90de3535aaae202U, 0xd3515c2831559a83U, - 0x8412d9991ed58091U, 0xa5178fff668ae0b6U, 0xce5d73ff402d98e3U, - 0x80fa687f881c7f8eU, 0xa139029f6a239f72U, 0xc987434744ac874eU, - 0xfbe9141915d7a922U, 0x9d71ac8fada6c9b5U, 0xc4ce17b399107c22U, - 0xf6019da07f549b2bU, 0x99c102844f94e0fbU, 0xc0314325637a1939U, - 0xf03d93eebc589f88U, 0x96267c7535b763b5U, 0xbbb01b9283253ca2U, - 0xea9c227723ee8bcbU, 0x92a1958a7675175fU, 0xb749faed14125d36U, - 0xe51c79a85916f484U, 0x8f31cc0937ae58d2U, 0xb2fe3f0b8599ef07U, - 0xdfbdcece67006ac9U, 0x8bd6a141006042bdU, 0xaecc49914078536dU, - 0xda7f5bf590966848U, 0x888f99797a5e012dU, 0xaab37fd7d8f58178U, - 0xd5605fcdcf32e1d6U, 0x855c3be0a17fcd26U, 0xa6b34ad8c9dfc06fU, - 0xd0601d8efc57b08bU, 0x823c12795db6ce57U, 0xa2cb1717b52481edU, - 0xcb7ddcdda26da268U, 0xfe5d54150b090b02U, 0x9efa548d26e5a6e1U, - 0xc6b8e9b0709f109aU, 0xf867241c8cc6d4c0U, 0x9b407691d7fc44f8U, - 0xc21094364dfb5636U, 0xf294b943e17a2bc4U, 0x979cf3ca6cec5b5aU, - 0xbd8430bd08277231U, 0xece53cec4a314ebdU, 0x940f4613ae5ed136U, - 0xb913179899f68584U, 0xe757dd7ec07426e5U, 0x9096ea6f3848984fU, - 0xb4bca50b065abe63U, 0xe1ebce4dc7f16dfbU, 0x8d3360f09cf6e4bdU, - 0xb080392cc4349decU, 0xdca04777f541c567U, 0x89e42caaf9491b60U, - 0xac5d37d5b79b6239U, 0xd77485cb25823ac7U, 0x86a8d39ef77164bcU, - 0xa8530886b54dbdebU, 0xd267caa862a12d66U, 0x8380dea93da4bc60U, - 0xa46116538d0deb78U, 0xcd795be870516656U, 0x806bd9714632dff6U, - 0xa086cfcd97bf97f3U, 0xc8a883c0fdaf7df0U, 0xfad2a4b13d1b5d6cU, - 0x9cc3a6eec6311a63U, 0xc3f490aa77bd60fcU, 0xf4f1b4d515acb93bU, - 0x991711052d8bf3c5U, 0xbf5cd54678eef0b6U, 0xef340a98172aace4U, - 0x9580869f0e7aac0eU, 0xbae0a846d2195712U, 0xe998d258869facd7U, - 0x91ff83775423cc06U, 0xb67f6455292cbf08U, 0xe41f3d6a7377eecaU, - 0x8e938662882af53eU, 0xb23867fb2a35b28dU, 0xdec681f9f4c31f31U, - 0x8b3c113c38f9f37eU, 0xae0b158b4738705eU, 0xd98ddaee19068c76U, - 0x87f8a8d4cfa417c9U, 0xa9f6d30a038d1dbcU, 0xd47487cc8470652bU, - 0x84c8d4dfd2c63f3bU, 0xa5fb0a17c777cf09U, 0xcf79cc9db955c2ccU, - 0x81ac1fe293d599bfU, 0xa21727db38cb002fU, 0xca9cf1d206fdc03bU, - 0xfd442e4688bd304aU, 0x9e4a9cec15763e2eU, 0xc5dd44271ad3cdbaU, - 0xf7549530e188c128U, 0x9a94dd3e8cf578b9U, 0xc13a148e3032d6e7U, - 0xf18899b1bc3f8ca1U, 0x96f5600f15a7b7e5U, 0xbcb2b812db11a5deU, - 0xebdf661791d60f56U, 0x936b9fcebb25c995U, 0xb84687c269ef3bfbU, - 0xe65829b3046b0afaU, 0x8ff71a0fe2c2e6dcU, 0xb3f4e093db73a093U, - 0xe0f218b8d25088b8U, 0x8c974f7383725573U, 0xafbd2350644eeacfU, - 0xdbac6c247d62a583U, 0x894bc396ce5da772U, 0xab9eb47c81f5114fU, - 0xd686619ba27255a2U, 0x8613fd0145877585U, 0xa798fc4196e952e7U, - 0xd17f3b51fca3a7a0U, 0x82ef85133de648c4U, 0xa3ab66580d5fdaf5U, - 0xcc963fee10b7d1b3U, 0xffbbcfe994e5c61fU, 0x9fd561f1fd0f9bd3U, - 0xc7caba6e7c5382c8U, 0xf9bd690a1b68637bU, 0x9c1661a651213e2dU, - 0xc31bfa0fe5698db8U, 0xf3e2f893dec3f126U, 0x986ddb5c6b3a76b7U, - 0xbe89523386091465U, 0xee2ba6c0678b597fU, 0x94db483840b717efU, - 0xba121a4650e4ddebU, 0xe896a0d7e51e1566U, 0x915e2486ef32cd60U, - 0xb5b5ada8aaff80b8U, 0xe3231912d5bf60e6U, 0x8df5efabc5979c8fU, - 0xb1736b96b6fd83b3U, 0xddd0467c64bce4a0U, 0x8aa22c0dbef60ee4U, - 0xad4ab7112eb3929dU, 0xd89d64d57a607744U, 0x87625f056c7c4a8bU, - 0xa93af6c6c79b5d2dU, 0xd389b47879823479U, 0x843610cb4bf160cbU, - 0xa54394fe1eedb8feU, 0xce947a3da6a9273eU, 0x811ccc668829b887U, - 0xa163ff802a3426a8U, 0xc9bcff6034c13052U, 0xfc2c3f3841f17c67U, - 0x9d9ba7832936edc0U, 0xc5029163f384a931U, 0xf64335bcf065d37dU, - 0x99ea0196163fa42eU, 0xc06481fb9bcf8d39U, 0xf07da27a82c37088U, - 0x964e858c91ba2655U, 0xbbe226efb628afeaU, 0xeadab0aba3b2dbe5U, - 0x92c8ae6b464fc96fU, 0xb77ada0617e3bbcbU, 0xe55990879ddcaabdU, - 0x8f57fa54c2a9eab6U, 0xb32df8e9f3546564U, 0xdff9772470297ebdU, - 0x8bfbea76c619ef36U, 0xaefae51477a06b03U, 0xdab99e59958885c4U, - 0x88b402f7fd75539bU, 0xaae103b5fcd2a881U, 0xd59944a37c0752a2U, - 0x857fcae62d8493a5U, 0xa6dfbd9fb8e5b88eU, 0xd097ad07a71f26b2U, - 0x825ecc24c873782fU, 0xa2f67f2dfa90563bU, 0xcbb41ef979346bcaU, - 0xfea126b7d78186bcU, 0x9f24b832e6b0f436U, 0xc6ede63fa05d3143U, - 0xf8a95fcf88747d94U, 0x9b69dbe1b548ce7cU, 0xc24452da229b021bU, - 0xf2d56790ab41c2a2U, 0x97c560ba6b0919a5U, 0xbdb6b8e905cb600fU, - 0xed246723473e3813U, 0x9436c0760c86e30bU, 0xb94470938fa89bceU, - 0xe7958cb87392c2c2U, 0x90bd77f3483bb9b9U, 0xb4ecd5f01a4aa828U, - 0xe2280b6c20dd5232U, 0x8d590723948a535fU, 0xb0af48ec79ace837U, - 0xdcdb1b2798182244U, 0x8a08f0f8bf0f156bU, 0xac8b2d36eed2dac5U, - 0xd7adf884aa879177U, 0x86ccbb52ea94baeaU, 0xa87fea27a539e9a5U, - 0xd29fe4b18e88640eU, 0x83a3eeeef9153e89U, 0xa48ceaaab75a8e2bU, - 0xcdb02555653131b6U, 0x808e17555f3ebf11U, 0xa0b19d2ab70e6ed6U, - 0xc8de047564d20a8bU, 0xfb158592be068d2eU, 0x9ced737bb6c4183dU, - 0xc428d05aa4751e4cU, 0xf53304714d9265dfU, 0x993fe2c6d07b7fabU, - 0xbf8fdb78849a5f96U, 0xef73d256a5c0f77cU, 0x95a8637627989aadU, - 0xbb127c53b17ec159U, 0xe9d71b689dde71afU, 0x9226712162ab070dU, - 0xb6b00d69bb55c8d1U, 0xe45c10c42a2b3b05U, 0x8eb98a7a9a5b04e3U, - 0xb267ed1940f1c61cU, 0xdf01e85f912e37a3U, 0x8b61313bbabce2c6U, - 0xae397d8aa96c1b77U, 0xd9c7dced53c72255U, 0x881cea14545c7575U, - 0xaa242499697392d2U, 0xd4ad2dbfc3d07787U, 0x84ec3c97da624ab4U, - 0xa6274bbdd0fadd61U, 0xcfb11ead453994baU, 0x81ceb32c4b43fcf4U, - 0xa2425ff75e14fc31U, 0xcad2f7f5359a3b3eU, 0xfd87b5f28300ca0dU, - 0x9e74d1b791e07e48U, 0xc612062576589ddaU, 0xf79687aed3eec551U, - 0x9abe14cd44753b52U, 0xc16d9a0095928a27U, 0xf1c90080baf72cb1U, - 0x971da05074da7beeU, 0xbce5086492111aeaU, 0xec1e4a7db69561a5U, - 0x9392ee8e921d5d07U, 0xb877aa3236a4b449U, 0xe69594bec44de15bU, - 0x901d7cf73ab0acd9U, 0xb424dc35095cd80fU, 0xe12e13424bb40e13U, - 0x8cbccc096f5088cbU, 0xafebff0bcb24aafeU, 0xdbe6fecebdedd5beU, - 0x89705f4136b4a597U, 0xabcc77118461cefcU, 0xd6bf94d5e57a42bcU, - 0x8637bd05af6c69b5U, 0xa7c5ac471b478423U, 0xd1b71758e219652bU, - 0x83126e978d4fdf3bU, 0xa3d70a3d70a3d70aU, 0xccccccccccccccccU, - 0x8000000000000000U, 0xa000000000000000U, 0xc800000000000000U, - 0xfa00000000000000U, 0x9c40000000000000U, 0xc350000000000000U, - 0xf424000000000000U, 0x9896800000000000U, 0xbebc200000000000U, - 0xee6b280000000000U, 0x9502f90000000000U, 0xba43b74000000000U, - 0xe8d4a51000000000U, 0x9184e72a00000000U, 0xb5e620f480000000U, - 0xe35fa931a0000000U, 0x8e1bc9bf04000000U, 0xb1a2bc2ec5000000U, - 0xde0b6b3a76400000U, 0x8ac7230489e80000U, 0xad78ebc5ac620000U, - 0xd8d726b7177a8000U, 0x878678326eac9000U, 0xa968163f0a57b400U, - 0xd3c21bcecceda100U, 0x84595161401484a0U, 0xa56fa5b99019a5c8U, - 0xcecb8f27f4200f3aU, 0x813f3978f8940984U, 0xa18f07d736b90be5U, - 0xc9f2c9cd04674edeU, 0xfc6f7c4045812296U, 0x9dc5ada82b70b59dU, - 0xc5371912364ce305U, 0xf684df56c3e01bc6U, 0x9a130b963a6c115cU, - 0xc097ce7bc90715b3U, 0xf0bdc21abb48db20U, 0x96769950b50d88f4U, - 0xbc143fa4e250eb31U, 0xeb194f8e1ae525fdU, 0x92efd1b8d0cf37beU, - 0xb7abc627050305adU, 0xe596b7b0c643c719U, 0x8f7e32ce7bea5c6fU, - 0xb35dbf821ae4f38bU, 0xe0352f62a19e306eU, 0x8c213d9da502de45U, - 0xaf298d050e4395d6U, 0xdaf3f04651d47b4cU, 0x88d8762bf324cd0fU, - 0xab0e93b6efee0053U, 0xd5d238a4abe98068U, 0x85a36366eb71f041U, - 0xa70c3c40a64e6c51U, 0xd0cf4b50cfe20765U, 0x82818f1281ed449fU, - 0xa321f2d7226895c7U, 0xcbea6f8ceb02bb39U, 0xfee50b7025c36a08U, - 0x9f4f2726179a2245U, 0xc722f0ef9d80aad6U, 0xf8ebad2b84e0d58bU, - 0x9b934c3b330c8577U, 0xc2781f49ffcfa6d5U, 0xf316271c7fc3908aU, - 0x97edd871cfda3a56U, 0xbde94e8e43d0c8ecU, 0xed63a231d4c4fb27U, - 0x945e455f24fb1cf8U, 0xb975d6b6ee39e436U, 0xe7d34c64a9c85d44U, - 0x90e40fbeea1d3a4aU, 0xb51d13aea4a488ddU, 0xe264589a4dcdab14U, - 0x8d7eb76070a08aecU, 0xb0de65388cc8ada8U, 0xdd15fe86affad912U, - 0x8a2dbf142dfcc7abU, 0xacb92ed9397bf996U, 0xd7e77a8f87daf7fbU, - 0x86f0ac99b4e8dafdU, 0xa8acd7c0222311bcU, 0xd2d80db02aabd62bU, - 0x83c7088e1aab65dbU, 0xa4b8cab1a1563f52U, 0xcde6fd5e09abcf26U, - 0x80b05e5ac60b6178U, 0xa0dc75f1778e39d6U, 0xc913936dd571c84cU, - 0xfb5878494ace3a5fU, 0x9d174b2dcec0e47bU, 0xc45d1df942711d9aU, - 0xf5746577930d6500U, 0x9968bf6abbe85f20U, 0xbfc2ef456ae276e8U, - 0xefb3ab16c59b14a2U, 0x95d04aee3b80ece5U, 0xbb445da9ca61281fU, - 0xea1575143cf97226U, 0x924d692ca61be758U, 0xb6e0c377cfa2e12eU, - 0xe498f455c38b997aU, 0x8edf98b59a373fecU, 0xb2977ee300c50fe7U, - 0xdf3d5e9bc0f653e1U, 0x8b865b215899f46cU, 0xae67f1e9aec07187U, - 0xda01ee641a708de9U, 0x884134fe908658b2U, 0xaa51823e34a7eedeU, - 0xd4e5e2cdc1d1ea96U, 0x850fadc09923329eU, 0xa6539930bf6bff45U, - 0xcfe87f7cef46ff16U, 0x81f14fae158c5f6eU, 0xa26da3999aef7749U, - 0xcb090c8001ab551cU, 0xfdcb4fa002162a63U, 0x9e9f11c4014dda7eU, - 0xc646d63501a1511dU, 0xf7d88bc24209a565U, 0x9ae757596946075fU, - 0xc1a12d2fc3978937U, 0xf209787bb47d6b84U, 0x9745eb4d50ce6332U, - 0xbd176620a501fbffU, 0xec5d3fa8ce427affU, 0x93ba47c980e98cdfU, - 0xb8a8d9bbe123f017U, 0xe6d3102ad96cec1dU, 0x9043ea1ac7e41392U, - 0xb454e4a179dd1877U, 0xe16a1dc9d8545e94U, 0x8ce2529e2734bb1dU, - 0xb01ae745b101e9e4U, 0xdc21a1171d42645dU, 0x899504ae72497ebaU, - 0xabfa45da0edbde69U, 0xd6f8d7509292d603U, 0x865b86925b9bc5c2U, - 0xa7f26836f282b732U, 0xd1ef0244af2364ffU, 0x8335616aed761f1fU, - 0xa402b9c5a8d3a6e7U, 0xcd036837130890a1U, 0x802221226be55a64U, - 0xa02aa96b06deb0fdU, 0xc83553c5c8965d3dU, 0xfa42a8b73abbf48cU, - 0x9c69a97284b578d7U, 0xc38413cf25e2d70dU, 0xf46518c2ef5b8cd1U, - 0x98bf2f79d5993802U, 0xbeeefb584aff8603U, 0xeeaaba2e5dbf6784U, - 0x952ab45cfa97a0b2U, 0xba756174393d88dfU, 0xe912b9d1478ceb17U, - 0x91abb422ccb812eeU, 0xb616a12b7fe617aaU, 0xe39c49765fdf9d94U, - 0x8e41ade9fbebc27dU, 0xb1d219647ae6b31cU, 0xde469fbd99a05fe3U, - 0x8aec23d680043beeU, 0xada72ccc20054ae9U, 0xd910f7ff28069da4U, - 0x87aa9aff79042286U, 0xa99541bf57452b28U, 0xd3fa922f2d1675f2U, - 0x847c9b5d7c2e09b7U, 0xa59bc234db398c25U, 0xcf02b2c21207ef2eU, - 0x8161afb94b44f57dU, 0xa1ba1ba79e1632dcU, 0xca28a291859bbf93U, - 0xfcb2cb35e702af78U, 0x9defbf01b061adabU, 0xc56baec21c7a1916U, - 0xf6c69a72a3989f5bU, 0x9a3c2087a63f6399U, 0xc0cb28a98fcf3c7fU, - 0xf0fdf2d3f3c30b9fU, 0x969eb7c47859e743U, 0xbc4665b596706114U, - 0xeb57ff22fc0c7959U, 0x9316ff75dd87cbd8U, 0xb7dcbf5354e9beceU, - 0xe5d3ef282a242e81U, 0x8fa475791a569d10U, 0xb38d92d760ec4455U, - 0xe070f78d3927556aU, 0x8c469ab843b89562U, 0xaf58416654a6babbU, - 0xdb2e51bfe9d0696aU, 0x88fcf317f22241e2U, 0xab3c2fddeeaad25aU, - 0xd60b3bd56a5586f1U, 0x85c7056562757456U, 0xa738c6bebb12d16cU, - 0xd106f86e69d785c7U, 0x82a45b450226b39cU, 0xa34d721642b06084U, - 0xcc20ce9bd35c78a5U, 0xff290242c83396ceU, 0x9f79a169bd203e41U, - 0xc75809c42c684dd1U, 0xf92e0c3537826145U, 0x9bbcc7a142b17ccbU, - 0xc2abf989935ddbfeU, 0xf356f7ebf83552feU, 0x98165af37b2153deU, - 0xbe1bf1b059e9a8d6U, 0xeda2ee1c7064130cU, 0x9485d4d1c63e8be7U, - 0xb9a74a0637ce2ee1U, 0xe8111c87c5c1ba99U, 0x910ab1d4db9914a0U, - 0xb54d5e4a127f59c8U, 0xe2a0b5dc971f303aU, 0x8da471a9de737e24U, - 0xb10d8e1456105dadU, 0xdd50f1996b947518U, 0x8a5296ffe33cc92fU, - 0xace73cbfdc0bfb7bU, 0xd8210befd30efa5aU, 0x8714a775e3e95c78U, - 0xa8d9d1535ce3b396U, 0xd31045a8341ca07cU, 0x83ea2b892091e44dU, - 0xa4e4b66b68b65d60U, 0xce1de40642e3f4b9U, 0x80d2ae83e9ce78f3U, - 0xa1075a24e4421730U, 0xc94930ae1d529cfcU, 0xfb9b7cd9a4a7443cU, - 0x9d412e0806e88aa5U, 0xc491798a08a2ad4eU, 0xf5b5d7ec8acb58a2U, - 0x9991a6f3d6bf1765U, 0xbff610b0cc6edd3fU, 0xeff394dcff8a948eU, - 0x95f83d0a1fb69cd9U, 0xbb764c4ca7a4440fU, 0xea53df5fd18d5513U, - 0x92746b9be2f8552cU, 0xb7118682dbb66a77U, 0xe4d5e82392a40515U, - 0x8f05b1163ba6832dU, 0xb2c71d5bca9023f8U, 0xdf78e4b2bd342cf6U, - 0x8bab8eefb6409c1aU, 0xae9672aba3d0c320U, 0xda3c0f568cc4f3e8U, - 0x8865899617fb1871U, 0xaa7eebfb9df9de8dU, 0xd51ea6fa85785631U, - 0x8533285c936b35deU, 0xa67ff273b8460356U, 0xd01fef10a657842cU, - 0x8213f56a67f6b29bU, 0xa298f2c501f45f42U, 0xcb3f2f7642717713U, - 0xfe0efb53d30dd4d7U, 0x9ec95d1463e8a506U, 0xc67bb4597ce2ce48U, - 0xf81aa16fdc1b81daU, 0x9b10a4e5e9913128U, 0xc1d4ce1f63f57d72U, - 0xf24a01a73cf2dccfU, 0x976e41088617ca01U, 0xbd49d14aa79dbc82U, - 0xec9c459d51852ba2U, 0x93e1ab8252f33b45U, 0xb8da1662e7b00a17U, - 0xe7109bfba19c0c9dU, 0x906a617d450187e2U, 0xb484f9dc9641e9daU, - 0xe1a63853bbd26451U, 0x8d07e33455637eb2U, 0xb049dc016abc5e5fU, - 0xdc5c5301c56b75f7U, 0x89b9b3e11b6329baU, 0xac2820d9623bf429U, - 0xd732290fbacaf133U, 0x867f59a9d4bed6c0U, 0xa81f301449ee8c70U, - 0xd226fc195c6a2f8cU, 0x83585d8fd9c25db7U, 0xa42e74f3d032f525U, - 0xcd3a1230c43fb26fU, 0x80444b5e7aa7cf85U, 0xa0555e361951c366U, - 0xc86ab5c39fa63440U, 0xfa856334878fc150U, 0x9c935e00d4b9d8d2U, - 0xc3b8358109e84f07U, 0xf4a642e14c6262c8U, 0x98e7e9cccfbd7dbdU, - 0xbf21e44003acdd2cU, 0xeeea5d5004981478U, 0x95527a5202df0ccbU, - 0xbaa718e68396cffdU, 0xe950df20247c83fdU, 0x91d28b7416cdd27eU, - 0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU, -}; - -const int16_t kPower10ExponentTable[] = { - -1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166, - -1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130, - -1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093, - -1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057, - -1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020, - -1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984, - -980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947, - -944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911, - -907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874, - -871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838, - -834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801, - -798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764, - -761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728, - -725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691, - -688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655, - -651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618, - -615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582, - -578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545, - -542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509, - -505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472, - -469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436, - -432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399, - -396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362, - -359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326, - -323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289, - -286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253, - -250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216, - -213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180, - -176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143, - -140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107, - -103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70, - -67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34, - -30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3, - 6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39, - 43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76, - 79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113, - 116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149, - 152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186, - 189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222, - 226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259, - 262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295, - 299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332, - 335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368, - 372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405, - 408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441, - 445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478, - 481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515, - 518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551, - 554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588, - 591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624, - 627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661, - 664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697, - 701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734, - 737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770, - 774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807, - 810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843, - 847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880, - 883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916, - 920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953, - 956, 960, -}; - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/charconv.h b/third_party/abseil_cpp/absl/strings/charconv.h deleted file mode 100644 index e04be32f9514..000000000000 --- a/third_party/abseil_cpp/absl/strings/charconv.h +++ /dev/null @@ -1,119 +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. - -#ifndef ABSL_STRINGS_CHARCONV_H_ -#define ABSL_STRINGS_CHARCONV_H_ - -#include <system_error> // NOLINT(build/c++11) - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Workalike compatibilty version of std::chars_format from C++17. -// -// This is an bitfield enumerator which can be passed to absl::from_chars to -// configure the string-to-float conversion. -enum class chars_format { - scientific = 1, - fixed = 2, - hex = 4, - general = fixed | scientific, -}; - -// The return result of a string-to-number conversion. -// -// `ec` will be set to `invalid_argument` if a well-formed number was not found -// at the start of the input range, `result_out_of_range` if a well-formed -// number was found, but it was out of the representable range of the requested -// type, or to std::errc() otherwise. -// -// If a well-formed number was found, `ptr` is set to one past the sequence of -// characters that were successfully parsed. If none was found, `ptr` is set -// to the `first` argument to from_chars. -struct from_chars_result { - const char* ptr; - std::errc ec; -}; - -// Workalike compatibilty version of std::from_chars from C++17. Currently -// this only supports the `double` and `float` types. -// -// This interface incorporates the proposed resolutions for library issues -// DR 3080 and DR 3081. If these are adopted with different wording, -// Abseil's behavior will change to match the standard. (The behavior most -// likely to change is for DR 3081, which says what `value` will be set to in -// the case of overflow and underflow. Code that wants to avoid possible -// breaking changes in this area should not depend on `value` when the returned -// from_chars_result indicates a range error.) -// -// Searches the range [first, last) for the longest matching pattern beginning -// at `first` that represents a floating point number. If one is found, store -// the result in `value`. -// -// The matching pattern format is almost the same as that of strtod(), except -// 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 -// `scientific`, a matching number must contain an exponent. If set to `fixed`, -// then an exponent will never match. (For example, the string "1e5" will be -// parsed as "1".) If set to `hex`, then a hexadecimal float is parsed in the -// format that strtod() accepts, except that a "0x" prefix is NOT matched. -// (In particular, in `hex` mode, the input "0xff" results in the largest -// matching pattern "0".) -absl::from_chars_result from_chars(const char* first, const char* last, - double& value, // NOLINT - chars_format fmt = chars_format::general); - -absl::from_chars_result from_chars(const char* first, const char* last, - float& value, // NOLINT - chars_format fmt = chars_format::general); - -// std::chars_format is specified as a bitmask type, which means the following -// operations must be provided: -inline constexpr chars_format operator&(chars_format lhs, chars_format rhs) { - return static_cast<chars_format>(static_cast<int>(lhs) & - static_cast<int>(rhs)); -} -inline constexpr chars_format operator|(chars_format lhs, chars_format rhs) { - return static_cast<chars_format>(static_cast<int>(lhs) | - static_cast<int>(rhs)); -} -inline constexpr chars_format operator^(chars_format lhs, chars_format rhs) { - return static_cast<chars_format>(static_cast<int>(lhs) ^ - static_cast<int>(rhs)); -} -inline constexpr chars_format operator~(chars_format arg) { - return static_cast<chars_format>(~static_cast<int>(arg)); -} -inline chars_format& operator&=(chars_format& lhs, chars_format rhs) { - lhs = lhs & rhs; - return lhs; -} -inline chars_format& operator|=(chars_format& lhs, chars_format rhs) { - lhs = lhs | rhs; - return lhs; -} -inline chars_format& operator^=(chars_format& lhs, chars_format rhs) { - lhs = lhs ^ rhs; - return lhs; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_CHARCONV_H_ diff --git a/third_party/abseil_cpp/absl/strings/charconv_benchmark.cc b/third_party/abseil_cpp/absl/strings/charconv_benchmark.cc deleted file mode 100644 index e8c7371d6586..000000000000 --- a/third_party/abseil_cpp/absl/strings/charconv_benchmark.cc +++ /dev/null @@ -1,204 +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/strings/charconv.h" - -#include <cstdlib> -#include <cstring> -#include <string> - -#include "benchmark/benchmark.h" - -namespace { - -void BM_Strtod_Pi(benchmark::State& state) { - const char* pi = "3.14159"; - for (auto s : state) { - benchmark::DoNotOptimize(pi); - benchmark::DoNotOptimize(strtod(pi, nullptr)); - } -} -BENCHMARK(BM_Strtod_Pi); - -void BM_Absl_Pi(benchmark::State& state) { - const char* pi = "3.14159"; - const char* pi_end = pi + strlen(pi); - for (auto s : state) { - benchmark::DoNotOptimize(pi); - double v; - absl::from_chars(pi, pi_end, v); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_Absl_Pi); - -void BM_Strtod_Pi_float(benchmark::State& state) { - const char* pi = "3.14159"; - for (auto s : state) { - benchmark::DoNotOptimize(pi); - benchmark::DoNotOptimize(strtof(pi, nullptr)); - } -} -BENCHMARK(BM_Strtod_Pi_float); - -void BM_Absl_Pi_float(benchmark::State& state) { - const char* pi = "3.14159"; - const char* pi_end = pi + strlen(pi); - for (auto s : state) { - benchmark::DoNotOptimize(pi); - float v; - absl::from_chars(pi, pi_end, v); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_Absl_Pi_float); - -void BM_Strtod_HardLarge(benchmark::State& state) { - const char* num = "272104041512242479.e200"; - for (auto s : state) { - benchmark::DoNotOptimize(num); - benchmark::DoNotOptimize(strtod(num, nullptr)); - } -} -BENCHMARK(BM_Strtod_HardLarge); - -void BM_Absl_HardLarge(benchmark::State& state) { - const char* numstr = "272104041512242479.e200"; - const char* numstr_end = numstr + strlen(numstr); - for (auto s : state) { - benchmark::DoNotOptimize(numstr); - double v; - absl::from_chars(numstr, numstr_end, v); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_Absl_HardLarge); - -void BM_Strtod_HardSmall(benchmark::State& state) { - const char* num = "94080055902682397.e-242"; - for (auto s : state) { - benchmark::DoNotOptimize(num); - benchmark::DoNotOptimize(strtod(num, nullptr)); - } -} -BENCHMARK(BM_Strtod_HardSmall); - -void BM_Absl_HardSmall(benchmark::State& state) { - const char* numstr = "94080055902682397.e-242"; - const char* numstr_end = numstr + strlen(numstr); - for (auto s : state) { - benchmark::DoNotOptimize(numstr); - double v; - absl::from_chars(numstr, numstr_end, v); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_Absl_HardSmall); - -void BM_Strtod_HugeMantissa(benchmark::State& state) { - std::string huge(200, '3'); - const char* num = huge.c_str(); - for (auto s : state) { - benchmark::DoNotOptimize(num); - benchmark::DoNotOptimize(strtod(num, nullptr)); - } -} -BENCHMARK(BM_Strtod_HugeMantissa); - -void BM_Absl_HugeMantissa(benchmark::State& state) { - std::string huge(200, '3'); - const char* num = huge.c_str(); - const char* num_end = num + 200; - for (auto s : state) { - benchmark::DoNotOptimize(num); - double v; - absl::from_chars(num, num_end, v); - benchmark::DoNotOptimize(v); - } -} -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. - const std::string digits = - "1." - "152113937042223790993097181572444900347587985074226836242307364987727724" - "831384300183638649152607195040591791364113930628852279348613864894524591" - "272746490313676832900762939595690019745859128071117417798540258114233761" - "012939937017879509401007964861774960297319002612457273148497158989073482" - "171377406078223015359818300988676687994537274548940612510414856761641652" - "513434981938564294004070500716200446656421722229202383105446378511678258" - "370570631774499359748259931676320916632111681001853983492795053244971606" - "922718923011680846577744433974087653954904214152517799883551075537146316" - "168973685866425605046988661997658648354773076621610279716804960009043764" - "038392994055171112475093876476783502487512538082706095923790634572014823" - "78877699375152587890625" + - std::string(5000, '0'); - // generate the hard cases on either side for the given length. - // Lengths between 3 and 1000 are reasonable. - return digits.substr(0, length) + "1e-297"; -} - -void BM_Strtod_Big_And_Difficult(benchmark::State& state) { - std::string testcase = MakeHardCase(state.range(0)); - const char* begin = testcase.c_str(); - for (auto s : state) { - benchmark::DoNotOptimize(begin); - benchmark::DoNotOptimize(strtod(begin, nullptr)); - } -} -BENCHMARK(BM_Strtod_Big_And_Difficult)->Range(3, 5000); - -void BM_Absl_Big_And_Difficult(benchmark::State& state) { - std::string testcase = MakeHardCase(state.range(0)); - const char* begin = testcase.c_str(); - const char* end = begin + testcase.size(); - for (auto s : state) { - benchmark::DoNotOptimize(begin); - double v; - absl::from_chars(begin, end, v); - benchmark::DoNotOptimize(v); - } -} -BENCHMARK(BM_Absl_Big_And_Difficult)->Range(3, 5000); - -} // namespace - -// ------------------------------------------------------------------------ -// Benchmark Time CPU Iterations -// ------------------------------------------------------------------------ -// BM_Strtod_Pi 96 ns 96 ns 6337454 -// BM_Absl_Pi 35 ns 35 ns 20031996 -// BM_Strtod_Pi_float 91 ns 91 ns 7745851 -// BM_Absl_Pi_float 35 ns 35 ns 20430298 -// BM_Strtod_HardLarge 133 ns 133 ns 5288341 -// BM_Absl_HardLarge 181 ns 181 ns 3855615 -// BM_Strtod_HardSmall 279 ns 279 ns 2517243 -// BM_Absl_HardSmall 287 ns 287 ns 2458744 -// BM_Strtod_HugeMantissa 433 ns 433 ns 1604293 -// BM_Absl_HugeMantissa 160 ns 160 ns 4403671 -// BM_Strtod_Big_And_Difficult/3 236 ns 236 ns 2942496 -// BM_Strtod_Big_And_Difficult/8 232 ns 232 ns 2983796 -// BM_Strtod_Big_And_Difficult/64 437 ns 437 ns 1591951 -// BM_Strtod_Big_And_Difficult/512 1738 ns 1738 ns 402519 -// BM_Strtod_Big_And_Difficult/4096 3943 ns 3943 ns 176128 -// BM_Strtod_Big_And_Difficult/5000 4397 ns 4397 ns 157878 -// BM_Absl_Big_And_Difficult/3 39 ns 39 ns 17799583 -// BM_Absl_Big_And_Difficult/8 43 ns 43 ns 16096859 -// BM_Absl_Big_And_Difficult/64 550 ns 550 ns 1259717 -// BM_Absl_Big_And_Difficult/512 4167 ns 4167 ns 171414 -// BM_Absl_Big_And_Difficult/4096 9160 ns 9159 ns 76297 -// BM_Absl_Big_And_Difficult/5000 9738 ns 9738 ns 70140 diff --git a/third_party/abseil_cpp/absl/strings/charconv_test.cc b/third_party/abseil_cpp/absl/strings/charconv_test.cc deleted file mode 100644 index 9090e9c89c50..000000000000 --- a/third_party/abseil_cpp/absl/strings/charconv_test.cc +++ /dev/null @@ -1,780 +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/strings/charconv.h" - -#include <cstdlib> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/internal/pow10_helper.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" - -#ifdef _MSC_FULL_VER -#define ABSL_COMPILER_DOES_EXACT_ROUNDING 0 -#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 0 -#else -#define ABSL_COMPILER_DOES_EXACT_ROUNDING 1 -#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 1 -#endif - -namespace { - -using absl::strings_internal::Pow10; - -#if ABSL_COMPILER_DOES_EXACT_ROUNDING - -// Tests that the given string is accepted by absl::from_chars, and that it -// converts exactly equal to the given number. -void TestDoubleParse(absl::string_view str, double expected_number) { - SCOPED_TRACE(str); - double actual_number = 0.0; - absl::from_chars_result result = - absl::from_chars(str.data(), str.data() + str.length(), actual_number); - EXPECT_EQ(result.ec, std::errc()); - EXPECT_EQ(result.ptr, str.data() + str.length()); - EXPECT_EQ(actual_number, expected_number); -} - -void TestFloatParse(absl::string_view str, float expected_number) { - SCOPED_TRACE(str); - float actual_number = 0.0; - absl::from_chars_result result = - absl::from_chars(str.data(), str.data() + str.length(), actual_number); - EXPECT_EQ(result.ec, std::errc()); - EXPECT_EQ(result.ptr, str.data() + str.length()); - EXPECT_EQ(actual_number, expected_number); -} - -// Tests that the given double or single precision floating point literal is -// parsed correctly by absl::from_chars. -// -// These convenience macros assume that the C++ compiler being used also does -// fully correct decimal-to-binary conversions. -#define FROM_CHARS_TEST_DOUBLE(number) \ - { \ - TestDoubleParse(#number, number); \ - TestDoubleParse("-" #number, -number); \ - } - -#define FROM_CHARS_TEST_FLOAT(number) \ - { \ - TestFloatParse(#number, number##f); \ - TestFloatParse("-" #number, -number##f); \ - } - -TEST(FromChars, NearRoundingCases) { - // Cases from "A Program for Testing IEEE Decimal-Binary Conversion" - // by Vern Paxson. - - // Forms that should round towards zero. (These are the hardest cases for - // each decimal mantissa size.) - FROM_CHARS_TEST_DOUBLE(5.e125); - FROM_CHARS_TEST_DOUBLE(69.e267); - FROM_CHARS_TEST_DOUBLE(999.e-026); - FROM_CHARS_TEST_DOUBLE(7861.e-034); - FROM_CHARS_TEST_DOUBLE(75569.e-254); - FROM_CHARS_TEST_DOUBLE(928609.e-261); - FROM_CHARS_TEST_DOUBLE(9210917.e080); - FROM_CHARS_TEST_DOUBLE(84863171.e114); - FROM_CHARS_TEST_DOUBLE(653777767.e273); - FROM_CHARS_TEST_DOUBLE(5232604057.e-298); - FROM_CHARS_TEST_DOUBLE(27235667517.e-109); - FROM_CHARS_TEST_DOUBLE(653532977297.e-123); - FROM_CHARS_TEST_DOUBLE(3142213164987.e-294); - FROM_CHARS_TEST_DOUBLE(46202199371337.e-072); - FROM_CHARS_TEST_DOUBLE(231010996856685.e-073); - FROM_CHARS_TEST_DOUBLE(9324754620109615.e212); - FROM_CHARS_TEST_DOUBLE(78459735791271921.e049); - FROM_CHARS_TEST_DOUBLE(272104041512242479.e200); - FROM_CHARS_TEST_DOUBLE(6802601037806061975.e198); - FROM_CHARS_TEST_DOUBLE(20505426358836677347.e-221); - FROM_CHARS_TEST_DOUBLE(836168422905420598437.e-234); - FROM_CHARS_TEST_DOUBLE(4891559871276714924261.e222); - FROM_CHARS_TEST_FLOAT(5.e-20); - FROM_CHARS_TEST_FLOAT(67.e14); - FROM_CHARS_TEST_FLOAT(985.e15); - FROM_CHARS_TEST_FLOAT(7693.e-42); - FROM_CHARS_TEST_FLOAT(55895.e-16); - FROM_CHARS_TEST_FLOAT(996622.e-44); - FROM_CHARS_TEST_FLOAT(7038531.e-32); - FROM_CHARS_TEST_FLOAT(60419369.e-46); - FROM_CHARS_TEST_FLOAT(702990899.e-20); - FROM_CHARS_TEST_FLOAT(6930161142.e-48); - FROM_CHARS_TEST_FLOAT(25933168707.e-13); - FROM_CHARS_TEST_FLOAT(596428896559.e20); - - // Similarly, forms that should round away from zero. - FROM_CHARS_TEST_DOUBLE(9.e-265); - FROM_CHARS_TEST_DOUBLE(85.e-037); - FROM_CHARS_TEST_DOUBLE(623.e100); - FROM_CHARS_TEST_DOUBLE(3571.e263); - FROM_CHARS_TEST_DOUBLE(81661.e153); - FROM_CHARS_TEST_DOUBLE(920657.e-023); - FROM_CHARS_TEST_DOUBLE(4603285.e-024); - FROM_CHARS_TEST_DOUBLE(87575437.e-309); - FROM_CHARS_TEST_DOUBLE(245540327.e122); - FROM_CHARS_TEST_DOUBLE(6138508175.e120); - FROM_CHARS_TEST_DOUBLE(83356057653.e193); - FROM_CHARS_TEST_DOUBLE(619534293513.e124); - FROM_CHARS_TEST_DOUBLE(2335141086879.e218); - FROM_CHARS_TEST_DOUBLE(36167929443327.e-159); - FROM_CHARS_TEST_DOUBLE(609610927149051.e-255); - FROM_CHARS_TEST_DOUBLE(3743626360493413.e-165); - FROM_CHARS_TEST_DOUBLE(94080055902682397.e-242); - FROM_CHARS_TEST_DOUBLE(899810892172646163.e283); - FROM_CHARS_TEST_DOUBLE(7120190517612959703.e120); - FROM_CHARS_TEST_DOUBLE(25188282901709339043.e-252); - FROM_CHARS_TEST_DOUBLE(308984926168550152811.e-052); - FROM_CHARS_TEST_DOUBLE(6372891218502368041059.e064); - FROM_CHARS_TEST_FLOAT(3.e-23); - FROM_CHARS_TEST_FLOAT(57.e18); - FROM_CHARS_TEST_FLOAT(789.e-35); - FROM_CHARS_TEST_FLOAT(2539.e-18); - FROM_CHARS_TEST_FLOAT(76173.e28); - FROM_CHARS_TEST_FLOAT(887745.e-11); - FROM_CHARS_TEST_FLOAT(5382571.e-37); - FROM_CHARS_TEST_FLOAT(82381273.e-35); - FROM_CHARS_TEST_FLOAT(750486563.e-38); - FROM_CHARS_TEST_FLOAT(3752432815.e-39); - FROM_CHARS_TEST_FLOAT(75224575729.e-45); - FROM_CHARS_TEST_FLOAT(459926601011.e15); -} - -#undef FROM_CHARS_TEST_DOUBLE -#undef FROM_CHARS_TEST_FLOAT -#endif - -float ToFloat(absl::string_view s) { - float f; - absl::from_chars(s.data(), s.data() + s.size(), f); - return f; -} - -double ToDouble(absl::string_view s) { - double d; - absl::from_chars(s.data(), s.data() + s.size(), d); - return d; -} - -// A duplication of the test cases in "NearRoundingCases" above, but with -// expected values expressed with integers, using ldexp/ldexpf. These test -// cases will work even on compilers that do not accurately round floating point -// literals. -TEST(FromChars, NearRoundingCasesExplicit) { - EXPECT_EQ(ToDouble("5.e125"), ldexp(6653062250012735, 365)); - EXPECT_EQ(ToDouble("69.e267"), ldexp(4705683757438170, 841)); - EXPECT_EQ(ToDouble("999.e-026"), ldexp(6798841691080350, -129)); - EXPECT_EQ(ToDouble("7861.e-034"), ldexp(8975675289889240, -153)); - EXPECT_EQ(ToDouble("75569.e-254"), ldexp(6091718967192243, -880)); - EXPECT_EQ(ToDouble("928609.e-261"), ldexp(7849264900213743, -900)); - EXPECT_EQ(ToDouble("9210917.e080"), ldexp(8341110837370930, 236)); - EXPECT_EQ(ToDouble("84863171.e114"), ldexp(4625202867375927, 353)); - EXPECT_EQ(ToDouble("653777767.e273"), ldexp(5068902999763073, 884)); - EXPECT_EQ(ToDouble("5232604057.e-298"), ldexp(5741343011915040, -1010)); - EXPECT_EQ(ToDouble("27235667517.e-109"), ldexp(6707124626673586, -380)); - EXPECT_EQ(ToDouble("653532977297.e-123"), ldexp(7078246407265384, -422)); - EXPECT_EQ(ToDouble("3142213164987.e-294"), ldexp(8219991337640559, -988)); - EXPECT_EQ(ToDouble("46202199371337.e-072"), ldexp(5224462102115359, -246)); - EXPECT_EQ(ToDouble("231010996856685.e-073"), ldexp(5224462102115359, -247)); - EXPECT_EQ(ToDouble("9324754620109615.e212"), ldexp(5539753864394442, 705)); - EXPECT_EQ(ToDouble("78459735791271921.e049"), ldexp(8388176519442766, 166)); - EXPECT_EQ(ToDouble("272104041512242479.e200"), ldexp(5554409530847367, 670)); - EXPECT_EQ(ToDouble("6802601037806061975.e198"), ldexp(5554409530847367, 668)); - EXPECT_EQ(ToDouble("20505426358836677347.e-221"), - ldexp(4524032052079546, -722)); - EXPECT_EQ(ToDouble("836168422905420598437.e-234"), - ldexp(5070963299887562, -760)); - EXPECT_EQ(ToDouble("4891559871276714924261.e222"), - ldexp(6452687840519111, 757)); - EXPECT_EQ(ToFloat("5.e-20"), ldexpf(15474250, -88)); - EXPECT_EQ(ToFloat("67.e14"), ldexpf(12479722, 29)); - EXPECT_EQ(ToFloat("985.e15"), ldexpf(14333636, 36)); - EXPECT_EQ(ToFloat("7693.e-42"), ldexpf(10979816, -150)); - EXPECT_EQ(ToFloat("55895.e-16"), ldexpf(12888509, -61)); - EXPECT_EQ(ToFloat("996622.e-44"), ldexpf(14224264, -150)); - EXPECT_EQ(ToFloat("7038531.e-32"), ldexpf(11420669, -107)); - EXPECT_EQ(ToFloat("60419369.e-46"), ldexpf(8623340, -150)); - EXPECT_EQ(ToFloat("702990899.e-20"), ldexpf(16209866, -61)); - EXPECT_EQ(ToFloat("6930161142.e-48"), ldexpf(9891056, -150)); - EXPECT_EQ(ToFloat("25933168707.e-13"), ldexpf(11138211, -32)); - EXPECT_EQ(ToFloat("596428896559.e20"), ldexpf(12333860, 82)); - - - EXPECT_EQ(ToDouble("9.e-265"), ldexp(8168427841980010, -930)); - EXPECT_EQ(ToDouble("85.e-037"), ldexp(6360455125664090, -169)); - EXPECT_EQ(ToDouble("623.e100"), ldexp(6263531988747231, 289)); - EXPECT_EQ(ToDouble("3571.e263"), ldexp(6234526311072170, 833)); - EXPECT_EQ(ToDouble("81661.e153"), ldexp(6696636728760206, 472)); - EXPECT_EQ(ToDouble("920657.e-023"), ldexp(5975405561110124, -109)); - EXPECT_EQ(ToDouble("4603285.e-024"), ldexp(5975405561110124, -110)); - EXPECT_EQ(ToDouble("87575437.e-309"), ldexp(8452160731874668, -1053)); - EXPECT_EQ(ToDouble("245540327.e122"), ldexp(4985336549131723, 381)); - EXPECT_EQ(ToDouble("6138508175.e120"), ldexp(4985336549131723, 379)); - EXPECT_EQ(ToDouble("83356057653.e193"), ldexp(5986732817132056, 625)); - EXPECT_EQ(ToDouble("619534293513.e124"), ldexp(4798406992060657, 399)); - EXPECT_EQ(ToDouble("2335141086879.e218"), ldexp(5419088166961646, 713)); - EXPECT_EQ(ToDouble("36167929443327.e-159"), ldexp(8135819834632444, -536)); - EXPECT_EQ(ToDouble("609610927149051.e-255"), ldexp(4576664294594737, -850)); - EXPECT_EQ(ToDouble("3743626360493413.e-165"), ldexp(6898586531774201, -549)); - EXPECT_EQ(ToDouble("94080055902682397.e-242"), ldexp(6273271706052298, -800)); - EXPECT_EQ(ToDouble("899810892172646163.e283"), ldexp(7563892574477827, 947)); - EXPECT_EQ(ToDouble("7120190517612959703.e120"), ldexp(5385467232557565, 409)); - EXPECT_EQ(ToDouble("25188282901709339043.e-252"), - ldexp(5635662608542340, -825)); - EXPECT_EQ(ToDouble("308984926168550152811.e-052"), - ldexp(5644774693823803, -157)); - EXPECT_EQ(ToDouble("6372891218502368041059.e064"), - ldexp(4616868614322430, 233)); - - EXPECT_EQ(ToFloat("3.e-23"), ldexpf(9507380, -98)); - EXPECT_EQ(ToFloat("57.e18"), ldexpf(12960300, 42)); - EXPECT_EQ(ToFloat("789.e-35"), ldexpf(10739312, -130)); - EXPECT_EQ(ToFloat("2539.e-18"), ldexpf(11990089, -72)); - EXPECT_EQ(ToFloat("76173.e28"), ldexpf(9845130, 86)); - EXPECT_EQ(ToFloat("887745.e-11"), ldexpf(9760860, -40)); - EXPECT_EQ(ToFloat("5382571.e-37"), ldexpf(11447463, -124)); - EXPECT_EQ(ToFloat("82381273.e-35"), ldexpf(8554961, -113)); - EXPECT_EQ(ToFloat("750486563.e-38"), ldexpf(9975678, -120)); - EXPECT_EQ(ToFloat("3752432815.e-39"), ldexpf(9975678, -121)); - EXPECT_EQ(ToFloat("75224575729.e-45"), ldexpf(13105970, -137)); - EXPECT_EQ(ToFloat("459926601011.e15"), ldexpf(12466336, 65)); -} - -// Common test logic for converting a string which lies exactly halfway between -// two target floats. -// -// mantissa and exponent represent the precise value between two floating point -// numbers, `expected_low` and `expected_high`. The floating point -// representation to parse in `StrCat(mantissa, "e", exponent)`. -// -// This function checks that an input just slightly less than the exact value -// is rounded down to `expected_low`, and an input just slightly greater than -// the exact value is rounded up to `expected_high`. -// -// The exact value should round to `expected_half`, which must be either -// `expected_low` or `expected_high`. -template <typename FloatType> -void TestHalfwayValue(const std::string& mantissa, int exponent, - FloatType expected_low, FloatType expected_high, - FloatType expected_half) { - std::string low_rep = mantissa; - low_rep[low_rep.size() - 1] -= 1; - absl::StrAppend(&low_rep, std::string(1000, '9'), "e", exponent); - - FloatType actual_low = 0; - absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low); - EXPECT_EQ(expected_low, actual_low); - - std::string high_rep = - absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent); - FloatType actual_high = 0; - absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(), - actual_high); - EXPECT_EQ(expected_high, actual_high); - - std::string halfway_rep = absl::StrCat(mantissa, "e", exponent); - FloatType actual_half = 0; - absl::from_chars(halfway_rep.data(), halfway_rep.data() + halfway_rep.size(), - actual_half); - EXPECT_EQ(expected_half, actual_half); -} - -TEST(FromChars, DoubleRounding) { - const double zero = 0.0; - const double first_subnormal = nextafter(zero, 1.0); - const double second_subnormal = nextafter(first_subnormal, 1.0); - - const double first_normal = DBL_MIN; - const double last_subnormal = nextafter(first_normal, 0.0); - const double second_normal = nextafter(first_normal, 1.0); - - const double last_normal = DBL_MAX; - const double penultimate_normal = nextafter(last_normal, 0.0); - - // Various test cases for numbers between two representable floats. Each - // call to TestHalfwayValue tests a number just below and just above the - // halfway point, as well as the number exactly between them. - - // Test between zero and first_subnormal. Round-to-even tie rounds down. - TestHalfwayValue( - "2." - "470328229206232720882843964341106861825299013071623822127928412503377536" - "351043759326499181808179961898982823477228588654633283551779698981993873" - "980053909390631503565951557022639229085839244910518443593180284993653615" - "250031937045767824921936562366986365848075700158576926990370631192827955" - "855133292783433840935197801553124659726357957462276646527282722005637400" - "648549997709659947045402082816622623785739345073633900796776193057750674" - "017632467360096895134053553745851666113422376667860416215968046191446729" - "184030053005753084904876539171138659164623952491262365388187963623937328" - "042389101867234849766823508986338858792562830275599565752445550725518931" - "369083625477918694866799496832404970582102851318545139621383772282614543" - "7693412532098591327667236328125", - -324, zero, first_subnormal, zero); - - // first_subnormal and second_subnormal. Round-to-even tie rounds up. - TestHalfwayValue( - "7." - "410984687618698162648531893023320585475897039214871466383785237510132609" - "053131277979497545424539885696948470431685765963899850655339096945981621" - "940161728171894510697854671067917687257517734731555330779540854980960845" - "750095811137303474765809687100959097544227100475730780971111893578483867" - "565399878350301522805593404659373979179073872386829939581848166016912201" - "945649993128979841136206248449867871357218035220901702390328579173252022" - "052897402080290685402160661237554998340267130003581248647904138574340187" - "552090159017259254714629617513415977493871857473787096164563890871811984" - "127167305601704549300470526959016576377688490826798697257336652176556794" - "107250876433756084600398490497214911746308553955635418864151316847843631" - "3080237596295773983001708984375", - -324, first_subnormal, second_subnormal, second_subnormal); - - // last_subnormal and first_normal. Round-to-even tie rounds up. - TestHalfwayValue( - "2." - "225073858507201136057409796709131975934819546351645648023426109724822222" - "021076945516529523908135087914149158913039621106870086438694594645527657" - "207407820621743379988141063267329253552286881372149012981122451451889849" - "057222307285255133155755015914397476397983411801999323962548289017107081" - "850690630666655994938275772572015763062690663332647565300009245888316433" - "037779791869612049497390377829704905051080609940730262937128958950003583" - "799967207254304360284078895771796150945516748243471030702609144621572289" - "880258182545180325707018860872113128079512233426288368622321503775666622" - "503982534335974568884423900265498198385487948292206894721689831099698365" - "846814022854243330660339850886445804001034933970427567186443383770486037" - "86162277173854562306587467901408672332763671875", - -308, last_subnormal, first_normal, first_normal); - - // first_normal and second_normal. Round-to-even tie rounds down. - TestHalfwayValue( - "2." - "225073858507201630123055637955676152503612414573018013083228724049586647" - "606759446192036794116886953213985520549032000903434781884412325572184367" - "563347617020518175998922941393629966742598285899994830148971433555578567" - "693279306015978183162142425067962460785295885199272493577688320732492479" - "924816869232247165964934329258783950102250973957579510571600738343645738" - "494324192997092179207389919761694314131497173265255020084997973676783743" - "155205818804439163810572367791175177756227497413804253387084478193655533" - "073867420834526162513029462022730109054820067654020201547112002028139700" - "141575259123440177362244273712468151750189745559978653234255886219611516" - "335924167958029604477064946470184777360934300451421683607013647479513962" - "13837722826145437693412532098591327667236328125", - -308, first_normal, second_normal, first_normal); - - // penultimate_normal and last_normal. Round-to-even rounds down. - TestHalfwayValue( - "1." - "797693134862315608353258760581052985162070023416521662616611746258695532" - "672923265745300992879465492467506314903358770175220871059269879629062776" - "047355692132901909191523941804762171253349609463563872612866401980290377" - "995141836029815117562837277714038305214839639239356331336428021390916694" - "57927874464075218944", - 308, penultimate_normal, last_normal, penultimate_normal); -} - -// Same test cases as DoubleRounding, now with new and improved Much Smaller -// Precision! -TEST(FromChars, FloatRounding) { - const float zero = 0.0; - const float first_subnormal = nextafterf(zero, 1.0); - const float second_subnormal = nextafterf(first_subnormal, 1.0); - - const float first_normal = FLT_MIN; - const float last_subnormal = nextafterf(first_normal, 0.0); - const float second_normal = nextafterf(first_normal, 1.0); - - const float last_normal = FLT_MAX; - const float penultimate_normal = nextafterf(last_normal, 0.0); - - // Test between zero and first_subnormal. Round-to-even tie rounds down. - TestHalfwayValue( - "7." - "006492321624085354618647916449580656401309709382578858785341419448955413" - "42930300743319094181060791015625", - -46, zero, first_subnormal, zero); - - // first_subnormal and second_subnormal. Round-to-even tie rounds up. - TestHalfwayValue( - "2." - "101947696487225606385594374934874196920392912814773657635602425834686624" - "028790902229957282543182373046875", - -45, first_subnormal, second_subnormal, second_subnormal); - - // last_subnormal and first_normal. Round-to-even tie rounds up. - TestHalfwayValue( - "1." - "175494280757364291727882991035766513322858992758990427682963118425003064" - "9651730385585324256680905818939208984375", - -38, last_subnormal, first_normal, first_normal); - - // first_normal and second_normal. Round-to-even tie rounds down. - TestHalfwayValue( - "1." - "175494420887210724209590083408724842314472120785184615334540294131831453" - "9442813071445925743319094181060791015625", - -38, first_normal, second_normal, first_normal); - - // penultimate_normal and last_normal. Round-to-even rounds down. - TestHalfwayValue("3.40282336497324057985868971510891282432", 38, - penultimate_normal, last_normal, penultimate_normal); -} - -TEST(FromChars, Underflow) { - // Check that underflow is handled correctly, according to the specification - // in DR 3081. - double d; - float f; - absl::from_chars_result result; - - std::string negative_underflow = "-1e-1000"; - const char* begin = negative_underflow.data(); - const char* end = begin + negative_underflow.size(); - d = 100.0; - result = absl::from_chars(begin, end, d); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_TRUE(std::signbit(d)); // negative - EXPECT_GE(d, -std::numeric_limits<double>::min()); - f = 100.0; - result = absl::from_chars(begin, end, f); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_TRUE(std::signbit(f)); // negative - EXPECT_GE(f, -std::numeric_limits<float>::min()); - - std::string positive_underflow = "1e-1000"; - begin = positive_underflow.data(); - end = begin + positive_underflow.size(); - d = -100.0; - result = absl::from_chars(begin, end, d); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_FALSE(std::signbit(d)); // positive - EXPECT_LE(d, std::numeric_limits<double>::min()); - f = -100.0; - result = absl::from_chars(begin, end, f); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_FALSE(std::signbit(f)); // positive - EXPECT_LE(f, std::numeric_limits<float>::min()); -} - -TEST(FromChars, Overflow) { - // Check that overflow is handled correctly, according to the specification - // in DR 3081. - double d; - float f; - absl::from_chars_result result; - - std::string negative_overflow = "-1e1000"; - const char* begin = negative_overflow.data(); - const char* end = begin + negative_overflow.size(); - d = 100.0; - result = absl::from_chars(begin, end, d); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_TRUE(std::signbit(d)); // negative - EXPECT_EQ(d, -std::numeric_limits<double>::max()); - f = 100.0; - result = absl::from_chars(begin, end, f); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_TRUE(std::signbit(f)); // negative - EXPECT_EQ(f, -std::numeric_limits<float>::max()); - - std::string positive_overflow = "1e1000"; - begin = positive_overflow.data(); - end = begin + positive_overflow.size(); - d = -100.0; - result = absl::from_chars(begin, end, d); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_FALSE(std::signbit(d)); // positive - EXPECT_EQ(d, std::numeric_limits<double>::max()); - f = -100.0; - result = absl::from_chars(begin, end, f); - EXPECT_EQ(result.ptr, end); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_FALSE(std::signbit(f)); // positive - EXPECT_EQ(f, std::numeric_limits<float>::max()); -} - -TEST(FromChars, RegressionTestsFromFuzzer) { - absl::string_view src = "0x21900000p00000000099"; - float f; - auto result = absl::from_chars(src.data(), src.data() + src.size(), f); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); -} - -TEST(FromChars, ReturnValuePtr) { - // Check that `ptr` points one past the number scanned, even if that number - // is not representable. - double d; - absl::from_chars_result result; - - std::string normal = "3.14@#$%@#$%"; - result = absl::from_chars(normal.data(), normal.data() + normal.size(), d); - EXPECT_EQ(result.ec, std::errc()); - EXPECT_EQ(result.ptr - normal.data(), 4); - - std::string overflow = "1e1000@#$%@#$%"; - result = absl::from_chars(overflow.data(), - overflow.data() + overflow.size(), d); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_EQ(result.ptr - overflow.data(), 6); - - std::string garbage = "#$%@#$%"; - result = absl::from_chars(garbage.data(), - garbage.data() + garbage.size(), d); - EXPECT_EQ(result.ec, std::errc::invalid_argument); - EXPECT_EQ(result.ptr - garbage.data(), 0); -} - -// Check for a wide range of inputs that strtod() and absl::from_chars() exactly -// agree on the conversion amount. -// -// This test assumes the platform's strtod() uses perfect round_to_nearest -// rounding. -TEST(FromChars, TestVersusStrtod) { - for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) { - for (int exponent = -300; exponent < 300; ++exponent) { - std::string candidate = absl::StrCat(mantissa, "e", exponent); - double strtod_value = strtod(candidate.c_str(), nullptr); - double absl_value = 0; - absl::from_chars(candidate.data(), candidate.data() + candidate.size(), - absl_value); - ASSERT_EQ(strtod_value, absl_value) << candidate; - } - } -} - -// Check for a wide range of inputs that strtof() and absl::from_chars() exactly -// agree on the conversion amount. -// -// This test assumes the platform's strtof() uses perfect round_to_nearest -// rounding. -TEST(FromChars, TestVersusStrtof) { - for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) { - for (int exponent = -43; exponent < 32; ++exponent) { - std::string candidate = absl::StrCat(mantissa, "e", exponent); - float strtod_value = strtof(candidate.c_str(), nullptr); - float absl_value = 0; - absl::from_chars(candidate.data(), candidate.data() + candidate.size(), - absl_value); - ASSERT_EQ(strtod_value, absl_value) << candidate; - } - } -} - -// Tests if two floating point values have identical bit layouts. (EXPECT_EQ -// is not suitable for NaN testing, since NaNs are never equal.) -template <typename Float> -bool Identical(Float a, Float b) { - return 0 == memcmp(&a, &b, sizeof(Float)); -} - -// Check that NaNs are parsed correctly. The spec requires that -// std::from_chars on "NaN(123abc)" return the same value as std::nan("123abc"). -// How such an n-char-sequence affects the generated NaN is unspecified, so we -// just test for symmetry with std::nan and strtod here. -// -// (In Linux, this parses the value as a number and stuffs that number into the -// free bits of a quiet NaN.) -TEST(FromChars, NaNDoubles) { - for (std::string n_char_sequence : - {"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000", - "8000000000000", "abc123", "legal_but_unexpected", - "99999999999999999999999", "_"}) { - std::string input = absl::StrCat("nan(", n_char_sequence, ")"); - SCOPED_TRACE(input); - double from_chars_double; - absl::from_chars(input.data(), input.data() + input.size(), - from_chars_double); - double std_nan_double = std::nan(n_char_sequence.c_str()); - EXPECT_TRUE(Identical(from_chars_double, std_nan_double)); - - // Also check that we match strtod()'s behavior. This test assumes that the - // platform has a compliant strtod(). -#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY - double strtod_double = strtod(input.c_str(), nullptr); - EXPECT_TRUE(Identical(from_chars_double, strtod_double)); -#endif // ABSL_STRTOD_HANDLES_NAN_CORRECTLY - - // Check that we can parse a negative NaN - std::string negative_input = "-" + input; - double negative_from_chars_double; - absl::from_chars(negative_input.data(), - negative_input.data() + negative_input.size(), - negative_from_chars_double); - EXPECT_TRUE(std::signbit(negative_from_chars_double)); - EXPECT_FALSE(Identical(negative_from_chars_double, from_chars_double)); - from_chars_double = std::copysign(from_chars_double, -1.0); - EXPECT_TRUE(Identical(negative_from_chars_double, from_chars_double)); - } -} - -TEST(FromChars, NaNFloats) { - for (std::string n_char_sequence : - {"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000", - "8000000000000", "abc123", "legal_but_unexpected", - "99999999999999999999999", "_"}) { - std::string input = absl::StrCat("nan(", n_char_sequence, ")"); - SCOPED_TRACE(input); - float from_chars_float; - absl::from_chars(input.data(), input.data() + input.size(), - from_chars_float); - float std_nan_float = std::nanf(n_char_sequence.c_str()); - EXPECT_TRUE(Identical(from_chars_float, std_nan_float)); - - // Also check that we match strtof()'s behavior. This test assumes that the - // platform has a compliant strtof(). -#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY - float strtof_float = strtof(input.c_str(), nullptr); - EXPECT_TRUE(Identical(from_chars_float, strtof_float)); -#endif // ABSL_STRTOD_HANDLES_NAN_CORRECTLY - - // Check that we can parse a negative NaN - std::string negative_input = "-" + input; - float negative_from_chars_float; - absl::from_chars(negative_input.data(), - negative_input.data() + negative_input.size(), - negative_from_chars_float); - EXPECT_TRUE(std::signbit(negative_from_chars_float)); - EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float)); - from_chars_float = std::copysign(from_chars_float, -1.0); - EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float)); - } -} - -// Returns an integer larger than step. The values grow exponentially. -int NextStep(int step) { - return step + (step >> 2) + 1; -} - -// Test a conversion on a family of input strings, checking that the calculation -// is correct for in-bounds values, and that overflow and underflow are done -// correctly for out-of-bounds values. -// -// input_generator maps from an integer index to a string to test. -// expected_generator maps from an integer index to an expected Float value. -// from_chars conversion of input_generator(i) should result in -// expected_generator(i). -// -// lower_bound and upper_bound denote the smallest and largest values for which -// the conversion is expected to succeed. -template <typename Float> -void TestOverflowAndUnderflow( - const std::function<std::string(int)>& input_generator, - const std::function<Float(int)>& expected_generator, int lower_bound, - int upper_bound) { - // test legal values near lower_bound - int index, step; - for (index = lower_bound, step = 1; index < upper_bound; - index += step, step = NextStep(step)) { - std::string input = input_generator(index); - SCOPED_TRACE(input); - Float expected = expected_generator(index); - Float actual; - auto result = - absl::from_chars(input.data(), input.data() + input.size(), actual); - EXPECT_EQ(result.ec, std::errc()); - EXPECT_EQ(expected, actual) - << absl::StrFormat("%a vs %a", expected, actual); - } - // test legal values near upper_bound - for (index = upper_bound, step = 1; index > lower_bound; - index -= step, step = NextStep(step)) { - std::string input = input_generator(index); - SCOPED_TRACE(input); - Float expected = expected_generator(index); - Float actual; - auto result = - absl::from_chars(input.data(), input.data() + input.size(), actual); - EXPECT_EQ(result.ec, std::errc()); - EXPECT_EQ(expected, actual) - << absl::StrFormat("%a vs %a", expected, actual); - } - // Test underflow values below lower_bound - for (index = lower_bound - 1, step = 1; index > -1000000; - index -= step, step = NextStep(step)) { - std::string input = input_generator(index); - SCOPED_TRACE(input); - Float actual; - auto result = - absl::from_chars(input.data(), input.data() + input.size(), actual); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_LT(actual, 1.0); // check for underflow - } - // Test overflow values above upper_bound - for (index = upper_bound + 1, step = 1; index < 1000000; - index += step, step = NextStep(step)) { - std::string input = input_generator(index); - SCOPED_TRACE(input); - Float actual; - auto result = - absl::from_chars(input.data(), input.data() + input.size(), actual); - EXPECT_EQ(result.ec, std::errc::result_out_of_range); - EXPECT_GT(actual, 1.0); // check for overflow - } -} - -// Check that overflow and underflow are caught correctly for hex doubles. -// -// The largest representable double is 0x1.fffffffffffffp+1023, and the -// smallest representable subnormal is 0x0.0000000000001p-1022, which equals -// 0x1p-1074. Therefore 1023 and -1074 are the limits of acceptable exponents -// in this test. -TEST(FromChars, HexdecimalDoubleLimits) { - auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); }; - auto expected_gen = [](int index) { return std::ldexp(1.0, index); }; - TestOverflowAndUnderflow<double>(input_gen, expected_gen, -1074, 1023); -} - -// Check that overflow and underflow are caught correctly for hex floats. -// -// The largest representable float is 0x1.fffffep+127, and the smallest -// representable subnormal is 0x0.000002p-126, which equals 0x1p-149. -// Therefore 127 and -149 are the limits of acceptable exponents in this test. -TEST(FromChars, HexdecimalFloatLimits) { - auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); }; - auto expected_gen = [](int index) { return std::ldexp(1.0f, index); }; - TestOverflowAndUnderflow<float>(input_gen, expected_gen, -149, 127); -} - -// Check that overflow and underflow are caught correctly for decimal doubles. -// -// The largest representable double is about 1.8e308, and the smallest -// representable subnormal is about 5e-324. '1e-324' therefore rounds away from -// the smallest representable positive value. -323 and 308 are the limits of -// acceptable exponents in this test. -TEST(FromChars, DecimalDoubleLimits) { - auto input_gen = [](int index) { return absl::StrCat("1.0e", index); }; - auto expected_gen = [](int index) { return Pow10(index); }; - TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308); -} - -// Check that overflow and underflow are caught correctly for decimal floats. -// -// The largest representable float is about 3.4e38, and the smallest -// representable subnormal is about 1.45e-45. '1e-45' therefore rounds towards -// the smallest representable positive value. -45 and 38 are the limits of -// acceptable exponents in this test. -TEST(FromChars, DecimalFloatLimits) { - auto input_gen = [](int index) { return absl::StrCat("1.0e", index); }; - auto expected_gen = [](int index) { return Pow10(index); }; - TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/cord.cc b/third_party/abseil_cpp/absl/strings/cord.cc deleted file mode 100644 index 9efd13575039..000000000000 --- a/third_party/abseil_cpp/absl/strings/cord.cc +++ /dev/null @@ -1,1995 +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/cord.h" - -#include <algorithm> -#include <atomic> -#include <cstddef> -#include <cstdio> -#include <cstdlib> -#include <iomanip> -#include <iostream> -#include <limits> -#include <ostream> -#include <sstream> -#include <type_traits> -#include <unordered_set> -#include <vector> - -#include "absl/base/casts.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/container/fixed_array.h" -#include "absl/container/inlined_vector.h" -#include "absl/strings/escaping.h" -#include "absl/strings/internal/cord_internal.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_join.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -using ::absl::cord_internal::CordRep; -using ::absl::cord_internal::CordRepConcat; -using ::absl::cord_internal::CordRepExternal; -using ::absl::cord_internal::CordRepSubstring; - -using ::absl::cord_internal::CONCAT; -using ::absl::cord_internal::EXTERNAL; -using ::absl::cord_internal::FLAT; -using ::absl::cord_internal::SUBSTRING; - -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); - -// 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); -} - -static_assert(Fibonacci(63) == 6557470319842, - "Fibonacci values computed incorrectly"); - -// Minimum length required for a given depth tree -- a tree is considered -// balanced if -// length(t) >= min_length[depth(t)] -// The root node depth is allowed to become twice as large to reduce rebalancing -// for larger strings (see IsRootBalanced). -static constexpr uint64_t min_length[] = { - Fibonacci(2), Fibonacci(3), Fibonacci(4), Fibonacci(5), - Fibonacci(6), Fibonacci(7), Fibonacci(8), Fibonacci(9), - Fibonacci(10), Fibonacci(11), Fibonacci(12), Fibonacci(13), - Fibonacci(14), Fibonacci(15), Fibonacci(16), Fibonacci(17), - Fibonacci(18), Fibonacci(19), Fibonacci(20), Fibonacci(21), - Fibonacci(22), Fibonacci(23), Fibonacci(24), Fibonacci(25), - Fibonacci(26), Fibonacci(27), Fibonacci(28), Fibonacci(29), - Fibonacci(30), Fibonacci(31), Fibonacci(32), Fibonacci(33), - Fibonacci(34), Fibonacci(35), Fibonacci(36), Fibonacci(37), - Fibonacci(38), Fibonacci(39), Fibonacci(40), Fibonacci(41), - Fibonacci(42), Fibonacci(43), Fibonacci(44), Fibonacci(45), - Fibonacci(46), Fibonacci(47), - 0xffffffffffffffffull, // Avoid overflow -}; - -static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length); - -// 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->tag != CONCAT) { - return true; - } else if (node->concat()->depth() <= 15) { - return true; - } else if (node->concat()->depth() > kMinLengthSize) { - return false; - } else { - // Allow depth to become twice as large as implied by fibonacci rule to - // reduce rebalancing for larger strings. - return (node->length >= min_length[node->concat()->depth() / 2]); - } -} - -static CordRep* Rebalance(CordRep* node); -static void DumpNode(CordRep* rep, bool include_data, std::ostream* os); -static bool VerifyNode(CordRep* root, CordRep* start_node, - bool full_validation); - -static inline CordRep* VerifyTree(CordRep* node) { - // Verification is expensive, so only do it in debug mode. - // Even in debug mode we normally do only light validation. - // If you are debugging Cord itself, you should define the - // macro EXTRA_CORD_VALIDATION, e.g. by adding - // --copt=-DEXTRA_CORD_VALIDATION to the blaze line. -#ifdef EXTRA_CORD_VALIDATION - assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true)); -#else // EXTRA_CORD_VALIDATION - assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false)); -#endif // EXTRA_CORD_VALIDATION - static_cast<void>(&VerifyNode); - - return node; -} - -// -------------------------------------------------------------------- -// 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) { - 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 == EXTERNAL) { - CordRepExternal* rep_external = rep->external(); - assert(rep_external->releaser_invoker != nullptr); - rep_external->releaser_invoker(rep_external); - 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->tag == CONCAT) { - return rep->concat()->depth(); - } else { - return 0; - } -} - -static void SetConcatChildren(CordRepConcat* concat, CordRep* left, - CordRep* right) { - concat->left = left; - concat->right = right; - - concat->length = left->length + right->length; - concat->set_depth(1 + std::max(Depth(left), Depth(right))); -} - -// Create a concatenation of the specified nodes. -// Does not change the refcounts of "left" and "right". -// The returned node has a refcount of 1. -static CordRep* RawConcat(CordRep* left, CordRep* right) { - // Avoid making degenerate concat nodes (one child is empty) - if (left == nullptr || left->length == 0) { - Unref(left); - return right; - } - if (right == nullptr || right->length == 0) { - Unref(right); - return left; - } - - CordRepConcat* rep = new CordRepConcat(); - rep->tag = CONCAT; - SetConcatChildren(rep, left, right); - - return rep; -} - -static CordRep* Concat(CordRep* left, CordRep* right) { - CordRep* rep = RawConcat(left, right); - if (rep != nullptr && !IsRootBalanced(rep)) { - rep = Rebalance(rep); - } - return VerifyTree(rep); -} - -// Make a balanced tree out of an array of leaf nodes. -static CordRep* MakeBalancedTree(CordRep** reps, size_t n) { - // Make repeated passes over the array, merging adjacent pairs - // until we are left with just a single node. - while (n > 1) { - size_t dst = 0; - for (size_t src = 0; src < n; src += 2) { - if (src + 1 < n) { - reps[dst] = Concat(reps[src], reps[src + 1]); - } else { - reps[dst] = reps[src]; - } - dst++; - } - n = dst; - } - - return reps[0]; -} - -// 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; - } - - // 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) { - if (length == 0) return nullptr; - absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1); - size_t n = 0; - do { - const size_t len = std::min(length, kMaxFlatLength); - CordRep* rep = NewFlat(len + alloc_hint); - rep->length = len; - memcpy(rep->data, data, len); - reps[n++] = VerifyTree(rep); - data += len; - length -= len; - } while (length != 0); - return MakeBalancedTree(reps.data(), n); -} - -namespace cord_internal { - -void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { - assert(!data.empty()); - rep->length = data.size(); - rep->tag = EXTERNAL; - rep->base = data.data(); - VerifyTree(rep); -} - -} // namespace cord_internal - -static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) { - // Never create empty substring nodes - if (length == 0) { - Unref(child); - return nullptr; - } else { - CordRepSubstring* rep = new CordRepSubstring(); - assert((offset + length) <= child->length); - rep->length = length; - rep->tag = SUBSTRING; - rep->start = offset; - rep->child = child; - return VerifyTree(rep); - } -} - -// -------------------------------------------------------------------- -// Cord::InlineRep functions - -constexpr unsigned char Cord::InlineRep::kMaxInline; - -inline void Cord::InlineRep::set_data(const char* data, size_t n, - bool nullify_tail) { - static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15"); - - cord_internal::SmallMemmove(data_.as_chars, data, n, nullify_tail); - set_tagged_size(static_cast<char>(n)); -} - -inline char* Cord::InlineRep::set_data(size_t n) { - assert(n <= kMaxInline); - ResetToEmpty(); - set_tagged_size(static_cast<char>(n)); - return data_.as_chars; -} - -inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) { - size_t len = tagged_size(); - if (len > kMaxInline) { - return data_.as_tree.rep; - } - - CordRep* result = NewFlat(len + extra_hint); - result->length = len; - static_assert(kMinFlatLength >= sizeof(data_.as_chars), ""); - memcpy(result->data, data_.as_chars, sizeof(data_.as_chars)); - set_tree(result); - return result; -} - -inline void Cord::InlineRep::reduce_size(size_t n) { - size_t tag = tagged_size(); - assert(tag <= kMaxInline); - assert(tag >= n); - tag -= n; - memset(data_.as_chars + tag, 0, n); - set_tagged_size(static_cast<char>(tag)); -} - -inline void Cord::InlineRep::remove_prefix(size_t n) { - cord_internal::SmallMemmove(data_.as_chars, data_.as_chars + n, - tagged_size() - n); - reduce_size(n); -} - -void Cord::InlineRep::AppendTree(CordRep* tree) { - if (tree == nullptr) return; - size_t len = tagged_size(); - if (len == 0) { - set_tree(tree); - } else { - set_tree(Concat(force_tree(0), tree)); - } -} - -void Cord::InlineRep::PrependTree(CordRep* tree) { - assert(tree != nullptr); - size_t len = tagged_size(); - if (len == 0) { - set_tree(tree); - } else { - set_tree(Concat(tree, force_tree(0))); - } -} - -// Searches for a non-full flat node at the rightmost leaf of the tree. If a -// suitable leaf is found, the function will update the length field for all -// nodes to account for the size increase. The append region address will be -// written to region and the actual size increase will be written to size. -static inline bool PrepareAppendRegion(CordRep* root, char** region, - size_t* size, size_t max_length) { - // Search down the right-hand path for a non-full FLAT node. - CordRep* dst = root; - while (dst->tag == CONCAT && dst->refcount.IsOne()) { - dst = dst->concat()->right; - } - - if (dst->tag < FLAT || !dst->refcount.IsOne()) { - *region = nullptr; - *size = 0; - return false; - } - - const size_t in_use = dst->length; - const size_t capacity = TagToLength(dst->tag); - if (in_use == capacity) { - *region = nullptr; - *size = 0; - return false; - } - - size_t size_increase = std::min(capacity - in_use, max_length); - - // We need to update the length fields for all nodes, including the leaf node. - for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) { - rep->length += size_increase; - } - dst->length += size_increase; - - *region = dst->data + in_use; - *size = size_increase; - return true; -} - -void Cord::InlineRep::GetAppendRegion(char** region, size_t* size, - size_t max_length) { - if (max_length == 0) { - *region = nullptr; - *size = 0; - return; - } - - // Try to fit in the inline buffer if possible. - size_t inline_length = tagged_size(); - if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) { - *region = data_.as_chars + inline_length; - *size = max_length; - set_tagged_size(static_cast<char>(inline_length + max_length)); - return; - } - - CordRep* root = force_tree(max_length); - - if (PrepareAppendRegion(root, region, size, max_length)) { - return; - } - - // Allocate new node. - 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; - replace_tree(Concat(root, new_node)); -} - -void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) { - const size_t max_length = std::numeric_limits<size_t>::max(); - - // Try to fit in the inline buffer if possible. - size_t inline_length = tagged_size(); - if (inline_length < kMaxInline) { - *region = data_.as_chars + inline_length; - *size = kMaxInline - inline_length; - set_tagged_size(kMaxInline); - return; - } - - CordRep* root = force_tree(max_length); - - if (PrepareAppendRegion(root, region, size, max_length)) { - return; - } - - // 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->tag >= FLAT) { - *total_mem_usage += TagToAllocatedSize(rep->tag); - return true; - } - if (rep->tag == EXTERNAL) { - *total_mem_usage += sizeof(CordRepConcat) + rep->length; - return true; - } - return false; -} - -void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) { - ClearSlow(); - - data_ = src.data_; - if (is_tree()) { - Ref(tree()); - } -} - -void Cord::InlineRep::ClearSlow() { - if (is_tree()) { - Unref(tree()); - } - ResetToEmpty(); -} - -// -------------------------------------------------------------------- -// Constructors and destructors - -Cord::Cord(const Cord& src) : contents_(src.contents_) { - Ref(contents_.tree()); // Does nothing if contents_ has embedded data -} - -Cord::Cord(absl::string_view src) { - const size_t n = src.size(); - if (n <= InlineRep::kMaxInline) { - contents_.set_data(src.data(), n, false); - } else { - contents_.set_tree(NewTree(src.data(), n, 0)); - } -} - -template <typename T, Cord::EnableIfString<T>> -Cord::Cord(T&& src) { - if ( - // String is short: copy data to avoid external block overhead. - src.size() <= kMaxBytesToCopy || - // String is wasteful: copy data to avoid pinning too much unused memory. - src.size() < src.capacity() / 2 - ) { - if (src.size() <= InlineRep::kMaxInline) { - contents_.set_data(src.data(), src.size(), false); - } else { - contents_.set_tree(NewTree(src.data(), src.size(), 0)); - } - } else { - struct StringReleaser { - void operator()(absl::string_view /* data */) {} - std::string data; - }; - const absl::string_view original_data = src; - auto* rep = static_cast< - ::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>( - absl::cord_internal::NewExternalRep( - original_data, StringReleaser{std::forward<T>(src)})); - // Moving src may have invalidated its data pointer, so adjust it. - rep->base = rep->template get<0>().data.data(); - contents_.set_tree(rep); - } -} - -template Cord::Cord(std::string&& src); - -// The destruction code is separate so that the compiler can determine -// that it does not need to call the destructor on a moved-from Cord. -void Cord::DestroyCordSlow() { - Unref(VerifyTree(contents_.tree())); -} - -// -------------------------------------------------------------------- -// Mutators - -void Cord::Clear() { - Unref(contents_.clear()); -} - -Cord& Cord::operator=(absl::string_view src) { - - const char* data = src.data(); - size_t length = src.size(); - CordRep* tree = contents_.tree(); - if (length <= InlineRep::kMaxInline) { - // Embed into this->contents_ - contents_.set_data(data, length, true); - Unref(tree); - return *this; - } - 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; -} - -template <typename T, Cord::EnableIfString<T>> -Cord& Cord::operator=(T&& src) { - if (src.size() <= kMaxBytesToCopy) { - *this = absl::string_view(src); - } else { - *this = Cord(std::forward<T>(src)); - } - return *this; -} - -template Cord& Cord::operator=(std::string&& src); - -// TODO(sanjay): Move to Cord::InlineRep section of file. For now, -// we keep it here to make diffs easier. -void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) { - if (src_size == 0) return; // memcpy(_, nullptr, 0) is undefined. - // Try to fit in the inline buffer if possible. - size_t inline_length = tagged_size(); - if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) { - // Append new data to embedded array - set_tagged_size(static_cast<char>(inline_length + src_size)); - memcpy(data_.as_chars + inline_length, src_data, src_size); - return; - } - - CordRep* root = tree(); - - size_t appended = 0; - if (root) { - char* region; - if (PrepareAppendRegion(root, ®ion, &appended, src_size)) { - memcpy(region, src_data, appended); - } - } else { - // 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_.as_chars, 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; - } - - // Use new block(s) for any remaining bytes that were not handled above. - // Alloc extra memory only if the right child of the root of the new tree is - // going to be a FLAT node, which will permit further inplace appends. - size_t length = src_size; - if (src_size < kMaxFlatLength) { - // The new length is either - // - old size + 10% - // - old_size + src_size - // This will cause a reasonable conservative step-up in size that is still - // large enough to avoid excessive amounts of small fragments being added. - length = std::max<size_t>(root->length / 10, src_size); - } - set_tree(Concat(root, NewTree(src_data, src_size, length - src_size))); -} - -inline CordRep* Cord::TakeRep() const& { - return Ref(contents_.tree()); -} - -inline CordRep* Cord::TakeRep() && { - CordRep* rep = contents_.tree(); - contents_.clear(); - return rep; -} - -template <typename C> -inline void Cord::AppendImpl(C&& src) { - if (empty()) { - // In case of an empty destination avoid allocating a new node, do not copy - // data. - *this = std::forward<C>(src); - return; - } - - // For short cords, it is faster to copy data if there is room in dst. - const size_t src_size = src.contents_.size(); - if (src_size <= kMaxBytesToCopy) { - CordRep* src_tree = src.contents_.tree(); - if (src_tree == nullptr) { - // src has embedded data. - contents_.AppendArray(src.contents_.data(), src_size); - return; - } - if (src_tree->tag >= FLAT) { - // src tree just has one flat node. - contents_.AppendArray(src_tree->data, src_size); - return; - } - if (&src == this) { - // ChunkIterator below assumes that src is not modified during traversal. - Append(Cord(src)); - return; - } - // TODO(mec): Should we only do this if "dst" has space? - for (absl::string_view chunk : src.Chunks()) { - Append(chunk); - } - return; - } - - contents_.AppendTree(std::forward<C>(src).TakeRep()); -} - -void Cord::Append(const Cord& src) { AppendImpl(src); } - -void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); } - -template <typename T, Cord::EnableIfString<T>> -void Cord::Append(T&& src) { - if (src.size() <= kMaxBytesToCopy) { - Append(absl::string_view(src)); - } else { - Append(Cord(std::forward<T>(src))); - } -} - -template void Cord::Append(std::string&& src); - -void Cord::Prepend(const Cord& src) { - CordRep* src_tree = src.contents_.tree(); - if (src_tree != nullptr) { - Ref(src_tree); - contents_.PrependTree(src_tree); - return; - } - - // `src` cord is inlined. - absl::string_view src_contents(src.contents_.data(), src.contents_.size()); - return Prepend(src_contents); -} - -void Cord::Prepend(absl::string_view src) { - if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined. - 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 { - contents_.PrependTree(NewTree(src.data(), src.size(), 0)); - } -} - -template <typename T, Cord::EnableIfString<T>> -inline void Cord::Prepend(T&& src) { - if (src.size() <= kMaxBytesToCopy) { - Prepend(absl::string_view(src)); - } else { - Prepend(Cord(std::forward<T>(src))); - } -} - -template void Cord::Prepend(std::string&& src); - -static CordRep* RemovePrefixFrom(CordRep* node, size_t n) { - if (n >= node->length) return nullptr; - if (n == 0) return Ref(node); - absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack; - - while (node->tag == CONCAT) { - assert(n <= node->length); - if (n < node->concat()->left->length) { - // Push right to stack, descend left. - rhs_stack.push_back(node->concat()->right); - node = node->concat()->left; - } else { - // Drop left, descend right. - n -= node->concat()->left->length; - node = node->concat()->right; - } - } - assert(n <= node->length); - - if (n == 0) { - Ref(node); - } else { - size_t start = n; - size_t len = node->length - n; - if (node->tag == SUBSTRING) { - // Consider in-place update of node, similar to in RemoveSuffixFrom(). - start += node->substring()->start; - node = node->substring()->child; - } - node = NewSubstring(Ref(node), start, len); - } - while (!rhs_stack.empty()) { - node = Concat(node, Ref(rhs_stack.back())); - rhs_stack.pop_back(); - } - return node; -} - -// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the -// exception that removing a suffix has an optimization where a node may be -// edited in place iff that node and all its ancestors have a refcount of 1. -static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) { - if (n >= node->length) return nullptr; - if (n == 0) return Ref(node); - absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack; - bool inplace_ok = node->refcount.IsOne(); - - while (node->tag == CONCAT) { - assert(n <= node->length); - if (n < node->concat()->right->length) { - // Push left to stack, descend right. - lhs_stack.push_back(node->concat()->left); - node = node->concat()->right; - } else { - // Drop right, descend left. - n -= node->concat()->right->length; - node = node->concat()->left; - } - inplace_ok = inplace_ok && node->refcount.IsOne(); - } - assert(n <= node->length); - - if (n == 0) { - 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. - Ref(node); - node->length -= n; - } else { - size_t start = 0; - size_t len = node->length - n; - if (node->tag == SUBSTRING) { - start = node->substring()->start; - node = node->substring()->child; - } - node = NewSubstring(Ref(node), start, len); - } - while (!lhs_stack.empty()) { - node = Concat(Ref(lhs_stack.back()), node); - lhs_stack.pop_back(); - } - return node; -} - -void Cord::RemovePrefix(size_t n) { - ABSL_INTERNAL_CHECK(n <= size(), - absl::StrCat("Requested prefix size ", n, - " exceeds Cord's size ", size())); - CordRep* tree = contents_.tree(); - if (tree == nullptr) { - contents_.remove_prefix(n); - } else { - CordRep* newrep = RemovePrefixFrom(tree, n); - Unref(tree); - contents_.replace_tree(VerifyTree(newrep)); - } -} - -void Cord::RemoveSuffix(size_t n) { - ABSL_INTERNAL_CHECK(n <= size(), - absl::StrCat("Requested suffix size ", n, - " exceeds Cord's size ", size())); - CordRep* tree = contents_.tree(); - if (tree == nullptr) { - contents_.reduce_size(n); - } else { - CordRep* newrep = RemoveSuffixFrom(tree, n); - Unref(tree); - contents_.replace_tree(VerifyTree(newrep)); - } -} - -// Work item for NewSubRange(). -struct SubRange { - SubRange(CordRep* a_node, size_t a_pos, size_t a_n) - : node(a_node), pos(a_pos), n(a_n) {} - CordRep* node; // nullptr means concat last 2 results. - size_t pos; - size_t n; -}; - -static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) { - absl::InlinedVector<CordRep*, kInlinedVectorSize> results; - absl::InlinedVector<SubRange, kInlinedVectorSize> todo; - todo.push_back(SubRange(node, pos, n)); - do { - const SubRange& sr = todo.back(); - node = sr.node; - pos = sr.pos; - n = sr.n; - todo.pop_back(); - - if (node == nullptr) { - assert(results.size() >= 2); - CordRep* right = results.back(); - results.pop_back(); - CordRep* left = results.back(); - results.pop_back(); - results.push_back(Concat(left, right)); - } else if (pos == 0 && n == node->length) { - results.push_back(Ref(node)); - } else if (node->tag != CONCAT) { - if (node->tag == SUBSTRING) { - pos += node->substring()->start; - node = node->substring()->child; - } - 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) { - pos -= node->concat()->left->length; - todo.push_back(SubRange(node->concat()->right, pos, n)); - } else { - size_t left_n = node->concat()->left->length - pos; - todo.push_back(SubRange(nullptr, 0, 0)); // Concat() - todo.push_back(SubRange(node->concat()->right, 0, n - left_n)); - todo.push_back(SubRange(node->concat()->left, pos, left_n)); - } - } while (!todo.empty()); - assert(results.size() == 1); - return results[0]; -} - -Cord Cord::Subcord(size_t pos, size_t new_size) const { - Cord sub_cord; - size_t length = size(); - if (pos > length) pos = length; - if (new_size > length - pos) new_size = length - pos; - CordRep* tree = contents_.tree(); - if (tree == nullptr) { - // sub_cord is newly constructed, no need to re-zero-out the tail of - // contents_ memory. - sub_cord.contents_.set_data(contents_.data() + pos, new_size, false); - } else if (new_size == 0) { - // We want to return empty subcord, so nothing to do. - } else if (new_size <= InlineRep::kMaxInline) { - Cord::ChunkIterator it = chunk_begin(); - it.AdvanceBytes(pos); - char* dest = sub_cord.contents_.data_.as_chars; - size_t remaining_size = new_size; - while (remaining_size > it->size()) { - cord_internal::SmallMemmove(dest, it->data(), it->size()); - remaining_size -= it->size(); - dest += it->size(); - ++it; - } - cord_internal::SmallMemmove(dest, it->data(), remaining_size); - sub_cord.contents_.set_tagged_size(new_size); - } else { - sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size)); - } - return sub_cord; -} - -// -------------------------------------------------------------------- -// Balancing - -class CordForest { - public: - explicit CordForest(size_t length) - : root_length_(length), trees_(kMinLengthSize, nullptr) {} - - void Build(CordRep* cord_root) { - std::vector<CordRep*> pending = {cord_root}; - - while (!pending.empty()) { - CordRep* node = pending.back(); - pending.pop_back(); - CheckNode(node); - if (ABSL_PREDICT_FALSE(node->tag != CONCAT)) { - AddNode(node); - continue; - } - - CordRepConcat* concat_node = node->concat(); - if (concat_node->depth() >= kMinLengthSize || - concat_node->length < min_length[concat_node->depth()]) { - pending.push_back(concat_node->right); - pending.push_back(concat_node->left); - - if (concat_node->refcount.IsOne()) { - concat_node->left = concat_freelist_; - concat_freelist_ = concat_node; - } else { - Ref(concat_node->right); - Ref(concat_node->left); - Unref(concat_node); - } - } else { - AddNode(node); - } - } - } - - CordRep* ConcatNodes() { - CordRep* sum = nullptr; - for (auto* node : trees_) { - if (node == nullptr) continue; - - sum = PrependNode(node, sum); - root_length_ -= node->length; - if (root_length_ == 0) break; - } - ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node"); - return VerifyTree(sum); - } - - private: - CordRep* AppendNode(CordRep* node, CordRep* sum) { - return (sum == nullptr) ? node : MakeConcat(sum, node); - } - - CordRep* PrependNode(CordRep* node, CordRep* sum) { - return (sum == nullptr) ? node : MakeConcat(node, sum); - } - - void AddNode(CordRep* node) { - CordRep* sum = nullptr; - - // Collect together everything with which we will merge with node - int i = 0; - for (; node->length > min_length[i + 1]; ++i) { - auto& tree_at_i = trees_[i]; - - if (tree_at_i == nullptr) continue; - sum = PrependNode(tree_at_i, sum); - tree_at_i = nullptr; - } - - sum = AppendNode(node, sum); - - // Insert sum into appropriate place in the forest - for (; sum->length >= min_length[i]; ++i) { - auto& tree_at_i = trees_[i]; - if (tree_at_i == nullptr) continue; - - sum = MakeConcat(tree_at_i, sum); - tree_at_i = nullptr; - } - - // min_length[0] == 1, which means sum->length >= min_length[0] - assert(i > 0); - trees_[i - 1] = sum; - } - - // Make concat node trying to resue existing CordRepConcat nodes we - // already collected in the concat_freelist_. - CordRep* MakeConcat(CordRep* left, CordRep* right) { - if (concat_freelist_ == nullptr) return RawConcat(left, right); - - CordRepConcat* rep = concat_freelist_; - if (concat_freelist_->left == nullptr) { - concat_freelist_ = nullptr; - } else { - concat_freelist_ = concat_freelist_->left->concat(); - } - SetConcatChildren(rep, left, right); - - return rep; - } - - static void CheckNode(CordRep* node) { - ABSL_INTERNAL_CHECK(node->length != 0u, ""); - if (node->tag == CONCAT) { - ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, ""); - ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, ""); - ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length + - node->concat()->right->length), - ""); - } - } - - size_t root_length_; - - // use an inlined vector instead of a flat array to get bounds checking - absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_; - - // List of concat nodes we can re-use for Cord balancing. - CordRepConcat* concat_freelist_ = nullptr; -}; - -static CordRep* Rebalance(CordRep* node) { - VerifyTree(node); - assert(node->tag == CONCAT); - - if (node->length == 0) { - return nullptr; - } - - CordForest forest(node->length); - forest.Build(node); - return forest.ConcatNodes(); -} - -// -------------------------------------------------------------------- -// Comparators - -namespace { - -int ClampResult(int memcmp_res) { - return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0); -} - -int CompareChunks(absl::string_view* lhs, absl::string_view* rhs, - size_t* size_to_compare) { - size_t compared_size = std::min(lhs->size(), rhs->size()); - assert(*size_to_compare >= compared_size); - *size_to_compare -= compared_size; - - int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size); - if (memcmp_res != 0) return memcmp_res; - - lhs->remove_prefix(compared_size); - rhs->remove_prefix(compared_size); - - return 0; -} - -// This overload set computes comparison results from memcmp result. This -// interface is used inside GenericCompare below. Differet implementations -// are specialized for int and bool. For int we clamp result to {-1, 0, 1} -// set. For bool we just interested in "value == 0". -template <typename ResultType> -ResultType ComputeCompareResult(int memcmp_res) { - return ClampResult(memcmp_res); -} -template <> -bool ComputeCompareResult<bool>(int memcmp_res) { - return memcmp_res == 0; -} - -} // namespace - -// Helper routine. Locates the first flat chunk of the Cord without -// initializing the iterator. -inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const { - size_t n = tagged_size(); - if (n <= kMaxInline) { - return absl::string_view(data_.as_chars, n); - } - - CordRep* node = tree(); - if (node->tag >= FLAT) { - return absl::string_view(node->data, node->length); - } - - if (node->tag == EXTERNAL) { - return absl::string_view(node->external()->base, node->length); - } - - // Walk down the left branches until we hit a non-CONCAT node. - while (node->tag == CONCAT) { - node = node->concat()->left; - } - - // Get the child node if we encounter a SUBSTRING. - size_t offset = 0; - size_t length = node->length; - assert(length != 0); - - if (node->tag == SUBSTRING) { - offset = node->substring()->start; - node = node->substring()->child; - } - - if (node->tag >= FLAT) { - return absl::string_view(node->data + offset, length); - } - - assert((node->tag == EXTERNAL) && "Expect FLAT or EXTERNAL node here"); - - return absl::string_view(node->external()->base + offset, length); -} - -inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, - size_t size_to_compare) const { - auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { - if (!chunk->empty()) return true; - ++*it; - if (it->bytes_remaining_ == 0) return false; - *chunk = **it; - return true; - }; - - Cord::ChunkIterator lhs_it = chunk_begin(); - - // compared_size is inside first chunk. - absl::string_view lhs_chunk = - (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view(); - assert(compared_size <= lhs_chunk.size()); - assert(compared_size <= rhs.size()); - lhs_chunk.remove_prefix(compared_size); - rhs.remove_prefix(compared_size); - size_to_compare -= compared_size; // skip already compared size. - - while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) { - int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare); - if (comparison_result != 0) return comparison_result; - if (size_to_compare == 0) return 0; - } - - return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty()); -} - -inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size, - size_t size_to_compare) const { - auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { - if (!chunk->empty()) return true; - ++*it; - if (it->bytes_remaining_ == 0) return false; - *chunk = **it; - return true; - }; - - Cord::ChunkIterator lhs_it = chunk_begin(); - Cord::ChunkIterator rhs_it = rhs.chunk_begin(); - - // compared_size is inside both first chunks. - absl::string_view lhs_chunk = - (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view(); - absl::string_view rhs_chunk = - (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view(); - assert(compared_size <= lhs_chunk.size()); - assert(compared_size <= rhs_chunk.size()); - lhs_chunk.remove_prefix(compared_size); - rhs_chunk.remove_prefix(compared_size); - size_to_compare -= compared_size; // skip already compared size. - - while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) { - int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare); - if (memcmp_res != 0) return memcmp_res; - if (size_to_compare == 0) return 0; - } - - return static_cast<int>(rhs_chunk.empty()) - - static_cast<int>(lhs_chunk.empty()); -} - -inline absl::string_view Cord::GetFirstChunk(const Cord& c) { - return c.contents_.FindFlatStartPiece(); -} -inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) { - return sv; -} - -// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed -// that 'size_to_compare' is greater that size of smallest of first chunks. -template <typename ResultType, typename RHS> -ResultType GenericCompare(const Cord& lhs, const RHS& rhs, - size_t size_to_compare) { - absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs); - absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs); - - size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size()); - assert(size_to_compare >= compared_size); - int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size); - if (compared_size == size_to_compare || memcmp_res != 0) { - return ComputeCompareResult<ResultType>(memcmp_res); - } - - return ComputeCompareResult<ResultType>( - lhs.CompareSlowPath(rhs, compared_size, size_to_compare)); -} - -bool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const { - return GenericCompare<bool>(*this, rhs, size_to_compare); -} - -bool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const { - return GenericCompare<bool>(*this, rhs, size_to_compare); -} - -template <typename RHS> -inline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) { - size_t lhs_size = lhs.size(); - size_t rhs_size = rhs.size(); - if (lhs_size == rhs_size) { - return GenericCompare<int>(lhs, rhs, lhs_size); - } - if (lhs_size < rhs_size) { - auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size); - return data_comp_res == 0 ? -1 : data_comp_res; - } - - auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size); - return data_comp_res == 0 ? +1 : data_comp_res; -} - -int Cord::Compare(absl::string_view rhs) const { - return SharedCompareImpl(*this, rhs); -} - -int Cord::CompareImpl(const Cord& rhs) const { - return SharedCompareImpl(*this, rhs); -} - -bool Cord::EndsWith(absl::string_view rhs) const { - size_t my_size = size(); - size_t rhs_size = rhs.size(); - - if (my_size < rhs_size) return false; - - Cord tmp(*this); - tmp.RemovePrefix(my_size - rhs_size); - return tmp.EqualsImpl(rhs, rhs_size); -} - -bool Cord::EndsWith(const Cord& rhs) const { - size_t my_size = size(); - size_t rhs_size = rhs.size(); - - if (my_size < rhs_size) return false; - - Cord tmp(*this); - tmp.RemovePrefix(my_size - rhs_size); - return tmp.EqualsImpl(rhs, rhs_size); -} - -// -------------------------------------------------------------------- -// Misc. - -Cord::operator std::string() const { - std::string s; - absl::CopyCordToString(*this, &s); - return s; -} - -void CopyCordToString(const Cord& src, std::string* dst) { - if (!src.contents_.is_tree()) { - src.contents_.CopyTo(dst); - } else { - absl::strings_internal::STLStringResizeUninitialized(dst, src.size()); - src.CopyToArraySlowPath(&(*dst)[0]); - } -} - -void Cord::CopyToArraySlowPath(char* dst) const { - assert(contents_.is_tree()); - absl::string_view fragment; - if (GetFlatAux(contents_.tree(), &fragment)) { - memcpy(dst, fragment.data(), fragment.size()); - return; - } - for (absl::string_view chunk : Chunks()) { - memcpy(dst, chunk.data(), chunk.size()); - dst += chunk.size(); - } -} - -Cord::ChunkIterator& Cord::ChunkIterator::operator++() { - ABSL_HARDENING_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(); - - // Walk down the left branches until we hit a non-CONCAT node. Save the - // right children to the stack for subsequent traversal. - while (node->tag == CONCAT) { - stack_of_right_children_.push_back(node->concat()->right); - node = node->concat()->left; - } - - // Get the child node if we encounter a SUBSTRING. - size_t offset = 0; - size_t length = node->length; - if (node->tag == SUBSTRING) { - offset = node->substring()->start; - node = node->substring()->child; - } - - assert(node->tag == EXTERNAL || node->tag >= FLAT); - assert(length != 0); - const char* data = - node->tag == EXTERNAL ? node->external()->base : node->data; - current_chunk_ = absl::string_view(data + offset, length); - current_leaf_ = node; - return *this; -} - -Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) { - ABSL_HARDENING_ASSERT(bytes_remaining_ >= n && - "Attempted to iterate past `end()`"); - Cord subcord; - - if (n <= InlineRep::kMaxInline) { - // Range to read fits in inline data. Flatten it. - char* data = subcord.contents_.set_data(n); - while (n > current_chunk_.size()) { - memcpy(data, current_chunk_.data(), current_chunk_.size()); - data += current_chunk_.size(); - n -= current_chunk_.size(); - ++*this; - } - memcpy(data, current_chunk_.data(), n); - if (n < current_chunk_.size()) { - RemoveChunkPrefix(n); - } else if (n > 0) { - ++*this; - } - return subcord; - } - if (n < current_chunk_.size()) { - // Range to read is a proper subrange of the current chunk. - assert(current_leaf_ != nullptr); - 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_.set_tree(VerifyTree(subnode)); - RemoveChunkPrefix(n); - return subcord; - } - - // Range to read begins with a proper subrange of the current chunk. - assert(!current_chunk_.empty()); - assert(current_leaf_ != nullptr); - CordRep* subnode = Ref(current_leaf_); - if (current_chunk_.size() < subnode->length) { - const char* data = - subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data; - subnode = NewSubstring(subnode, current_chunk_.data() - data, - current_chunk_.size()); - } - n -= current_chunk_.size(); - bytes_remaining_ -= current_chunk_.size(); - - // Process the next node(s) on the stack, reading whole subtrees depending on - // their length and how many bytes we are advancing. - CordRep* node = nullptr; - while (!stack_of_right_children_.empty()) { - node = stack_of_right_children_.back(); - stack_of_right_children_.pop_back(); - if (node->length > n) break; - // TODO(qrczak): This might unnecessarily recreate existing concat nodes. - // Avoiding that would need pretty complicated logic (instead of - // current_leaf_, keep current_subtree_ which points to the highest node - // such that the current leaf can be found on the path of left children - // starting from current_subtree_; delay creating subnode while node is - // below current_subtree_; find the proper node along the path of left - // children starting from current_subtree_ if this loop exits while staying - // below current_subtree_; etc.; alternatively, push parents instead of - // right children on the stack). - subnode = Concat(subnode, Ref(node)); - n -= node->length; - bytes_remaining_ -= node->length; - node = nullptr; - } - - if (node == nullptr) { - // We have reached the end of the Cord. - assert(bytes_remaining_ == 0); - subcord.contents_.set_tree(VerifyTree(subnode)); - return subcord; - } - - // Walk down the appropriate branches until we hit a non-CONCAT node. Save the - // right children to the stack for subsequent traversal. - while (node->tag == CONCAT) { - if (node->concat()->left->length > n) { - // Push right, descend left. - stack_of_right_children_.push_back(node->concat()->right); - node = node->concat()->left; - } else { - // Read left, descend right. - subnode = Concat(subnode, Ref(node->concat()->left)); - n -= node->concat()->left->length; - bytes_remaining_ -= node->concat()->left->length; - node = node->concat()->right; - } - } - - // Get the child node if we encounter a SUBSTRING. - size_t offset = 0; - size_t length = node->length; - if (node->tag == SUBSTRING) { - offset = node->substring()->start; - node = node->substring()->child; - } - - // Range to read ends with a proper (possibly empty) subrange of the current - // chunk. - assert(node->tag == EXTERNAL || node->tag >= FLAT); - assert(length > n); - if (n > 0) subnode = Concat(subnode, NewSubstring(Ref(node), offset, n)); - const char* 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_.set_tree(VerifyTree(subnode)); - return subcord; -} - -void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) { - assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`"); - assert(n >= current_chunk_.size()); // This should only be called when - // iterating to a new node. - - n -= current_chunk_.size(); - bytes_remaining_ -= current_chunk_.size(); - - // 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; - while (!stack_of_right_children_.empty()) { - node = stack_of_right_children_.back(); - stack_of_right_children_.pop_back(); - if (node->length > n) break; - n -= node->length; - bytes_remaining_ -= node->length; - node = nullptr; - } - - if (node == nullptr) { - // We have reached the end of the Cord. - assert(bytes_remaining_ == 0); - return; - } - - // Walk down the appropriate branches until we hit a non-CONCAT node. Save the - // right children to the stack for subsequent traversal. - while (node->tag == CONCAT) { - if (node->concat()->left->length > n) { - // Push right, descend left. - stack_of_right_children_.push_back(node->concat()->right); - node = node->concat()->left; - } else { - // Skip left, descend right. - n -= node->concat()->left->length; - bytes_remaining_ -= node->concat()->left->length; - node = node->concat()->right; - } - } - - // Get the child node if we encounter a SUBSTRING. - size_t offset = 0; - size_t length = node->length; - if (node->tag == SUBSTRING) { - offset = node->substring()->start; - node = node->substring()->child; - } - - assert(node->tag == EXTERNAL || node->tag >= FLAT); - assert(length > n); - const char* data = - node->tag == EXTERNAL ? node->external()->base : node->data; - current_chunk_ = absl::string_view(data + offset + n, length - n); - current_leaf_ = node; - bytes_remaining_ -= n; -} - -char Cord::operator[](size_t i) const { - ABSL_HARDENING_ASSERT(i < size()); - size_t offset = i; - const CordRep* rep = contents_.tree(); - if (rep == nullptr) { - return contents_.data()[i]; - } - while (true) { - assert(rep != nullptr); - assert(offset < rep->length); - if (rep->tag >= FLAT) { - // Get the "i"th character directly from the flat array. - return rep->data[offset]; - } else if (rep->tag == EXTERNAL) { - // Get the "i"th character from the external array. - return rep->external()->base[offset]; - } else if (rep->tag == CONCAT) { - // Recursively branch to the side of the concatenation that the "i"th - // character is on. - size_t left_length = rep->concat()->left->length; - if (offset < left_length) { - rep = rep->concat()->left; - } else { - offset -= left_length; - rep = rep->concat()->right; - } - } else { - // This must be a substring a node, so bypass it to get to the child. - assert(rep->tag == SUBSTRING); - offset += rep->substring()->start; - rep = rep->substring()->child; - } - } -} - -absl::string_view Cord::FlattenSlowPath() { - size_t total_size = size(); - CordRep* new_rep; - char* new_buffer; - - // Try to put the contents into a new flat rep. If they won't fit in the - // biggest possible flat node, use an external rep instead. - if (total_size <= kMaxFlatLength) { - new_rep = NewFlat(total_size); - new_rep->length = total_size; - new_buffer = new_rep->data; - CopyToArraySlowPath(new_buffer); - } else { - new_buffer = std::allocator<char>().allocate(total_size); - CopyToArraySlowPath(new_buffer); - new_rep = absl::cord_internal::NewExternalRep( - absl::string_view(new_buffer, total_size), [](absl::string_view s) { - std::allocator<char>().deallocate(const_cast<char*>(s.data()), - s.size()); - }); - } - 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->tag >= FLAT) { - *fragment = absl::string_view(rep->data, rep->length); - return true; - } else if (rep->tag == EXTERNAL) { - *fragment = absl::string_view(rep->external()->base, rep->length); - return true; - } else if (rep->tag == SUBSTRING) { - CordRep* child = rep->substring()->child; - if (child->tag >= FLAT) { - *fragment = - absl::string_view(child->data + rep->substring()->start, rep->length); - return true; - } else if (child->tag == EXTERNAL) { - *fragment = absl::string_view( - child->external()->base + rep->substring()->start, rep->length); - return true; - } - } - return false; -} - -/* static */ void Cord::ForEachChunkAux( - absl::cord_internal::CordRep* rep, - absl::FunctionRef<void(absl::string_view)> callback) { - assert(rep != nullptr); - int stack_pos = 0; - constexpr int stack_max = 128; - // Stack of right branches for tree traversal - absl::cord_internal::CordRep* stack[stack_max]; - absl::cord_internal::CordRep* current_node = rep; - while (true) { - if (current_node->tag == CONCAT) { - if (stack_pos == stack_max) { - // There's no more room on our stack array to add another right branch, - // and the idea is to avoid allocations, so call this function - // recursively to navigate this subtree further. (This is not something - // we expect to happen in practice). - ForEachChunkAux(current_node, callback); - - // Pop the next right branch and iterate. - current_node = stack[--stack_pos]; - continue; - } else { - // Save the right branch for later traversal and continue down the left - // branch. - stack[stack_pos++] = current_node->concat()->right; - current_node = current_node->concat()->left; - continue; - } - } - // This is a leaf node, so invoke our callback. - absl::string_view chunk; - bool success = GetFlatAux(current_node, &chunk); - assert(success); - if (success) { - callback(chunk); - } - if (stack_pos == 0) { - // end of traversal - return; - } - current_node = stack[--stack_pos]; - } -} - -static void DumpNode(CordRep* rep, bool include_data, std::ostream* os) { - const int kIndentStep = 1; - int indent = 0; - absl::InlinedVector<CordRep*, kInlinedVectorSize> stack; - absl::InlinedVector<int, kInlinedVectorSize> indents; - for (;;) { - *os << std::setw(3) << rep->refcount.Get(); - *os << " " << std::setw(7) << rep->length; - *os << " ["; - if (include_data) *os << static_cast<void*>(rep); - *os << "]"; - *os << " " << (IsRootBalanced(rep) ? 'b' : 'u'); - *os << " " << std::setw(indent) << ""; - if (rep->tag == CONCAT) { - *os << "CONCAT depth=" << Depth(rep) << "\n"; - indent += kIndentStep; - indents.push_back(indent); - stack.push_back(rep->concat()->right); - rep = rep->concat()->left; - } else if (rep->tag == SUBSTRING) { - *os << "SUBSTRING @ " << rep->substring()->start << "\n"; - indent += kIndentStep; - rep = rep->substring()->child; - } else { // Leaf - if (rep->tag == EXTERNAL) { - *os << "EXTERNAL ["; - if (include_data) - *os << absl::CEscape(std::string(rep->external()->base, rep->length)); - *os << "]\n"; - } else { - *os << "FLAT cap=" << TagToLength(rep->tag) << " ["; - if (include_data) - *os << absl::CEscape(std::string(rep->data, rep->length)); - *os << "]\n"; - } - if (stack.empty()) break; - rep = stack.back(); - stack.pop_back(); - indent = indents.back(); - indents.pop_back(); - } - } - ABSL_INTERNAL_CHECK(indents.empty(), ""); -} - -static std::string ReportError(CordRep* root, CordRep* node) { - std::ostringstream buf; - buf << "Error at node " << node << " in:"; - DumpNode(root, true, &buf); - return buf.str(); -} - -static bool VerifyNode(CordRep* root, CordRep* start_node, - bool full_validation) { - absl::InlinedVector<CordRep*, 2> worklist; - worklist.push_back(start_node); - do { - CordRep* node = worklist.back(); - worklist.pop_back(); - - ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node)); - if (node != root) { - ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node)); - } - - if (node->tag == CONCAT) { - ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, - ReportError(root, node)); - ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, - ReportError(root, node)); - ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length + - node->concat()->right->length), - ReportError(root, node)); - if (full_validation) { - worklist.push_back(node->concat()->right); - worklist.push_back(node->concat()->left); - } - } else if (node->tag >= FLAT) { - ABSL_INTERNAL_CHECK(node->length <= TagToLength(node->tag), - ReportError(root, node)); - } else if (node->tag == EXTERNAL) { - ABSL_INTERNAL_CHECK(node->external()->base != nullptr, - ReportError(root, node)); - } else if (node->tag == SUBSTRING) { - ABSL_INTERNAL_CHECK( - node->substring()->start < node->substring()->child->length, - ReportError(root, node)); - ABSL_INTERNAL_CHECK(node->substring()->start + node->length <= - node->substring()->child->length, - ReportError(root, node)); - } - } while (!worklist.empty()); - return true; -} - -// Traverses the tree and computes the total memory allocated. -/* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) { - size_t total_mem_usage = 0; - - // Allow a quick exit for the common case that the root is a leaf. - if (RepMemoryUsageLeaf(rep, &total_mem_usage)) { - return total_mem_usage; - } - - // Iterate over the tree. cur_node is never a leaf node and leaf nodes will - // never be appended to tree_stack. This reduces overhead from manipulating - // tree_stack. - absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack; - const CordRep* cur_node = rep; - while (true) { - const CordRep* next_node = nullptr; - - if (cur_node->tag == CONCAT) { - total_mem_usage += sizeof(CordRepConcat); - const CordRep* left = cur_node->concat()->left; - if (!RepMemoryUsageLeaf(left, &total_mem_usage)) { - next_node = left; - } - - const CordRep* right = cur_node->concat()->right; - if (!RepMemoryUsageLeaf(right, &total_mem_usage)) { - if (next_node) { - tree_stack.push_back(next_node); - } - next_node = right; - } - } else { - // Since cur_node is not a leaf or a concat node it must be a substring. - assert(cur_node->tag == SUBSTRING); - total_mem_usage += sizeof(CordRepSubstring); - next_node = cur_node->substring()->child; - if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) { - next_node = nullptr; - } - } - - if (!next_node) { - if (tree_stack.empty()) { - return total_mem_usage; - } - next_node = tree_stack.back(); - tree_stack.pop_back(); - } - cur_node = next_node; - } -} - -std::ostream& operator<<(std::ostream& out, const Cord& cord) { - for (absl::string_view chunk : cord.Chunks()) { - out.write(chunk.data(), chunk.size()); - } - return out; -} - -namespace strings_internal { -size_t CordTestAccess::FlatOverhead() { return kFlatOverhead; } -size_t CordTestAccess::MaxFlatLength() { return kMaxFlatLength; } -size_t CordTestAccess::FlatTagToLength(uint8_t tag) { - return TagToLength(tag); -} -uint8_t CordTestAccess::LengthToTag(size_t s) { - ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s)); - return AllocatedSizeToTag(s + kFlatOverhead); -} -size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); } -size_t CordTestAccess::SizeofCordRepExternal() { - return sizeof(CordRepExternal); -} -size_t CordTestAccess::SizeofCordRepSubstring() { - return sizeof(CordRepSubstring); -} -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/cord.h b/third_party/abseil_cpp/absl/strings/cord.h deleted file mode 100644 index 5d5c897e663c..000000000000 --- a/third_party/abseil_cpp/absl/strings/cord.h +++ /dev/null @@ -1,1299 +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: 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 accomodate data that changes over its -// lifetime, though it's not quite "mutable"; it can change only in the -// attachment, detachment, or rearrangement of chunks of its constituent data. -// -// A Cord provides some benefit over `std::string` under the following (albeit -// narrow) circumstances: -// -// * Cord data is designed to grow and shrink over a Cord's lifetime. Cord -// provides efficient insertions and deletions at the start and end of the -// character sequences, avoiding copies in those cases. Static data should -// generally be stored as strings. -// * External memory consisting of string-like data can be directly added to -// a Cord without requiring copies or allocations. -// * Cord data may be shared and copied cheaply. Cord provides a copy-on-write -// implementation and cheap sub-Cord operations. Copying a Cord is an O(1) -// operation. -// -// As a consequence to the above, Cord data is generally large. Small data -// should generally use strings, as construction of a Cord requires some -// overhead. Small Cords (<= 15 bytes) are represented inline, but most small -// Cords are expected to grow over their lifetimes. -// -// Note that because a Cord is made up of separate chunked data, random access -// to character data within a Cord is slower than within a `std::string`. -// -// Thread Safety -// -// Cord has the same thread-safety properties as many other types like -// std::string, std::vector<>, int, etc -- it is thread-compatible. In -// particular, if threads do not call non-const methods, then it is safe to call -// const methods without synchronization. Copying a Cord produces a new instance -// that can be used concurrently with the original in arbitrary ways. - -#ifndef ABSL_STRINGS_CORD_H_ -#define ABSL_STRINGS_CORD_H_ - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <iosfwd> -#include <iterator> -#include <string> -#include <type_traits> - -#include "absl/base/internal/endian.h" -#include "absl/base/internal/per_thread_tls.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/container/inlined_vector.h" -#include "absl/functional/function_ref.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/internal/cord_internal.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/internal/string_constant.h" -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -class Cord; -class CordTestPeer; -template <typename Releaser> -Cord MakeCordFromExternal(absl::string_view, Releaser&&); -void CopyCordToString(const Cord& src, std::string* dst); - -// Cord -// -// A Cord is a sequence of characters, designed to be more efficient than a -// `std::string` in certain circumstances: namely, large string data that needs -// to change over its lifetime or shared, especially when such data is shared -// across API boundaries. -// -// A Cord stores its character data in a structure that allows efficient prepend -// and append operations. This makes a Cord useful for large string data sent -// over in a wire format that may need to be prepended or appended at some point -// during the data exchange (e.g. HTTP, protocol buffers). For example, a -// Cord is useful for storing an HTTP request, and prepending an HTTP header to -// such a request. -// -// Cords should not be used for storing general string data, however. They -// require overhead to construct and are slower than strings for random access. -// -// The Cord API provides the following common API operations: -// -// * Create or assign Cords out of existing string data, memory, or other Cords -// * Append and prepend data to an existing Cord -// * Create new Sub-Cords from existing Cord data -// * Swap Cord data and compare Cord equality -// * Write out Cord data by constructing a `std::string` -// -// Additionally, the API provides iterator utilities to iterate through Cord -// data via chunks or character bytes. -// -class Cord { - private: - template <typename T> - using EnableIfString = - absl::enable_if_t<std::is_same<T, std::string>::value, int>; - - public: - // Cord::Cord() Constructors. - - // Creates an empty Cord. - constexpr Cord() noexcept; - - // Creates a Cord from an existing Cord. Cord is copyable and efficiently - // movable. The moved-from state is valid but unspecified. - Cord(const Cord& src); - Cord(Cord&& src) noexcept; - Cord& operator=(const Cord& x); - Cord& operator=(Cord&& x) noexcept; - - // Creates a Cord from a `src` string. This constructor is marked explicit to - // prevent implicit Cord constructions from arguments convertible to an - // `absl::string_view`. - explicit Cord(absl::string_view src); - Cord& operator=(absl::string_view src); - - // Creates a Cord from a `std::string&&` rvalue. These constructors are - // templated to avoid ambiguities for types that are convertible to both - // `absl::string_view` and `std::string`, such as `const char*`. - template <typename T, EnableIfString<T> = 0> - explicit Cord(T&& src); - template <typename T, EnableIfString<T> = 0> - Cord& operator=(T&& src); - - // Cord::~Cord() - // - // Destructs the Cord. - ~Cord() { - if (contents_.is_tree()) DestroyCordSlow(); - } - - // MakeCordFromExternal() - // - // Creates a Cord that takes ownership of external string memory. The - // contents of `data` are not copied to the Cord; instead, the external - // memory is added to the Cord and reference-counted. This data may not be - // changed for the life of the Cord, though it may be prepended or appended - // to. - // - // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when - // the reference count for `data` reaches zero. As noted above, this data must - // remain live until the releaser is invoked. The callable releaser also must: - // - // * be move constructible - // * support `void operator()(absl::string_view) const` or `void operator()` - // - // Example: - // - // Cord MakeCord(BlockPool* pool) { - // Block* block = pool->NewBlock(); - // FillBlock(block); - // return absl::MakeCordFromExternal( - // block->ToStringView(), - // [pool, block](absl::string_view v) { - // pool->FreeBlock(block, v); - // }); - // } - // - // WARNING: Because a Cord can be reference-counted, it's likely a bug if your - // releaser doesn't do anything. For example, consider the following: - // - // void Foo(const char* buffer, int len) { - // auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len), - // [](absl::string_view) {}); - // - // // BUG: If Bar() copies its cord for any reason, including keeping a - // // substring of it, the lifetime of buffer might be extended beyond - // // when Foo() returns. - // Bar(c); - // } - template <typename Releaser> - friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser); - - // Cord::Clear() - // - // Releases the Cord data. Any nodes that share data with other Cords, if - // applicable, will have their reference counts reduced by 1. - void Clear(); - - // Cord::Append() - // - // Appends data to the Cord, which may come from another Cord or other string - // data. - void Append(const Cord& src); - void Append(Cord&& src); - void Append(absl::string_view src); - template <typename T, EnableIfString<T> = 0> - void Append(T&& src); - - // Cord::Prepend() - // - // Prepends data to the Cord, which may come from another Cord or other string - // data. - void Prepend(const Cord& src); - void Prepend(absl::string_view src); - template <typename T, EnableIfString<T> = 0> - void Prepend(T&& src); - - // Cord::RemovePrefix() - // - // Removes the first `n` bytes of a Cord. - void RemovePrefix(size_t n); - void RemoveSuffix(size_t n); - - // Cord::Subcord() - // - // Returns a new Cord representing the subrange [pos, pos + new_size) of - // *this. If pos >= size(), the result is empty(). If - // (pos + new_size) >= size(), the result is the subrange [pos, size()). - Cord Subcord(size_t pos, size_t new_size) const; - - // Cord::swap() - // - // Swaps the contents of the Cord with `other`. - void swap(Cord& other) noexcept; - - // swap() - // - // Swaps the contents of two Cords. - friend void swap(Cord& x, Cord& y) noexcept { - x.swap(y); - } - - // Cord::size() - // - // Returns the size of the Cord. - size_t size() const; - - // Cord::empty() - // - // Determines whether the given Cord is empty, returning `true` is so. - bool empty() const; - - // Cord::EstimatedMemoryUsage() - // - // Returns the *approximate* number of bytes held in full or in part by this - // Cord (which may not remain the same between invocations). Note that Cords - // that share memory could each be "charged" independently for the same shared - // memory. - size_t EstimatedMemoryUsage() const; - - // Cord::Compare() - // - // Compares 'this' Cord with rhs. This function and its relatives treat Cords - // as sequences of unsigned bytes. The comparison is a straightforward - // lexicographic comparison. `Cord::Compare()` returns values as follows: - // - // -1 'this' Cord is smaller - // 0 two Cords are equal - // 1 'this' Cord is larger - int Compare(absl::string_view rhs) const; - int Compare(const Cord& rhs) const; - - // Cord::StartsWith() - // - // Determines whether the Cord starts with the passed string data `rhs`. - bool StartsWith(const Cord& rhs) const; - bool StartsWith(absl::string_view rhs) const; - - // Cord::EndsWidth() - // - // Determines whether the Cord ends with the passed string data `rhs`. - bool EndsWith(absl::string_view rhs) const; - bool EndsWith(const Cord& rhs) const; - - // Cord::operator std::string() - // - // Converts a Cord into a `std::string()`. This operator is marked explicit to - // prevent unintended Cord usage in functions that take a string. - explicit operator std::string() const; - - // CopyCordToString() - // - // Copies the contents of a `src` Cord into a `*dst` string. - // - // This function optimizes the case of reusing the destination string since it - // can reuse previously allocated capacity. However, this function does not - // guarantee that pointers previously returned by `dst->data()` remain valid - // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new - // object, prefer to simply use the conversion operator to `std::string`. - friend void CopyCordToString(const Cord& src, std::string* dst); - - class CharIterator; - - //---------------------------------------------------------------------------- - // Cord::ChunkIterator - //---------------------------------------------------------------------------- - // - // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its - // Cord. Such iteration allows you to perform non-const operatons on the data - // of a Cord without modifying it. - // - // Generally, you do not instantiate a `Cord::ChunkIterator` directly; - // instead, you create one implicitly through use of the `Cord::Chunks()` - // member function. - // - // The `Cord::ChunkIterator` has the following properties: - // - // * The iterator is invalidated after any non-const operation on the - // Cord object over which it iterates. - // * The `string_view` returned by dereferencing a valid, non-`end()` - // iterator is guaranteed to be non-empty. - // * Two `ChunkIterator` objects can be compared equal if and only if they - // remain valid and iterate over the same Cord. - // * The iterator in this case is a proxy iterator; the `string_view` - // returned by the iterator does not live inside the Cord, and its - // lifetime is limited to the lifetime of the iterator itself. To help - // prevent lifetime issues, `ChunkIterator::reference` is not a true - // reference type and is equivalent to `value_type`. - // * The iterator keeps state that can grow for Cords that contain many - // nodes and are imbalanced due to sharing. Prefer to pass this type by - // const reference instead of by value. - class ChunkIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = absl::string_view; - using difference_type = ptrdiff_t; - using pointer = const value_type*; - using reference = value_type; - - ChunkIterator() = default; - - ChunkIterator& operator++(); - ChunkIterator operator++(int); - bool operator==(const ChunkIterator& other) const; - bool operator!=(const ChunkIterator& other) const; - reference operator*() const; - pointer operator->() const; - - friend class Cord; - friend class CharIterator; - - private: - // Constructs a `begin()` iterator from `cord`. - explicit ChunkIterator(const Cord* cord); - - // 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); - // Iterates `n` bytes, where `n` is expected to be greater than or equal to - // `current_chunk_.size()`. - void AdvanceBytesSlowPath(size_t n); - - // A view into bytes of the current `CordRep`. It may only be a view to a - // suffix of bytes if this is being used by `CharIterator`. - absl::string_view current_chunk_; - // The current leaf, or `nullptr` if the iterator points to short data. - // If the current chunk is a substring node, current_leaf_ points to the - // underlying flat or external node. - absl::cord_internal::CordRep* current_leaf_ = nullptr; - // The number of bytes left in the `Cord` over which we are iterating. - size_t bytes_remaining_ = 0; - 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. - // - // Example: - // - // absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c, - // absl::string_view s) { - // return std::find(c.chunk_begin(), c.chunk_end(), s); - // } - ChunkIterator chunk_begin() const; - - // Cord::ChunkItertator::chunk_end() - // - // Returns an iterator one increment past the last chunk of the `Cord`. - // - // Generally, prefer using `Cord::Chunks()` within a range-based for loop for - // iterating over the chunks of a Cord. This method may be useful for getting - // a `ChunkIterator` where range-based for-loops may not be available. - ChunkIterator chunk_end() const; - - //---------------------------------------------------------------------------- - // Cord::ChunkIterator::ChunkRange - //---------------------------------------------------------------------------- - // - // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`, - // producing an iterator which can be used within a range-based for loop. - // Construction of a `ChunkRange` will return an iterator pointing to the - // first chunk of the Cord. Generally, do not construct a `ChunkRange` - // directly; instead, prefer to use the `Cord::Chunks()` method. - // - // Implementation note: `ChunkRange` is simply a convenience wrapper over - // `Cord::chunk_begin()` and `Cord::chunk_end()`. - class ChunkRange { - public: - explicit ChunkRange(const Cord* cord) : cord_(cord) {} - - ChunkIterator begin() const; - ChunkIterator end() const; - - private: - const Cord* cord_; - }; - - // Cord::Chunks() - // - // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks - // of a `Cord` with a range-based for-loop. For most iteration tasks on a - // Cord, use `Cord::Chunks()` to retrieve this iterator. - // - // Example: - // - // void ProcessChunks(const Cord& cord) { - // for (absl::string_view chunk : cord.Chunks()) { ... } - // } - // - // Note that the ordinary caveats of temporary lifetime extension apply: - // - // void Process() { - // for (absl::string_view chunk : CordFactory().Chunks()) { - // // The temporary Cord returned by CordFactory has been destroyed! - // } - // } - ChunkRange Chunks() const; - - //---------------------------------------------------------------------------- - // Cord::CharIterator - //---------------------------------------------------------------------------- - // - // A `Cord::CharIterator` allows iteration over the constituent characters of - // a `Cord`. - // - // Generally, you do not instantiate a `Cord::CharIterator` directly; instead, - // you create one implicitly through use of the `Cord::Chars()` member - // function. - // - // A `Cord::CharIterator` has the following properties: - // - // * The iterator is invalidated after any non-const operation on the - // Cord object over which it iterates. - // * Two `CharIterator` objects can be compared equal if and only if they - // remain valid and iterate over the same Cord. - // * The iterator keeps state that can grow for Cords that contain many - // nodes and are imbalanced due to sharing. Prefer to pass this type by - // const reference instead of by value. - // * This type cannot act as a forward iterator because a `Cord` can reuse - // sections of memory. This fact violates the requirement for forward - // iterators to compare equal if dereferencing them returns the same - // object. - class CharIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = char; - using difference_type = ptrdiff_t; - using pointer = const char*; - using reference = const char&; - - CharIterator() = default; - - CharIterator& operator++(); - CharIterator operator++(int); - bool operator==(const CharIterator& other) const; - bool operator!=(const CharIterator& other) const; - reference operator*() const; - pointer operator->() const; - - friend Cord; - - private: - explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {} - - ChunkIterator chunk_iterator_; - }; - - // Cord::CharIterator::AdvanceAndRead() - // - // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes - // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the - // number of bytes within the Cord; otherwise, behavior is undefined. It is - // valid to pass `char_end()` and `0`. - static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes); - - // Cord::CharIterator::Advance() - // - // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than - // or equal to the number of bytes remaining within the Cord; otherwise, - // behavior is undefined. It is valid to pass `char_end()` and `0`. - static void Advance(CharIterator* it, size_t n_bytes); - - // Cord::CharIterator::ChunkRemaining() - // - // Returns the longest contiguous view starting at the iterator's position. - // - // `it` must be dereferenceable. - static absl::string_view ChunkRemaining(const CharIterator& it); - - // Cord::CharIterator::char_begin() - // - // Returns an iterator to the first character of the `Cord`. - // - // Generally, prefer using `Cord::Chars()` within a range-based for loop for - // iterating over the chunks of a Cord. This method may be useful for getting - // a `CharIterator` where range-based for-loops may not be available. - CharIterator char_begin() const; - - // Cord::CharIterator::char_end() - // - // Returns an iterator to one past the last character of the `Cord`. - // - // Generally, prefer using `Cord::Chars()` within a range-based for loop for - // iterating over the chunks of a Cord. This method may be useful for getting - // a `CharIterator` where range-based for-loops are not useful. - CharIterator char_end() const; - - // Cord::CharIterator::CharRange - // - // `CharRange` is a helper class for iterating over the characters of a - // producing an iterator which can be used within a range-based for loop. - // Construction of a `CharRange` will return an iterator pointing to the first - // character of the Cord. Generally, do not construct a `CharRange` directly; - // instead, prefer to use the `Cord::Chars()` method show below. - // - // Implementation note: `CharRange` is simply a convenience wrapper over - // `Cord::char_begin()` and `Cord::char_end()`. - class CharRange { - public: - explicit CharRange(const Cord* cord) : cord_(cord) {} - - CharIterator begin() const; - CharIterator end() const; - - private: - const Cord* cord_; - }; - - // Cord::CharIterator::Chars() - // - // Returns a `Cord::CharIterator` for iterating over the characters of a - // `Cord` with a range-based for-loop. For most character-based iteration - // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator. - // - // Example: - // - // void ProcessCord(const Cord& cord) { - // for (char c : cord.Chars()) { ... } - // } - // - // Note that the ordinary caveats of temporary lifetime extension apply: - // - // void Process() { - // for (char c : CordFactory().Chars()) { - // // The temporary Cord returned by CordFactory has been destroyed! - // } - // } - CharRange Chars() const; - - // Cord::operator[] - // - // Gets the "i"th character of the Cord and returns it, provided that - // 0 <= i < Cord.size(). - // - // NOTE: This routine is reasonably efficient. It is roughly - // logarithmic based on the number of chunks that make up the cord. Still, - // if you need to iterate over the contents of a cord, you should - // use a CharIterator/ChunkIterator rather than call operator[] or Get() - // repeatedly in a loop. - char operator[](size_t i) const; - - // Cord::TryFlat() - // - // If this cord's representation is a single flat array, returns a - // string_view referencing that array. Otherwise returns nullopt. - absl::optional<absl::string_view> TryFlat() const; - - // Cord::Flatten() - // - // Flattens the cord into a single array and returns a view of the data. - // - // If the cord was already flat, the contents are not modified. - absl::string_view Flatten(); - - // Supports absl::Cord as a sink object for absl::Format(). - friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) { - cord->Append(part); - } - - template <typename H> - friend H AbslHashValue(H hash_state, const absl::Cord& c) { - absl::optional<absl::string_view> maybe_flat = c.TryFlat(); - if (maybe_flat.has_value()) { - return H::combine(std::move(hash_state), *maybe_flat); - } - return c.HashFragmented(std::move(hash_state)); - } - - // Create a Cord with the contents of StringConstant<T>::value. - // No allocations will be done and no data will be copied. - // This is an INTERNAL API and subject to change or removal. This API can only - // be used by spelling absl::strings_internal::MakeStringConstant, which is - // also an internal API. - template <typename T> - explicit constexpr Cord(strings_internal::StringConstant<T>); - - private: - friend class CordTestPeer; - friend bool operator==(const Cord& lhs, const Cord& rhs); - friend bool operator==(const Cord& lhs, absl::string_view rhs); - - // Calls the provided function once for each cord chunk, in order. Unlike - // Chunks(), this API will not allocate memory. - void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const; - - // Allocates new contiguous storage for the contents of the cord. This is - // called by Flatten() when the cord was not already flat. - absl::string_view FlattenSlowPath(); - - // Actual cord contents are hidden inside the following simple - // class so that we can isolate the bulk of cord.cc from changes - // to the representation. - // - // InlineRep holds either a tree pointer, or an array of kMaxInline bytes. - class InlineRep { - public: - static constexpr unsigned char kMaxInline = cord_internal::kMaxInline; - static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), ""); - static constexpr unsigned char kTreeFlag = cord_internal::kTreeFlag; - static constexpr unsigned char kProfiledFlag = cord_internal::kProfiledFlag; - - constexpr InlineRep() : data_() {} - InlineRep(const InlineRep& src); - InlineRep(InlineRep&& src); - InlineRep& operator=(const InlineRep& src); - InlineRep& operator=(InlineRep&& src) noexcept; - - explicit constexpr InlineRep(cord_internal::InlineData data); - - void Swap(InlineRep* rhs); - bool empty() const; - size_t size() const; - const char* data() const; // Returns nullptr if holding pointer - void set_data(const char* data, size_t n, - bool nullify_tail); // Discards pointer, if any - char* set_data(size_t n); // Write data to the result - // Returns nullptr if holding bytes - absl::cord_internal::CordRep* tree() const; - // Discards old pointer, if any - void set_tree(absl::cord_internal::CordRep* rep); - // Replaces a tree with a new root. This is faster than set_tree, but it - // should only be used when it's clear that the old rep was a tree. - void replace_tree(absl::cord_internal::CordRep* rep); - // Returns non-null iff was holding a pointer - absl::cord_internal::CordRep* clear(); - // Converts to pointer if necessary. - absl::cord_internal::CordRep* force_tree(size_t extra_hint); - void reduce_size(size_t n); // REQUIRES: holding data - void remove_prefix(size_t n); // REQUIRES: holding data - void AppendArray(const char* src_data, size_t src_size); - absl::string_view FindFlatStartPiece() const; - void AppendTree(absl::cord_internal::CordRep* tree); - void PrependTree(absl::cord_internal::CordRep* tree); - void GetAppendRegion(char** region, size_t* size, size_t max_length); - void GetAppendRegion(char** region, size_t* size); - bool IsSame(const InlineRep& other) const { - return memcmp(&data_, &other.data_, sizeof(data_)) == 0; - } - int BitwiseCompare(const InlineRep& other) const { - uint64_t x, y; - // Use memcpy to avoid aliasing issues. - memcpy(&x, &data_, sizeof(x)); - memcpy(&y, &other.data_, sizeof(y)); - if (x == y) { - memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x)); - memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y)); - if (x == y) return 0; - } - return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y) - ? -1 - : 1; - } - void CopyTo(std::string* dst) const { - // memcpy is much faster when operating on a known size. On most supported - // platforms, the small string optimization is large enough that resizing - // to 15 bytes does not cause a memory allocation. - absl::strings_internal::STLStringResizeUninitialized(dst, - sizeof(data_) - 1); - memcpy(&(*dst)[0], &data_, sizeof(data_) - 1); - // erase is faster than resize because the logic for memory allocation is - // not needed. - dst->erase(tagged_size()); - } - - // Copies the inline contents into `dst`. Assumes the cord is not empty. - void CopyToArray(char* dst) const; - - bool is_tree() const { return tagged_size() > kMaxInline; } - - private: - friend class Cord; - - void AssignSlow(const InlineRep& src); - // Unrefs the tree, stops profiling, and zeroes the contents - void ClearSlow(); - - void ResetToEmpty() { data_ = {}; } - - // This uses reinterpret_cast instead of the union to avoid accessing the - // inactive union element. The tagged size is not a common prefix. - void set_tagged_size(char new_tag) { - reinterpret_cast<char*>(&data_)[kMaxInline] = new_tag; - } - char tagged_size() const { - return reinterpret_cast<const char*>(&data_)[kMaxInline]; - } - - cord_internal::InlineData data_; - }; - InlineRep contents_; - - // Helper for MemoryUsage(). - static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep); - - // Helper for GetFlat() and TryFlat(). - static bool GetFlatAux(absl::cord_internal::CordRep* rep, - absl::string_view* fragment); - - // Helper for ForEachChunk(). - static void ForEachChunkAux( - absl::cord_internal::CordRep* rep, - absl::FunctionRef<void(absl::string_view)> callback); - - // The destructor for non-empty Cords. - void DestroyCordSlow(); - - // Out-of-line implementation of slower parts of logic. - void CopyToArraySlowPath(char* dst) const; - int CompareSlowPath(absl::string_view rhs, size_t compared_size, - size_t size_to_compare) const; - int CompareSlowPath(const Cord& rhs, size_t compared_size, - size_t size_to_compare) const; - bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const; - bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const; - int CompareImpl(const Cord& rhs) const; - - template <typename ResultType, typename RHS> - friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs, - size_t size_to_compare); - static absl::string_view GetFirstChunk(const Cord& c); - static absl::string_view GetFirstChunk(absl::string_view sv); - - // Returns a new reference to contents_.tree(), or steals an existing - // reference if called on an rvalue. - absl::cord_internal::CordRep* TakeRep() const&; - absl::cord_internal::CordRep* TakeRep() &&; - - // Helper for Append(). - template <typename C> - void AppendImpl(C&& src); - - // Helper for AbslHashValue(). - template <typename H> - H HashFragmented(H hash_state) const { - typename H::AbslInternalPiecewiseCombiner combiner; - ForEachChunk([&combiner, &hash_state](absl::string_view chunk) { - hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(), - chunk.size()); - }); - return H::combine(combiner.finalize(std::move(hash_state)), size()); - } -}; - -ABSL_NAMESPACE_END -} // namespace absl - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// allow a Cord to be logged -extern std::ostream& operator<<(std::ostream& out, const Cord& cord); - -// ------------------------------------------------------------------ -// Internal details follow. Clients should ignore. - -namespace cord_internal { - -// Fast implementation of memmove for up to 15 bytes. This implementation is -// safe for overlapping regions. If nullify_tail is true, the destination is -// padded with '\0' up to 16 bytes. -inline void SmallMemmove(char* dst, const char* src, size_t n, - bool nullify_tail = false) { - if (n >= 8) { - assert(n <= 16); - uint64_t buf1; - uint64_t buf2; - memcpy(&buf1, src, 8); - memcpy(&buf2, src + n - 8, 8); - if (nullify_tail) { - memset(dst + 8, 0, 8); - } - memcpy(dst, &buf1, 8); - memcpy(dst + n - 8, &buf2, 8); - } else if (n >= 4) { - uint32_t buf1; - uint32_t buf2; - memcpy(&buf1, src, 4); - memcpy(&buf2, src + n - 4, 4); - if (nullify_tail) { - memset(dst + 4, 0, 4); - memset(dst + 8, 0, 8); - } - memcpy(dst, &buf1, 4); - memcpy(dst + n - 4, &buf2, 4); - } else { - if (n != 0) { - dst[0] = src[0]; - dst[n / 2] = src[n / 2]; - dst[n - 1] = src[n - 1]; - } - if (nullify_tail) { - memset(dst + 8, 0, 8); - memset(dst + n, 0, 8); - } - } -} - -// Does non-template-specific `CordRepExternal` initialization. -// Expects `data` to be non-empty. -void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep); - -// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer -// to it, or `nullptr` if `data` was empty. -template <typename Releaser> -// NOLINTNEXTLINE - suppress clang-tidy raw pointer return. -CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { - using ReleaserType = absl::decay_t<Releaser>; - if (data.empty()) { - // Never create empty external nodes. - InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)), - data); - return nullptr; - } - - CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>( - std::forward<Releaser>(releaser), 0); - InitializeCordRepExternal(data, rep); - return rep; -} - -// Overload for function reference types that dispatches using a function -// pointer because there are no `alignof()` or `sizeof()` a function reference. -// NOLINTNEXTLINE - suppress clang-tidy raw pointer return. -inline CordRep* NewExternalRep(absl::string_view data, - void (&releaser)(absl::string_view)) { - return NewExternalRep(data, &releaser); -} - -} // namespace cord_internal - -template <typename Releaser> -Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) { - Cord cord; - cord.contents_.set_tree(::absl::cord_internal::NewExternalRep( - data, std::forward<Releaser>(releaser))); - return cord; -} - -constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data) - : data_(data) {} - -inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) { - data_ = src.data_; -} - -inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) { - data_ = src.data_; - src.ResetToEmpty(); -} - -inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) { - if (this == &src) { - return *this; - } - if (!is_tree() && !src.is_tree()) { - data_ = src.data_; - return *this; - } - AssignSlow(src); - return *this; -} - -inline Cord::InlineRep& Cord::InlineRep::operator=( - Cord::InlineRep&& src) noexcept { - if (is_tree()) { - ClearSlow(); - } - data_ = src.data_; - src.ResetToEmpty(); - return *this; -} - -inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) { - if (rhs == this) { - return; - } - - std::swap(data_, rhs->data_); -} - -inline const char* Cord::InlineRep::data() const { - return is_tree() ? nullptr : data_.as_chars; -} - -inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const { - if (is_tree()) { - return data_.as_tree.rep; - } else { - return nullptr; - } -} - -inline bool Cord::InlineRep::empty() const { return tagged_size() == 0; } - -inline size_t Cord::InlineRep::size() const { - const char tag = tagged_size(); - if (tag <= kMaxInline) return tag; - return static_cast<size_t>(tree()->length); -} - -inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) { - if (rep == nullptr) { - ResetToEmpty(); - } else { - bool was_tree = is_tree(); - data_.as_tree = {rep, {}, tagged_size()}; - if (!was_tree) { - // If we were not a tree already, set the tag. - // Otherwise, leave it alone because it might have the profile bit on. - set_tagged_size(kTreeFlag); - } - } -} - -inline void Cord::InlineRep::replace_tree(absl::cord_internal::CordRep* rep) { - ABSL_ASSERT(is_tree()); - if (ABSL_PREDICT_FALSE(rep == nullptr)) { - set_tree(rep); - return; - } - data_.as_tree = {rep, {}, tagged_size()}; -} - -inline absl::cord_internal::CordRep* Cord::InlineRep::clear() { - absl::cord_internal::CordRep* result = tree(); - ResetToEmpty(); - return result; -} - -inline void Cord::InlineRep::CopyToArray(char* dst) const { - assert(!is_tree()); - size_t n = tagged_size(); - assert(n != 0); - cord_internal::SmallMemmove(dst, data_.as_chars, n); -} - -constexpr inline Cord::Cord() noexcept {} - -template <typename T> -constexpr Cord::Cord(strings_internal::StringConstant<T>) - : contents_(strings_internal::StringConstant<T>::value.size() <= - cord_internal::kMaxInline - ? cord_internal::InlineData( - strings_internal::StringConstant<T>::value) - : cord_internal::InlineData(cord_internal::AsTree{ - &cord_internal::ConstInitExternalStorage< - strings_internal::StringConstant<T>>::value, - {}, - cord_internal::kTreeFlag})) {} - -inline Cord& Cord::operator=(const Cord& x) { - contents_ = x.contents_; - return *this; -} - -inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {} - -inline void Cord::swap(Cord& other) noexcept { - contents_.Swap(&other.contents_); -} - -inline Cord& Cord::operator=(Cord&& x) noexcept { - contents_ = std::move(x.contents_); - return *this; -} - -extern template Cord::Cord(std::string&& src); -extern template Cord& Cord::operator=(std::string&& src); - -inline size_t Cord::size() const { - // Length is 1st field in str.rep_ - return contents_.size(); -} - -inline bool Cord::empty() const { return contents_.empty(); } - -inline size_t Cord::EstimatedMemoryUsage() const { - size_t result = sizeof(Cord); - if (const absl::cord_internal::CordRep* rep = contents_.tree()) { - result += MemoryUsageAux(rep); - } - return result; -} - -inline absl::optional<absl::string_view> Cord::TryFlat() const { - absl::cord_internal::CordRep* rep = contents_.tree(); - if (rep == nullptr) { - return absl::string_view(contents_.data(), contents_.size()); - } - absl::string_view fragment; - if (GetFlatAux(rep, &fragment)) { - return fragment; - } - return absl::nullopt; -} - -inline absl::string_view Cord::Flatten() { - absl::cord_internal::CordRep* rep = contents_.tree(); - if (rep == nullptr) { - return absl::string_view(contents_.data(), contents_.size()); - } else { - absl::string_view already_flat_contents; - if (GetFlatAux(rep, &already_flat_contents)) { - return already_flat_contents; - } - } - return FlattenSlowPath(); -} - -inline void Cord::Append(absl::string_view src) { - contents_.AppendArray(src.data(), src.size()); -} - -extern template void Cord::Append(std::string&& src); -extern template void Cord::Prepend(std::string&& src); - -inline int Cord::Compare(const Cord& rhs) const { - if (!contents_.is_tree() && !rhs.contents_.is_tree()) { - return contents_.BitwiseCompare(rhs.contents_); - } - - return CompareImpl(rhs); -} - -// Does 'this' cord start/end with rhs -inline bool Cord::StartsWith(const Cord& rhs) const { - if (contents_.IsSame(rhs.contents_)) return true; - size_t rhs_size = rhs.size(); - if (size() < rhs_size) return false; - return EqualsImpl(rhs, rhs_size); -} - -inline bool Cord::StartsWith(absl::string_view rhs) const { - size_t rhs_size = rhs.size(); - if (size() < rhs_size) return false; - return EqualsImpl(rhs, rhs_size); -} - -inline Cord::ChunkIterator::ChunkIterator(const Cord* cord) - : bytes_remaining_(cord->size()) { - if (cord->empty()) return; - if (cord->contents_.is_tree()) { - stack_of_right_children_.push_back(cord->contents_.tree()); - operator++(); - } else { - current_chunk_ = absl::string_view(cord->contents_.data(), cord->size()); - } -} - -inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) { - ChunkIterator tmp(*this); - operator++(); - return tmp; -} - -inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const { - return bytes_remaining_ == other.bytes_remaining_; -} - -inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const { - return !(*this == other); -} - -inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const { - ABSL_HARDENING_ASSERT(bytes_remaining_ != 0); - return current_chunk_; -} - -inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const { - ABSL_HARDENING_ASSERT(bytes_remaining_ != 0); - return ¤t_chunk_; -} - -inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) { - assert(n < current_chunk_.size()); - current_chunk_.remove_prefix(n); - bytes_remaining_ -= n; -} - -inline void Cord::ChunkIterator::AdvanceBytes(size_t n) { - if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) { - RemoveChunkPrefix(n); - } else if (n != 0) { - AdvanceBytesSlowPath(n); - } -} - -inline Cord::ChunkIterator Cord::chunk_begin() const { - return ChunkIterator(this); -} - -inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); } - -inline Cord::ChunkIterator Cord::ChunkRange::begin() const { - return cord_->chunk_begin(); -} - -inline Cord::ChunkIterator Cord::ChunkRange::end() const { - return cord_->chunk_end(); -} - -inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); } - -inline Cord::CharIterator& Cord::CharIterator::operator++() { - if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) { - chunk_iterator_.RemoveChunkPrefix(1); - } else { - ++chunk_iterator_; - } - return *this; -} - -inline Cord::CharIterator Cord::CharIterator::operator++(int) { - CharIterator tmp(*this); - operator++(); - return tmp; -} - -inline bool Cord::CharIterator::operator==(const CharIterator& other) const { - return chunk_iterator_ == other.chunk_iterator_; -} - -inline bool Cord::CharIterator::operator!=(const CharIterator& other) const { - return !(*this == other); -} - -inline Cord::CharIterator::reference Cord::CharIterator::operator*() const { - return *chunk_iterator_->data(); -} - -inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const { - return chunk_iterator_->data(); -} - -inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) { - assert(it != nullptr); - return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes); -} - -inline void Cord::Advance(CharIterator* it, size_t n_bytes) { - assert(it != nullptr); - it->chunk_iterator_.AdvanceBytes(n_bytes); -} - -inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) { - return *it.chunk_iterator_; -} - -inline Cord::CharIterator Cord::char_begin() const { - return CharIterator(this); -} - -inline Cord::CharIterator Cord::char_end() const { return CharIterator(); } - -inline Cord::CharIterator Cord::CharRange::begin() const { - return cord_->char_begin(); -} - -inline Cord::CharIterator Cord::CharRange::end() const { - return cord_->char_end(); -} - -inline Cord::CharRange Cord::Chars() const { return CharRange(this); } - -inline void Cord::ForEachChunk( - absl::FunctionRef<void(absl::string_view)> callback) const { - absl::cord_internal::CordRep* rep = contents_.tree(); - if (rep == nullptr) { - callback(absl::string_view(contents_.data(), contents_.size())); - } else { - return ForEachChunkAux(rep, callback); - } -} - -// Nonmember Cord-to-Cord relational operarators. -inline bool operator==(const Cord& lhs, const Cord& rhs) { - if (lhs.contents_.IsSame(rhs.contents_)) return true; - size_t rhs_size = rhs.size(); - if (lhs.size() != rhs_size) return false; - return lhs.EqualsImpl(rhs, rhs_size); -} - -inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); } -inline bool operator<(const Cord& x, const Cord& y) { - return x.Compare(y) < 0; -} -inline bool operator>(const Cord& x, const Cord& y) { - return x.Compare(y) > 0; -} -inline bool operator<=(const Cord& x, const Cord& y) { - return x.Compare(y) <= 0; -} -inline bool operator>=(const Cord& x, const Cord& y) { - return x.Compare(y) >= 0; -} - -// Nonmember Cord-to-absl::string_view relational operators. -// -// Due to implicit conversions, these also enable comparisons of Cord with -// with std::string, ::string, and const char*. -inline bool operator==(const Cord& lhs, absl::string_view rhs) { - size_t lhs_size = lhs.size(); - size_t rhs_size = rhs.size(); - if (lhs_size != rhs_size) return false; - return lhs.EqualsImpl(rhs, rhs_size); -} - -inline bool operator==(absl::string_view x, const Cord& y) { return y == x; } -inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); } -inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); } -inline bool operator<(const Cord& x, absl::string_view y) { - return x.Compare(y) < 0; -} -inline bool operator<(absl::string_view x, const Cord& y) { - return y.Compare(x) > 0; -} -inline bool operator>(const Cord& x, absl::string_view y) { return y < x; } -inline bool operator>(absl::string_view x, const Cord& y) { return y < x; } -inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); } -inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); } -inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); } -inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); } - -// Some internals exposed to test code. -namespace strings_internal { -class CordTestAccess { - public: - static size_t FlatOverhead(); - static size_t MaxFlatLength(); - static size_t SizeofCordRepConcat(); - static size_t SizeofCordRepExternal(); - static size_t SizeofCordRepSubstring(); - static size_t FlatTagToLength(uint8_t tag); - static uint8_t LengthToTag(size_t s); -}; -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_CORD_H_ diff --git a/third_party/abseil_cpp/absl/strings/cord_test.cc b/third_party/abseil_cpp/absl/strings/cord_test.cc deleted file mode 100644 index 7942bfc03c49..000000000000 --- a/third_party/abseil_cpp/absl/strings/cord_test.cc +++ /dev/null @@ -1,1711 +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/cord.h" - -#include <algorithm> -#include <climits> -#include <cstdio> -#include <iterator> -#include <map> -#include <numeric> -#include <random> -#include <sstream> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/casts.h" -#include "absl/base/config.h" -#include "absl/base/internal/endian.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/container/fixed_array.h" -#include "absl/strings/cord_test_helpers.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/string_view.h" - -typedef std::mt19937_64 RandomEngine; - -static std::string RandomLowercaseString(RandomEngine* rng); -static std::string RandomLowercaseString(RandomEngine* rng, size_t length); - -static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) { - if (upper_bound > 0) { - std::uniform_int_distribution<int> uniform(0, upper_bound - 1); - return uniform(*rng); - } else { - return 0; - } -} - -static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) { - if (upper_bound > 0) { - std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1); - return uniform(*rng); - } else { - return 0; - } -} - -static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) { - const uint32_t base = (*rng)() % (max_log + 1); - const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u; - return (*rng)() & mask; -} - -static std::string RandomLowercaseString(RandomEngine* rng) { - int length; - std::bernoulli_distribution one_in_1k(0.001); - std::bernoulli_distribution one_in_10k(0.0001); - // With low probability, make a large fragment - if (one_in_10k(*rng)) { - length = GetUniformRandomUpTo(rng, 1048576); - } else if (one_in_1k(*rng)) { - length = GetUniformRandomUpTo(rng, 10000); - } else { - length = GenerateSkewedRandom(rng, 10); - } - return RandomLowercaseString(rng, length); -} - -static std::string RandomLowercaseString(RandomEngine* rng, size_t length) { - std::string result(length, '\0'); - std::uniform_int_distribution<int> chars('a', 'z'); - std::generate(result.begin(), result.end(), - [&]() { return static_cast<char>(chars(*rng)); }); - return result; -} - -static void DoNothing(absl::string_view /* data */, void* /* arg */) {} - -static void DeleteExternalString(absl::string_view data, void* arg) { - std::string* s = reinterpret_cast<std::string*>(arg); - EXPECT_EQ(data, *s); - delete s; -} - -// Add "s" to *dst via `MakeCordFromExternal` -static void AddExternalMemory(absl::string_view s, absl::Cord* dst) { - std::string* str = new std::string(s.data(), s.size()); - dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) { - DeleteExternalString(data, str); - })); -} - -static void DumpGrowth() { - absl::Cord str; - for (int i = 0; i < 1000; i++) { - char c = 'a' + i % 26; - str.Append(absl::string_view(&c, 1)); - } -} - -// Make a Cord with some number of fragments. Return the size (in bytes) -// of the smallest fragment. -static size_t AppendWithFragments(const std::string& s, RandomEngine* rng, - absl::Cord* cord) { - size_t j = 0; - const size_t max_size = s.size() / 5; // Make approx. 10 fragments - size_t min_size = max_size; // size of smallest fragment - while (j < s.size()) { - size_t N = 1 + GetUniformRandomUpTo(rng, max_size); - if (N > (s.size() - j)) { - N = s.size() - j; - } - if (N < min_size) { - min_size = N; - } - - std::bernoulli_distribution coin_flip(0.5); - if (coin_flip(*rng)) { - // Grow by adding an external-memory. - AddExternalMemory(absl::string_view(s.data() + j, N), cord); - } else { - cord->Append(absl::string_view(s.data() + j, N)); - } - j += N; - } - return min_size; -} - -// Add an external memory that contains the specified std::string to cord -static void AddNewStringBlock(const std::string& str, absl::Cord* dst) { - char* data = new char[str.size()]; - memcpy(data, str.data(), str.size()); - dst->Append(absl::MakeCordFromExternal( - absl::string_view(data, str.size()), - [](absl::string_view s) { delete[] s.data(); })); -} - -// Make a Cord out of many different types of nodes. -static absl::Cord MakeComposite() { - absl::Cord cord; - cord.Append("the"); - AddExternalMemory(" quick brown", &cord); - AddExternalMemory(" fox jumped", &cord); - - absl::Cord full(" over"); - AddExternalMemory(" the lazy", &full); - AddNewStringBlock(" dog slept the whole day away", &full); - absl::Cord substring = full.Subcord(0, 18); - - // Make substring long enough to defeat the copying fast path in Append. - substring.Append(std::string(1000, '.')); - cord.Append(substring); - cord = cord.Subcord(0, cord.size() - 998); // Remove most of extra junk - - return cord; -} - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class CordTestPeer { - public: - static void ForEachChunk( - const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) { - c.ForEachChunk(callback); - } - - static bool IsTree(const Cord& c) { return c.contents_.is_tree(); } -}; - -ABSL_NAMESPACE_END -} // namespace absl - -TEST(Cord, AllFlatSizes) { - using absl::strings_internal::CordTestAccess; - - for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) { - // Make a string of length s. - std::string src; - while (src.size() < s) { - src.push_back('a' + (src.size() % 26)); - } - - absl::Cord dst(src); - EXPECT_EQ(std::string(dst), src) << s; - } -} - -// We create a Cord at least 128GB in size using the fact that Cords can -// internally reference-count; thus the Cord is enormous without actually -// consuming very much memory. -TEST(GigabyteCord, FromExternal) { - const size_t one_gig = 1024U * 1024U * 1024U; - size_t max_size = 2 * one_gig; - if (sizeof(max_size) > 4) max_size = 128 * one_gig; - - size_t length = 128 * 1024; - char* data = new char[length]; - absl::Cord from = absl::MakeCordFromExternal( - absl::string_view(data, length), - [](absl::string_view sv) { delete[] sv.data(); }); - - // This loop may seem odd due to its combination of exponential doubling of - // size and incremental size increases. We do it incrementally to be sure the - // Cord will need rebalancing and will exercise code that, in the past, has - // caused crashes in production. We grow exponentially so that the code will - // execute in a reasonable amount of time. - absl::Cord c; - ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size()); - c.Append(from); - while (c.size() < max_size) { - c.Append(c); - c.Append(from); - c.Append(from); - c.Append(from); - c.Append(from); - } - - for (int i = 0; i < 1024; ++i) { - c.Append(from); - } - ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size()); - // Note: on a 32-bit build, this comes out to 2,818,048,000 bytes. - // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes. -} - -static absl::Cord MakeExternalCord(int size) { - char* buffer = new char[size]; - memset(buffer, 'x', size); - absl::Cord cord; - cord.Append(absl::MakeCordFromExternal( - absl::string_view(buffer, size), - [](absl::string_view s) { delete[] s.data(); })); - return cord; -} - -// Extern to fool clang that this is not constant. Needed to suppress -// a warning of unsafe code we want to test. -extern bool my_unique_true_boolean; -bool my_unique_true_boolean = true; - -TEST(Cord, Assignment) { - absl::Cord x(absl::string_view("hi there")); - absl::Cord y(x); - ASSERT_EQ(std::string(x), "hi there"); - ASSERT_EQ(std::string(y), "hi there"); - ASSERT_TRUE(x == y); - ASSERT_TRUE(x <= y); - ASSERT_TRUE(y <= x); - - x = absl::string_view("foo"); - ASSERT_EQ(std::string(x), "foo"); - ASSERT_EQ(std::string(y), "hi there"); - ASSERT_TRUE(x < y); - ASSERT_TRUE(y > x); - ASSERT_TRUE(x != y); - ASSERT_TRUE(x <= y); - ASSERT_TRUE(y >= x); - - x = "foo"; - ASSERT_EQ(x, "foo"); - - // Test that going from inline rep to tree we don't leak memory. - std::vector<std::pair<absl::string_view, absl::string_view>> - test_string_pairs = {{"hi there", "foo"}, - {"loooooong coooooord", "short cord"}, - {"short cord", "loooooong coooooord"}, - {"loooooong coooooord1", "loooooong coooooord2"}}; - for (std::pair<absl::string_view, absl::string_view> test_strings : - test_string_pairs) { - absl::Cord tmp(test_strings.first); - absl::Cord z(std::move(tmp)); - ASSERT_EQ(std::string(z), test_strings.first); - tmp = test_strings.second; - z = std::move(tmp); - ASSERT_EQ(std::string(z), test_strings.second); - } - { - // Test that self-move assignment doesn't crash/leak. - // Do not write such code! - absl::Cord my_small_cord("foo"); - absl::Cord my_big_cord("loooooong coooooord"); - // Bypass clang's warning on self move-assignment. - absl::Cord* my_small_alias = - my_unique_true_boolean ? &my_small_cord : &my_big_cord; - absl::Cord* my_big_alias = - !my_unique_true_boolean ? &my_small_cord : &my_big_cord; - - *my_small_alias = std::move(my_small_cord); - *my_big_alias = std::move(my_big_cord); - // my_small_cord and my_big_cord are in an unspecified but valid - // state, and will be correctly destroyed here. - } -} - -TEST(Cord, StartsEndsWith) { - absl::Cord x(absl::string_view("abcde")); - absl::Cord empty(""); - - ASSERT_TRUE(x.StartsWith(absl::Cord("abcde"))); - ASSERT_TRUE(x.StartsWith(absl::Cord("abc"))); - ASSERT_TRUE(x.StartsWith(absl::Cord(""))); - ASSERT_TRUE(empty.StartsWith(absl::Cord(""))); - ASSERT_TRUE(x.EndsWith(absl::Cord("abcde"))); - ASSERT_TRUE(x.EndsWith(absl::Cord("cde"))); - ASSERT_TRUE(x.EndsWith(absl::Cord(""))); - ASSERT_TRUE(empty.EndsWith(absl::Cord(""))); - - ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz"))); - ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz"))); - ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz"))); - ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz"))); - - ASSERT_TRUE(x.StartsWith("abcde")); - ASSERT_TRUE(x.StartsWith("abc")); - ASSERT_TRUE(x.StartsWith("")); - ASSERT_TRUE(empty.StartsWith("")); - ASSERT_TRUE(x.EndsWith("abcde")); - ASSERT_TRUE(x.EndsWith("cde")); - ASSERT_TRUE(x.EndsWith("")); - ASSERT_TRUE(empty.EndsWith("")); - - ASSERT_TRUE(!x.StartsWith("xyz")); - ASSERT_TRUE(!empty.StartsWith("xyz")); - ASSERT_TRUE(!x.EndsWith("xyz")); - ASSERT_TRUE(!empty.EndsWith("xyz")); -} - -TEST(Cord, Subcord) { - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - const std::string s = RandomLowercaseString(&rng, 1024); - - absl::Cord a; - AppendWithFragments(s, &rng, &a); - ASSERT_EQ(s.size(), a.size()); - - // Check subcords of a, from a variety of interesting points. - std::set<size_t> positions; - for (int i = 0; i <= 32; ++i) { - positions.insert(i); - positions.insert(i * 32 - 1); - positions.insert(i * 32); - positions.insert(i * 32 + 1); - positions.insert(a.size() - i); - } - positions.insert(237); - positions.insert(732); - for (size_t pos : positions) { - if (pos > a.size()) continue; - for (size_t end_pos : positions) { - if (end_pos < pos || end_pos > a.size()) continue; - absl::Cord sa = a.Subcord(pos, end_pos - pos); - EXPECT_EQ(absl::string_view(s).substr(pos, end_pos - pos), - std::string(sa)) - << a; - } - } - - // Do the same thing for an inline cord. - const std::string sh = "short"; - absl::Cord c(sh); - for (size_t pos = 0; pos <= sh.size(); ++pos) { - for (size_t n = 0; n <= sh.size() - pos; ++n) { - absl::Cord sc = c.Subcord(pos, n); - EXPECT_EQ(sh.substr(pos, n), std::string(sc)) << c; - } - } - - // Check subcords of subcords. - absl::Cord sa = a.Subcord(0, a.size()); - std::string ss = s.substr(0, s.size()); - while (sa.size() > 1) { - sa = sa.Subcord(1, sa.size() - 2); - ss = ss.substr(1, ss.size() - 2); - EXPECT_EQ(ss, std::string(sa)) << a; - if (HasFailure()) break; // halt cascade - } - - // It is OK to ask for too much. - sa = a.Subcord(0, a.size() + 1); - EXPECT_EQ(s, std::string(sa)); - - // It is OK to ask for something beyond the end. - sa = a.Subcord(a.size() + 1, 0); - EXPECT_TRUE(sa.empty()); - sa = a.Subcord(a.size() + 1, 1); - EXPECT_TRUE(sa.empty()); -} - -TEST(Cord, Swap) { - absl::string_view a("Dexter"); - absl::string_view b("Mandark"); - absl::Cord x(a); - absl::Cord y(b); - swap(x, y); - ASSERT_EQ(x, absl::Cord(b)); - ASSERT_EQ(y, absl::Cord(a)); - x.swap(y); - ASSERT_EQ(x, absl::Cord(a)); - ASSERT_EQ(y, absl::Cord(b)); -} - -static void VerifyCopyToString(const absl::Cord& cord) { - std::string initially_empty; - absl::CopyCordToString(cord, &initially_empty); - EXPECT_EQ(initially_empty, cord); - - constexpr size_t kInitialLength = 1024; - std::string has_initial_contents(kInitialLength, 'x'); - const char* address_before_copy = has_initial_contents.data(); - absl::CopyCordToString(cord, &has_initial_contents); - EXPECT_EQ(has_initial_contents, cord); - - if (cord.size() <= kInitialLength) { - EXPECT_EQ(has_initial_contents.data(), address_before_copy) - << "CopyCordToString allocated new string storage; " - "has_initial_contents = \"" - << has_initial_contents << "\""; - } -} - -TEST(Cord, CopyToString) { - VerifyCopyToString(absl::Cord()); - VerifyCopyToString(absl::Cord("small cord")); - VerifyCopyToString( - absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ", - "copying ", "to ", "a ", "string."})); -} - -TEST(TryFlat, Empty) { - absl::Cord c; - EXPECT_EQ(c.TryFlat(), ""); -} - -TEST(TryFlat, Flat) { - absl::Cord c("hello"); - EXPECT_EQ(c.TryFlat(), "hello"); -} - -TEST(TryFlat, SubstrInlined) { - absl::Cord c("hello"); - c.RemovePrefix(1); - EXPECT_EQ(c.TryFlat(), "ello"); -} - -TEST(TryFlat, SubstrFlat) { - absl::Cord c("longer than 15 bytes"); - c.RemovePrefix(1); - EXPECT_EQ(c.TryFlat(), "onger than 15 bytes"); -} - -TEST(TryFlat, Concat) { - absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"}); - EXPECT_EQ(c.TryFlat(), absl::nullopt); -} - -TEST(TryFlat, External) { - absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {}); - EXPECT_EQ(c.TryFlat(), "hell"); -} - -TEST(TryFlat, SubstrExternal) { - absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {}); - c.RemovePrefix(1); - EXPECT_EQ(c.TryFlat(), "ell"); -} - -TEST(TryFlat, SubstrConcat) { - absl::Cord c = absl::MakeFragmentedCord({"hello", " world"}); - c.RemovePrefix(1); - EXPECT_EQ(c.TryFlat(), absl::nullopt); -} - -static bool IsFlat(const absl::Cord& c) { - return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end(); -} - -static void VerifyFlatten(absl::Cord c) { - std::string old_contents(c); - absl::string_view old_flat; - bool already_flat_and_non_empty = IsFlat(c) && !c.empty(); - if (already_flat_and_non_empty) { - old_flat = *c.chunk_begin(); - } - absl::string_view new_flat = c.Flatten(); - - // Verify that the contents of the flattened Cord are correct. - EXPECT_EQ(new_flat, old_contents); - EXPECT_EQ(std::string(c), old_contents); - - // If the Cord contained data and was already flat, verify that the data - // wasn't copied. - if (already_flat_and_non_empty) { - EXPECT_EQ(old_flat.data(), new_flat.data()) - << "Allocated new memory even though the Cord was already flat."; - } - - // Verify that the flattened Cord is in fact flat. - EXPECT_TRUE(IsFlat(c)); -} - -TEST(Cord, Flatten) { - VerifyFlatten(absl::Cord()); - VerifyFlatten(absl::Cord("small cord")); - VerifyFlatten(absl::Cord("larger than small buffer optimization")); - VerifyFlatten(absl::MakeFragmentedCord({"small ", "fragmented ", "cord"})); - - // Test with a cord that is longer than the largest flat buffer - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - VerifyFlatten(absl::Cord(RandomLowercaseString(&rng, 8192))); -} - -// Test data -namespace { -class TestData { - private: - std::vector<std::string> data_; - - // Return a std::string of the specified length. - static std::string MakeString(int length) { - std::string result; - char buf[30]; - snprintf(buf, sizeof(buf), "(%d)", length); - while (result.size() < length) { - result += buf; - } - result.resize(length); - return result; - } - - public: - TestData() { - // short strings increasing in length by one - for (int i = 0; i < 30; i++) { - data_.push_back(MakeString(i)); - } - - // strings around half kMaxFlatLength - static const int kMaxFlatLength = 4096 - 9; - static const int kHalf = kMaxFlatLength / 2; - - for (int i = -10; i <= +10; i++) { - data_.push_back(MakeString(kHalf + i)); - } - - for (int i = -10; i <= +10; i++) { - data_.push_back(MakeString(kMaxFlatLength + i)); - } - } - - size_t size() const { return data_.size(); } - const std::string& data(size_t i) const { return data_[i]; } -}; -} // namespace - -TEST(Cord, MultipleLengths) { - TestData d; - for (size_t i = 0; i < d.size(); i++) { - std::string a = d.data(i); - - { // Construct from Cord - absl::Cord tmp(a); - absl::Cord x(tmp); - EXPECT_EQ(a, std::string(x)) << "'" << a << "'"; - } - - { // Construct from absl::string_view - absl::Cord x(a); - EXPECT_EQ(a, std::string(x)) << "'" << a << "'"; - } - - { // Append cord to self - absl::Cord self(a); - self.Append(self); - EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'"; - } - - { // Prepend cord to self - absl::Cord self(a); - self.Prepend(self); - EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'"; - } - - // Try to append/prepend others - for (size_t j = 0; j < d.size(); j++) { - std::string b = d.data(j); - - { // CopyFrom Cord - absl::Cord x(a); - absl::Cord y(b); - x = y; - EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'"; - } - - { // CopyFrom absl::string_view - absl::Cord x(a); - x = b; - EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'"; - } - - { // Cord::Append(Cord) - absl::Cord x(a); - absl::Cord y(b); - x.Append(y); - EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'"; - } - - { // Cord::Append(absl::string_view) - absl::Cord x(a); - x.Append(b); - EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'"; - } - - { // Cord::Prepend(Cord) - absl::Cord x(a); - absl::Cord y(b); - x.Prepend(y); - EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'"; - } - - { // Cord::Prepend(absl::string_view) - absl::Cord x(a); - x.Prepend(b); - EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'"; - } - } - } -} - -namespace { - -TEST(Cord, RemoveSuffixWithExternalOrSubstring) { - absl::Cord cord = absl::MakeCordFromExternal( - "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); }); - - EXPECT_EQ("foo bar baz", std::string(cord)); - - // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node. - cord.RemoveSuffix(4); - EXPECT_EQ("foo bar", std::string(cord)); - - // This RemoveSuffix() will adjust the SUBSTRING node in-place. - cord.RemoveSuffix(4); - EXPECT_EQ("foo", std::string(cord)); -} - -TEST(Cord, RemoveSuffixMakesZeroLengthNode) { - absl::Cord c; - c.Append(absl::Cord(std::string(100, 'x'))); - absl::Cord other_ref = c; // Prevent inplace appends - c.Append(absl::Cord(std::string(200, 'y'))); - c.RemoveSuffix(200); - EXPECT_EQ(std::string(100, 'x'), std::string(c)); -} - -} // namespace - -// CordSpliceTest contributed by hendrie. -namespace { - -// Create a cord with an external memory block filled with 'z' -absl::Cord CordWithZedBlock(size_t size) { - char* data = new char[size]; - if (size > 0) { - memset(data, 'z', size); - } - absl::Cord cord = absl::MakeCordFromExternal( - absl::string_view(data, size), - [](absl::string_view s) { delete[] s.data(); }); - return cord; -} - -// Establish that ZedBlock does what we think it does. -TEST(CordSpliceTest, ZedBlock) { - absl::Cord blob = CordWithZedBlock(10); - EXPECT_EQ(10, blob.size()); - std::string s; - absl::CopyCordToString(blob, &s); - EXPECT_EQ("zzzzzzzzzz", s); -} - -TEST(CordSpliceTest, ZedBlock0) { - absl::Cord blob = CordWithZedBlock(0); - EXPECT_EQ(0, blob.size()); - std::string s; - absl::CopyCordToString(blob, &s); - EXPECT_EQ("", s); -} - -TEST(CordSpliceTest, ZedBlockSuffix1) { - absl::Cord blob = CordWithZedBlock(10); - EXPECT_EQ(10, blob.size()); - absl::Cord suffix(blob); - suffix.RemovePrefix(9); - EXPECT_EQ(1, suffix.size()); - std::string s; - absl::CopyCordToString(suffix, &s); - EXPECT_EQ("z", s); -} - -// Remove all of a prefix block -TEST(CordSpliceTest, ZedBlockSuffix0) { - absl::Cord blob = CordWithZedBlock(10); - EXPECT_EQ(10, blob.size()); - absl::Cord suffix(blob); - suffix.RemovePrefix(10); - EXPECT_EQ(0, suffix.size()); - std::string s; - absl::CopyCordToString(suffix, &s); - EXPECT_EQ("", s); -} - -absl::Cord BigCord(size_t len, char v) { - std::string s(len, v); - return absl::Cord(s); -} - -// Splice block into cord. -absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset, - const absl::Cord& block) { - ABSL_RAW_CHECK(offset >= 0, ""); - ABSL_RAW_CHECK(offset + block.size() <= blob.size(), ""); - absl::Cord result(blob); - result.RemoveSuffix(blob.size() - offset); - result.Append(block); - absl::Cord suffix(blob); - suffix.RemovePrefix(offset + block.size()); - result.Append(suffix); - ABSL_RAW_CHECK(blob.size() == result.size(), ""); - return result; -} - -// Taking an empty suffix of a block breaks appending. -TEST(CordSpliceTest, RemoveEntireBlock1) { - absl::Cord zero = CordWithZedBlock(10); - absl::Cord suffix(zero); - suffix.RemovePrefix(10); - absl::Cord result; - result.Append(suffix); -} - -TEST(CordSpliceTest, RemoveEntireBlock2) { - absl::Cord zero = CordWithZedBlock(10); - absl::Cord prefix(zero); - prefix.RemoveSuffix(10); - absl::Cord suffix(zero); - suffix.RemovePrefix(10); - absl::Cord result(prefix); - result.Append(suffix); -} - -TEST(CordSpliceTest, RemoveEntireBlock3) { - absl::Cord blob = CordWithZedBlock(10); - absl::Cord block = BigCord(10, 'b'); - blob = SpliceCord(blob, 0, block); -} - -struct CordCompareTestCase { - template <typename LHS, typename RHS> - CordCompareTestCase(const LHS& lhs, const RHS& rhs) - : lhs_cord(lhs), rhs_cord(rhs) {} - - absl::Cord lhs_cord; - absl::Cord rhs_cord; -}; - -const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); }; - -void VerifyComparison(const CordCompareTestCase& test_case) { - std::string lhs_string(test_case.lhs_cord); - std::string rhs_string(test_case.rhs_cord); - int expected = sign(lhs_string.compare(rhs_string)); - EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord)) - << "LHS=" << lhs_string << "; RHS=" << rhs_string; - EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string)) - << "LHS=" << lhs_string << "; RHS=" << rhs_string; - EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord)) - << "LHS=" << rhs_string << "; RHS=" << lhs_string; - EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string)) - << "LHS=" << rhs_string << "; RHS=" << lhs_string; -} - -TEST(Cord, Compare) { - absl::Cord subcord("aaaaaBBBBBcccccDDDDD"); - subcord = subcord.Subcord(3, 10); - - absl::Cord tmp("aaaaaaaaaaaaaaaa"); - tmp.Append("BBBBBBBBBBBBBBBB"); - absl::Cord concat = absl::Cord("cccccccccccccccc"); - concat.Append("DDDDDDDDDDDDDDDD"); - concat.Prepend(tmp); - - absl::Cord concat2("aaaaaaaaaaaaa"); - concat2.Append("aaaBBBBBBBBBBBBBBBBccccc"); - concat2.Append("cccccccccccDDDDDDDDDDDDDD"); - concat2.Append("DD"); - - std::vector<CordCompareTestCase> test_cases = {{ - // Inline cords - {"abcdef", "abcdef"}, - {"abcdef", "abcdee"}, - {"abcdef", "abcdeg"}, - {"bbcdef", "abcdef"}, - {"bbcdef", "abcdeg"}, - {"abcdefa", "abcdef"}, - {"abcdef", "abcdefa"}, - - // Small flat cords - {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD"}, - {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD"}, - {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD"}, - {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX"}, - {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD"}, - {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa"}, - - // Subcords - {subcord, subcord}, - {subcord, "aaBBBBBccc"}, - {subcord, "aaBBBBBccd"}, - {subcord, "aaBBBBBccb"}, - {subcord, "aaBBBBBxcb"}, - {subcord, "aaBBBBBccca"}, - {subcord, "aaBBBBBcc"}, - - // Concats - {concat, concat}, - {concat, - "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD"}, - {concat, - "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD"}, - {concat, - "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD"}, - {concat, - "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD"}, - {concat, - "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe"}, - - {concat, concat2}, - }}; - - for (const auto& tc : test_cases) { - VerifyComparison(tc); - } -} - -TEST(Cord, CompareAfterAssign) { - absl::Cord a("aaaaaa1111111"); - absl::Cord b("aaaaaa2222222"); - a = "cccccc"; - b = "cccccc"; - EXPECT_EQ(a, b); - EXPECT_FALSE(a < b); - - a = "aaaa"; - b = "bbbbb"; - a = ""; - b = ""; - EXPECT_EQ(a, b); - EXPECT_FALSE(a < b); -} - -// Test CompareTo() and ComparePrefix() against string and substring -// comparison methods from basic_string. -static void TestCompare(const absl::Cord& c, const absl::Cord& d, - RandomEngine* rng) { - typedef std::basic_string<uint8_t> ustring; - ustring cs(reinterpret_cast<const uint8_t*>(std::string(c).data()), c.size()); - ustring ds(reinterpret_cast<const uint8_t*>(std::string(d).data()), d.size()); - // ustring comparison is ideal because we expect Cord comparisons to be - // based on unsigned byte comparisons regardless of whether char is signed. - int expected = sign(cs.compare(ds)); - EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d; -} - -TEST(Compare, ComparisonIsUnsigned) { - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255); - char x = static_cast<char>(uniform_uint8(rng)); - TestCompare( - absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)), - absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng); -} - -TEST(Compare, RandomComparisons) { - const int kIters = 5000; - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - - int n = GetUniformRandomUpTo(&rng, 5000); - absl::Cord a[] = {MakeExternalCord(n), - absl::Cord("ant"), - absl::Cord("elephant"), - absl::Cord("giraffe"), - absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), - GetUniformRandomUpTo(&rng, 100))), - absl::Cord(""), - absl::Cord("x"), - absl::Cord("A"), - absl::Cord("B"), - absl::Cord("C")}; - for (int i = 0; i < kIters; i++) { - absl::Cord c, d; - for (int j = 0; j < (i % 7) + 1; j++) { - c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]); - d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]); - } - std::bernoulli_distribution coin_flip(0.5); - TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)), - coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng); - } -} - -template <typename T1, typename T2> -void CompareOperators() { - const T1 a("a"); - const T2 b("b"); - - EXPECT_TRUE(a == a); - // For pointer type (i.e. `const char*`), operator== compares the address - // instead of the string, so `a == const char*("a")` isn't necessarily true. - EXPECT_TRUE(std::is_pointer<T1>::value || a == T1("a")); - EXPECT_TRUE(std::is_pointer<T2>::value || a == T2("a")); - EXPECT_FALSE(a == b); - - EXPECT_TRUE(a != b); - EXPECT_FALSE(a != a); - - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - - EXPECT_TRUE(b > a); - EXPECT_FALSE(a > b); - - EXPECT_TRUE(a >= a); - EXPECT_TRUE(b >= a); - EXPECT_FALSE(a >= b); - - EXPECT_TRUE(a <= a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); -} - -TEST(ComparisonOperators, Cord_Cord) { - CompareOperators<absl::Cord, absl::Cord>(); -} - -TEST(ComparisonOperators, Cord_StringPiece) { - CompareOperators<absl::Cord, absl::string_view>(); -} - -TEST(ComparisonOperators, StringPiece_Cord) { - CompareOperators<absl::string_view, absl::Cord>(); -} - -TEST(ComparisonOperators, Cord_string) { - CompareOperators<absl::Cord, std::string>(); -} - -TEST(ComparisonOperators, string_Cord) { - CompareOperators<std::string, absl::Cord>(); -} - -TEST(ComparisonOperators, stdstring_Cord) { - CompareOperators<std::string, absl::Cord>(); -} - -TEST(ComparisonOperators, Cord_stdstring) { - CompareOperators<absl::Cord, std::string>(); -} - -TEST(ComparisonOperators, charstar_Cord) { - CompareOperators<const char*, absl::Cord>(); -} - -TEST(ComparisonOperators, Cord_charstar) { - CompareOperators<absl::Cord, const char*>(); -} - -TEST(ConstructFromExternal, ReleaserInvoked) { - // Empty external memory means the releaser should be called immediately. - { - bool invoked = false; - auto releaser = [&invoked](absl::string_view) { invoked = true; }; - { - auto c = absl::MakeCordFromExternal("", releaser); - EXPECT_TRUE(invoked); - } - } - - // If the size of the data is small enough, a future constructor - // implementation may copy the bytes and immediately invoke the releaser - // instead of creating an external node. We make a large dummy std::string to - // make this test independent of such an optimization. - std::string large_dummy(2048, 'c'); - { - bool invoked = false; - auto releaser = [&invoked](absl::string_view) { invoked = true; }; - { - auto c = absl::MakeCordFromExternal(large_dummy, releaser); - EXPECT_FALSE(invoked); - } - EXPECT_TRUE(invoked); - } - - { - bool invoked = false; - auto releaser = [&invoked](absl::string_view) { invoked = true; }; - { - absl::Cord copy; - { - auto c = absl::MakeCordFromExternal(large_dummy, releaser); - copy = c; - EXPECT_FALSE(invoked); - } - EXPECT_FALSE(invoked); - } - EXPECT_TRUE(invoked); - } -} - -TEST(ConstructFromExternal, CompareContents) { - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - - for (int length = 1; length <= 2048; length *= 2) { - std::string data = RandomLowercaseString(&rng, length); - auto* external = new std::string(data); - auto cord = - absl::MakeCordFromExternal(*external, [external](absl::string_view sv) { - EXPECT_EQ(external->data(), sv.data()); - EXPECT_EQ(external->size(), sv.size()); - delete external; - }); - EXPECT_EQ(data, cord); - } -} - -TEST(ConstructFromExternal, LargeReleaser) { - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - constexpr size_t kLength = 256; - std::string data = RandomLowercaseString(&rng, kLength); - std::array<char, kLength> data_array; - for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i]; - bool invoked = false; - auto releaser = [data_array, &invoked](absl::string_view data) { - EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size())); - invoked = true; - }; - (void)absl::MakeCordFromExternal(data, releaser); - EXPECT_TRUE(invoked); -} - -TEST(ConstructFromExternal, FunctionPointerReleaser) { - static absl::string_view data("hello world"); - static bool invoked; - auto* releaser = - static_cast<void (*)(absl::string_view)>([](absl::string_view sv) { - EXPECT_EQ(data, sv); - invoked = true; - }); - invoked = false; - (void)absl::MakeCordFromExternal(data, releaser); - EXPECT_TRUE(invoked); - - invoked = false; - (void)absl::MakeCordFromExternal(data, *releaser); - EXPECT_TRUE(invoked); -} - -TEST(ConstructFromExternal, MoveOnlyReleaser) { - struct Releaser { - explicit Releaser(bool* invoked) : invoked(invoked) {} - Releaser(Releaser&& other) noexcept : invoked(other.invoked) {} - void operator()(absl::string_view) const { *invoked = true; } - - bool* invoked; - }; - - bool invoked = false; - (void)absl::MakeCordFromExternal("dummy", Releaser(&invoked)); - EXPECT_TRUE(invoked); -} - -TEST(ConstructFromExternal, NoArgLambda) { - bool invoked = false; - (void)absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; }); - EXPECT_TRUE(invoked); -} - -TEST(ConstructFromExternal, StringViewArgLambda) { - bool invoked = false; - (void)absl::MakeCordFromExternal( - "dummy", [&invoked](absl::string_view) { invoked = true; }); - EXPECT_TRUE(invoked); -} - -TEST(ConstructFromExternal, NonTrivialReleaserDestructor) { - struct Releaser { - explicit Releaser(bool* destroyed) : destroyed(destroyed) {} - ~Releaser() { *destroyed = true; } - void operator()(absl::string_view) const {} - - bool* destroyed; - }; - - bool destroyed = false; - Releaser releaser(&destroyed); - (void)absl::MakeCordFromExternal("dummy", releaser); - EXPECT_TRUE(destroyed); -} - -TEST(ConstructFromExternal, ReferenceQualifierOverloads) { - struct Releaser { - void operator()(absl::string_view) & { *lvalue_invoked = true; } - void operator()(absl::string_view) && { *rvalue_invoked = true; } - - bool* lvalue_invoked; - bool* rvalue_invoked; - }; - - bool lvalue_invoked = false; - bool rvalue_invoked = false; - Releaser releaser = {&lvalue_invoked, &rvalue_invoked}; - (void)absl::MakeCordFromExternal("", releaser); - EXPECT_FALSE(lvalue_invoked); - EXPECT_TRUE(rvalue_invoked); - rvalue_invoked = false; - - (void)absl::MakeCordFromExternal("dummy", releaser); - EXPECT_FALSE(lvalue_invoked); - EXPECT_TRUE(rvalue_invoked); - rvalue_invoked = false; - - // NOLINTNEXTLINE: suppress clang-tidy std::move on trivially copyable type. - (void)absl::MakeCordFromExternal("dummy", std::move(releaser)); - EXPECT_FALSE(lvalue_invoked); - EXPECT_TRUE(rvalue_invoked); -} - -TEST(ExternalMemory, BasicUsage) { - static const char* strings[] = {"", "hello", "there"}; - for (const char* str : strings) { - absl::Cord dst("(prefix)"); - AddExternalMemory(str, &dst); - dst.Append("(suffix)"); - EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")), - std::string(dst)); - } -} - -TEST(ExternalMemory, RemovePrefixSuffix) { - // Exhaustively try all sub-strings. - absl::Cord cord = MakeComposite(); - std::string s = std::string(cord); - for (int offset = 0; offset <= s.size(); offset++) { - for (int length = 0; length <= s.size() - offset; length++) { - absl::Cord result(cord); - result.RemovePrefix(offset); - result.RemoveSuffix(result.size() - length); - EXPECT_EQ(s.substr(offset, length), std::string(result)) - << offset << " " << length; - } - } -} - -TEST(ExternalMemory, Get) { - absl::Cord cord("hello"); - AddExternalMemory(" world!", &cord); - AddExternalMemory(" how are ", &cord); - cord.Append(" you?"); - std::string s = std::string(cord); - for (int i = 0; i < s.size(); i++) { - EXPECT_EQ(s[i], cord[i]); - } -} - -// CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage() -// These tests take into account that the reported memory usage is approximate -// and non-deterministic. For all tests, We verify that the reported memory -// usage is larger than `size()`, and less than `size() * 1.5` as a cord should -// never reserve more 'extra' capacity than half of its size as it grows. -// Additionally we have some whiteboxed expectations based on our knowledge of -// the layout and size of empty and inlined cords, and flat nodes. - -TEST(CordMemoryUsage, Empty) { - EXPECT_EQ(sizeof(absl::Cord), absl::Cord().EstimatedMemoryUsage()); -} - -TEST(CordMemoryUsage, Embedded) { - absl::Cord a("hello"); - EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord)); -} - -TEST(CordMemoryUsage, EmbeddedAppend) { - absl::Cord a("a"); - absl::Cord b("bcd"); - EXPECT_EQ(b.EstimatedMemoryUsage(), sizeof(absl::Cord)); - a.Append(b); - EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord)); -} - -TEST(CordMemoryUsage, ExternalMemory) { - static const int kLength = 1000; - absl::Cord cord; - AddExternalMemory(std::string(kLength, 'x'), &cord); - EXPECT_GT(cord.EstimatedMemoryUsage(), kLength); - EXPECT_LE(cord.EstimatedMemoryUsage(), kLength * 1.5); -} - -TEST(CordMemoryUsage, Flat) { - static const int kLength = 125; - absl::Cord a(std::string(kLength, 'a')); - EXPECT_GT(a.EstimatedMemoryUsage(), kLength); - EXPECT_LE(a.EstimatedMemoryUsage(), kLength * 1.5); -} - -TEST(CordMemoryUsage, AppendFlat) { - using absl::strings_internal::CordTestAccess; - absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a')); - size_t length = a.EstimatedMemoryUsage(); - a.Append(std::string(CordTestAccess::MaxFlatLength(), 'b')); - size_t delta = a.EstimatedMemoryUsage() - length; - EXPECT_GT(delta, CordTestAccess::MaxFlatLength()); - EXPECT_LE(delta, CordTestAccess::MaxFlatLength() * 1.5); -} - -// Regtest for a change that had to be rolled back because it expanded out -// of the InlineRep too soon, which was observable through MemoryUsage(). -TEST(CordMemoryUsage, InlineRep) { - constexpr size_t kMaxInline = 15; // Cord::InlineRep::N - const std::string small_string(kMaxInline, 'x'); - absl::Cord c1(small_string); - - absl::Cord c2; - c2.Append(small_string); - EXPECT_EQ(c1, c2); - EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage()); -} - -} // namespace - -// Regtest for 7510292 (fix a bug introduced by 7465150) -TEST(Cord, Concat_Append) { - // Create a rep of type CONCAT - absl::Cord s1("foobarbarbarbarbar"); - s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg"); - size_t size = s1.size(); - - // Create a copy of s1 and append to it. - absl::Cord s2 = s1; - s2.Append("x"); - - // 7465150 modifies s1 when it shouldn't. - EXPECT_EQ(s1.size(), size); - EXPECT_EQ(s2.size(), size + 1); -} - -TEST(MakeFragmentedCord, MakeFragmentedCordFromInitializerList) { - absl::Cord fragmented = - absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"}); - - EXPECT_EQ("A fragmented Cord", fragmented); - - auto chunk_it = fragmented.chunk_begin(); - - ASSERT_TRUE(chunk_it != fragmented.chunk_end()); - EXPECT_EQ("A ", *chunk_it); - - ASSERT_TRUE(++chunk_it != fragmented.chunk_end()); - EXPECT_EQ("fragmented ", *chunk_it); - - ASSERT_TRUE(++chunk_it != fragmented.chunk_end()); - EXPECT_EQ("Cord", *chunk_it); - - ASSERT_TRUE(++chunk_it == fragmented.chunk_end()); -} - -TEST(MakeFragmentedCord, MakeFragmentedCordFromVector) { - std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"}; - absl::Cord fragmented = absl::MakeFragmentedCord(chunks); - - EXPECT_EQ("A fragmented Cord", fragmented); - - auto chunk_it = fragmented.chunk_begin(); - - ASSERT_TRUE(chunk_it != fragmented.chunk_end()); - EXPECT_EQ("A ", *chunk_it); - - ASSERT_TRUE(++chunk_it != fragmented.chunk_end()); - EXPECT_EQ("fragmented ", *chunk_it); - - ASSERT_TRUE(++chunk_it != fragmented.chunk_end()); - EXPECT_EQ("Cord", *chunk_it); - - ASSERT_TRUE(++chunk_it == fragmented.chunk_end()); -} - -TEST(CordChunkIterator, Traits) { - static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value, - ""); - static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, ""); - - // Move semantics to satisfy swappable via std::swap - static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value, - ""); - static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, ""); - - static_assert( - std::is_same< - std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category, - std::input_iterator_tag>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type, - absl::string_view>::value, - ""); - static_assert( - std::is_same< - std::iterator_traits<absl::Cord::ChunkIterator>::difference_type, - ptrdiff_t>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer, - const absl::string_view*>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference, - absl::string_view>::value, - ""); -} - -static void VerifyChunkIterator(const absl::Cord& cord, - size_t expected_chunks) { - EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord; - EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty()); - - absl::Cord::ChunkRange range = cord.Chunks(); - EXPECT_EQ(range.begin() == range.end(), cord.empty()); - EXPECT_EQ(range.begin() != range.end(), !cord.empty()); - - std::string content(cord); - size_t pos = 0; - auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin(); - size_t n_chunks = 0; - while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) { - EXPECT_FALSE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test == - EXPECT_FALSE(post_iter == cord.chunk_end()); // NOLINT - - EXPECT_EQ(pre_iter, post_iter); - EXPECT_EQ(*pre_iter, *post_iter); - - EXPECT_EQ(pre_iter->data(), (*pre_iter).data()); - EXPECT_EQ(pre_iter->size(), (*pre_iter).size()); - - absl::string_view chunk = *pre_iter; - EXPECT_FALSE(chunk.empty()); - EXPECT_LE(pos + chunk.size(), content.size()); - EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk); - - int n_equal_iterators = 0; - for (absl::Cord::ChunkIterator it = range.begin(); it != range.end(); - ++it) { - n_equal_iterators += static_cast<int>(it == pre_iter); - } - EXPECT_EQ(n_equal_iterators, 1); - - ++pre_iter; - EXPECT_EQ(*post_iter++, chunk); - - pos += chunk.size(); - ++n_chunks; - } - EXPECT_EQ(expected_chunks, n_chunks); - EXPECT_EQ(pos, content.size()); - EXPECT_TRUE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test == - EXPECT_TRUE(post_iter == cord.chunk_end()); // NOLINT -} - -TEST(CordChunkIterator, Operations) { - absl::Cord empty_cord; - VerifyChunkIterator(empty_cord, 0); - - absl::Cord small_buffer_cord("small cord"); - VerifyChunkIterator(small_buffer_cord, 1); - - absl::Cord flat_node_cord("larger than small buffer optimization"); - VerifyChunkIterator(flat_node_cord, 1); - - VerifyChunkIterator( - absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ", - "testing ", "chunk ", "iterations."}), - 8); - - absl::Cord reused_nodes_cord(std::string(40, 'c')); - reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b'))); - reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a'))); - size_t expected_chunks = 3; - for (int i = 0; i < 8; ++i) { - reused_nodes_cord.Prepend(reused_nodes_cord); - expected_chunks *= 2; - VerifyChunkIterator(reused_nodes_cord, expected_chunks); - } - - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - absl::Cord flat_cord(RandomLowercaseString(&rng, 256)); - absl::Cord subcords; - for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128)); - VerifyChunkIterator(subcords, 128); -} - -TEST(CordCharIterator, Traits) { - static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value, - ""); - static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, ""); - - // Move semantics to satisfy swappable via std::swap - static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value, - ""); - static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, ""); - - static_assert( - std::is_same< - std::iterator_traits<absl::Cord::CharIterator>::iterator_category, - std::input_iterator_tag>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type, - char>::value, - ""); - static_assert( - std::is_same< - std::iterator_traits<absl::Cord::CharIterator>::difference_type, - ptrdiff_t>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer, - const char*>::value, - ""); - static_assert( - std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference, - const char&>::value, - ""); -} - -static void VerifyCharIterator(const absl::Cord& cord) { - EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty()); - EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty()); - - absl::Cord::CharRange range = cord.Chars(); - EXPECT_EQ(range.begin() == range.end(), cord.empty()); - EXPECT_EQ(range.begin() != range.end(), !cord.empty()); - - size_t i = 0; - absl::Cord::CharIterator pre_iter = cord.char_begin(); - absl::Cord::CharIterator post_iter = cord.char_begin(); - std::string content(cord); - while (pre_iter != cord.char_end() && post_iter != cord.char_end()) { - EXPECT_FALSE(pre_iter == cord.char_end()); // NOLINT: explicitly test == - EXPECT_FALSE(post_iter == cord.char_end()); // NOLINT - - EXPECT_LT(i, cord.size()); - EXPECT_EQ(content[i], *pre_iter); - - EXPECT_EQ(pre_iter, post_iter); - EXPECT_EQ(*pre_iter, *post_iter); - EXPECT_EQ(&*pre_iter, &*post_iter); - - EXPECT_EQ(&*pre_iter, pre_iter.operator->()); - - const char* character_address = &*pre_iter; - absl::Cord::CharIterator copy = pre_iter; - ++copy; - EXPECT_EQ(character_address, &*pre_iter); - - int n_equal_iterators = 0; - for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) { - n_equal_iterators += static_cast<int>(it == pre_iter); - } - EXPECT_EQ(n_equal_iterators, 1); - - absl::Cord::CharIterator advance_iter = range.begin(); - absl::Cord::Advance(&advance_iter, i); - EXPECT_EQ(pre_iter, advance_iter); - - advance_iter = range.begin(); - EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i)); - EXPECT_EQ(pre_iter, advance_iter); - - advance_iter = pre_iter; - absl::Cord::Advance(&advance_iter, cord.size() - i); - EXPECT_EQ(range.end(), advance_iter); - - advance_iter = pre_iter; - EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i), - cord.Subcord(i, cord.size() - i)); - EXPECT_EQ(range.end(), advance_iter); - - ++i; - ++pre_iter; - post_iter++; - } - EXPECT_EQ(i, cord.size()); - EXPECT_TRUE(pre_iter == cord.char_end()); // NOLINT: explicitly test == - EXPECT_TRUE(post_iter == cord.char_end()); // NOLINT - - absl::Cord::CharIterator zero_advanced_end = cord.char_end(); - absl::Cord::Advance(&zero_advanced_end, 0); - EXPECT_EQ(zero_advanced_end, cord.char_end()); - - absl::Cord::CharIterator it = cord.char_begin(); - for (absl::string_view chunk : cord.Chunks()) { - while (!chunk.empty()) { - EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk); - chunk.remove_prefix(1); - ++it; - } - } -} - -TEST(CordCharIterator, Operations) { - absl::Cord empty_cord; - VerifyCharIterator(empty_cord); - - absl::Cord small_buffer_cord("small cord"); - VerifyCharIterator(small_buffer_cord); - - absl::Cord flat_node_cord("larger than small buffer optimization"); - VerifyCharIterator(flat_node_cord); - - VerifyCharIterator( - absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ", - "testing ", "character ", "iteration."})); - - absl::Cord reused_nodes_cord("ghi"); - reused_nodes_cord.Prepend(absl::Cord("def")); - reused_nodes_cord.Prepend(absl::Cord("abc")); - for (int i = 0; i < 4; ++i) { - reused_nodes_cord.Prepend(reused_nodes_cord); - VerifyCharIterator(reused_nodes_cord); - } - - RandomEngine rng(testing::GTEST_FLAG(random_seed)); - absl::Cord flat_cord(RandomLowercaseString(&rng, 256)); - absl::Cord subcords; - for (int i = 0; i < 4; ++i) subcords.Prepend(flat_cord.Subcord(16 * i, 128)); - VerifyCharIterator(subcords); -} - -TEST(Cord, StreamingOutput) { - absl::Cord c = - absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."}); - std::stringstream output; - output << c; - EXPECT_EQ("A small fragmented Cord.", output.str()); -} - -TEST(Cord, ForEachChunk) { - for (int num_elements : {1, 10, 200}) { - SCOPED_TRACE(num_elements); - std::vector<std::string> cord_chunks; - for (int i = 0; i < num_elements; ++i) { - cord_chunks.push_back(absl::StrCat("[", i, "]")); - } - absl::Cord c = absl::MakeFragmentedCord(cord_chunks); - - std::vector<std::string> iterated_chunks; - absl::CordTestPeer::ForEachChunk(c, - [&iterated_chunks](absl::string_view sv) { - iterated_chunks.emplace_back(sv); - }); - EXPECT_EQ(iterated_chunks, cord_chunks); - } -} - -TEST(Cord, SmallBufferAssignFromOwnData) { - constexpr size_t kMaxInline = 15; - std::string contents = "small buff cord"; - EXPECT_EQ(contents.size(), kMaxInline); - for (size_t pos = 0; pos < contents.size(); ++pos) { - for (size_t count = contents.size() - pos; count > 0; --count) { - absl::Cord c(contents); - absl::string_view flat = c.Flatten(); - c = flat.substr(pos, count); - EXPECT_EQ(c, contents.substr(pos, count)) - << "pos = " << pos << "; count = " << count; - } - } -} - -TEST(Cord, Format) { - absl::Cord c; - absl::Format(&c, "There were %04d little %s.", 3, "pigs"); - EXPECT_EQ(c, "There were 0003 little pigs."); - absl::Format(&c, "And %-3llx bad wolf!", 1); - EXPECT_EQ(c, "There were 0003 little pigs.And 1 bad wolf!"); -} - -TEST(CordDeathTest, Hardening) { - absl::Cord cord("hello"); - // These statement should abort the program in all builds modes. - EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), ""); - EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), ""); - - bool test_hardening = false; - ABSL_HARDENING_ASSERT([&]() { - // This only runs when ABSL_HARDENING_ASSERT is active. - test_hardening = true; - return true; - }()); - if (!test_hardening) return; - - EXPECT_DEATH_IF_SUPPORTED(cord[5], ""); - EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), ""); - EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), ""); - EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), ""); -} - -class AfterExitCordTester { - public: - bool Set(absl::Cord* cord, absl::string_view expected) { - cord_ = cord; - expected_ = expected; - return true; - } - - ~AfterExitCordTester() { - EXPECT_EQ(*cord_, expected_); - } - private: - absl::Cord* cord_; - absl::string_view expected_; -}; - -template <typename Str> -void TestConstinitConstructor(Str) { - const auto expected = Str::value; - // Defined before `cord` to be destroyed after it. - static AfterExitCordTester exit_tester; // NOLINT - ABSL_CONST_INIT static absl::Cord cord(Str{}); // NOLINT - static bool init_exit_tester = exit_tester.Set(&cord, expected); - (void)init_exit_tester; - - EXPECT_EQ(cord, expected); - // Copy the object and test the copy, and the original. - { - absl::Cord copy = cord; - EXPECT_EQ(copy, expected); - } - // The original still works - EXPECT_EQ(cord, expected); - - // Try making adding more structure to the tree. - { - absl::Cord copy = cord; - std::string expected_copy(expected); - for (int i = 0; i < 10; ++i) { - copy.Append(cord); - absl::StrAppend(&expected_copy, expected); - EXPECT_EQ(copy, expected_copy); - } - } - - // Make sure we are using the right branch during constant evaluation. - EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16); - - for (int i = 0; i < 10; ++i) { - // Make a few more Cords from the same global rep. - // This tests what happens when the refcount for it gets below 1. - EXPECT_EQ(expected, absl::Cord(Str{})); - } -} - -constexpr int SimpleStrlen(const char* p) { - return *p ? 1 + SimpleStrlen(p + 1) : 0; -} - -struct ShortView { - constexpr absl::string_view operator()() const { - return absl::string_view("SSO string", SimpleStrlen("SSO string")); - } -}; - -struct LongView { - constexpr absl::string_view operator()() const { - return absl::string_view("String that does not fit SSO.", - SimpleStrlen("String that does not fit SSO.")); - } -}; - - -TEST(Cord, ConstinitConstructor) { - TestConstinitConstructor( - absl::strings_internal::MakeStringConstant(ShortView{})); - TestConstinitConstructor( - absl::strings_internal::MakeStringConstant(LongView{})); -} diff --git a/third_party/abseil_cpp/absl/strings/cord_test_helpers.h b/third_party/abseil_cpp/absl/strings/cord_test_helpers.h deleted file mode 100644 index f1036e3b1388..000000000000 --- a/third_party/abseil_cpp/absl/strings/cord_test_helpers.h +++ /dev/null @@ -1,60 +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. -// - -#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_ -#define ABSL_STRINGS_CORD_TEST_HELPERS_H_ - -#include "absl/strings/cord.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Creates a multi-segment Cord from an iterable container of strings. The -// resulting Cord is guaranteed to have one segment for every string in the -// container. This allows code to be unit tested with multi-segment Cord -// inputs. -// -// Example: -// -// absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"}); -// EXPECT_FALSE(c.GetFlat(&unused)); -// -// The mechanism by which this Cord is created is an implementation detail. Any -// implementation that produces a multi-segment Cord may produce a flat Cord in -// the future as new optimizations are added to the Cord class. -// MakeFragmentedCord will, however, always be updated to return a multi-segment -// Cord. -template <typename Container> -Cord MakeFragmentedCord(const Container& c) { - Cord result; - for (const auto& s : c) { - auto* external = new std::string(s); - Cord tmp = absl::MakeCordFromExternal( - *external, [external](absl::string_view) { delete external; }); - tmp.Prepend(result); - result = tmp; - } - return result; -} - -inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) { - return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_CORD_TEST_HELPERS_H_ diff --git a/third_party/abseil_cpp/absl/strings/escaping.cc b/third_party/abseil_cpp/absl/strings/escaping.cc deleted file mode 100644 index 18b20b83fd36..000000000000 --- a/third_party/abseil_cpp/absl/strings/escaping.cc +++ /dev/null @@ -1,949 +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/strings/escaping.h" - -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <cstring> -#include <iterator> -#include <limits> -#include <string> - -#include "absl/base/internal/endian.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/unaligned_access.h" -#include "absl/strings/internal/char_map.h" -#include "absl/strings/internal/escaping.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/internal/utf8.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -// These are used for the leave_nulls_escaped argument to CUnescapeInternal(). -constexpr bool kUnescapeNulls = false; - -inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); } - -inline int hex_digit_to_int(char c) { - static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61, - "Character set must be ASCII."); - assert(absl::ascii_isxdigit(c)); - int x = static_cast<unsigned char>(c); - if (x > '9') { - x += 9; - } - return x & 0xf; -} - -inline bool IsSurrogate(char32_t c, absl::string_view src, std::string* error) { - if (c >= 0xD800 && c <= 0xDFFF) { - if (error) { - *error = absl::StrCat("invalid surrogate character (0xD800-DFFF): \\", - src); - } - return true; - } - return false; -} - -// ---------------------------------------------------------------------- -// CUnescapeInternal() -// Implements both CUnescape() and CUnescapeForNullTerminatedString(). -// -// Unescapes C escape sequences and is the reverse of CEscape(). -// -// If 'source' is valid, stores the unescaped string and its size in -// 'dest' and 'dest_len' respectively, and returns true. Otherwise -// returns false and optionally stores the error description in -// 'error'. Set 'error' to nullptr to disable error reporting. -// -// 'dest' should point to a buffer that is at least as big as 'source'. -// 'source' and 'dest' may be the same. -// -// NOTE: any changes to this function must also be reflected in the older -// UnescapeCEscapeSequences(). -// ---------------------------------------------------------------------- -bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped, - char* dest, ptrdiff_t* dest_len, std::string* error) { - char* d = dest; - const char* p = source.data(); - const char* end = p + source.size(); - const char* last_byte = end - 1; - - // Small optimization for case where source = dest and there's no escaping - while (p == d && p < end && *p != '\\') p++, d++; - - while (p < end) { - if (*p != '\\') { - *d++ = *p++; - } else { - if (++p > last_byte) { // skip past the '\\' - if (error) *error = "String cannot end with \\"; - return false; - } - switch (*p) { - case 'a': *d++ = '\a'; break; - case 'b': *d++ = '\b'; break; - case 'f': *d++ = '\f'; break; - case 'n': *d++ = '\n'; break; - case 'r': *d++ = '\r'; break; - case 't': *d++ = '\t'; break; - case 'v': *d++ = '\v'; break; - case '\\': *d++ = '\\'; break; - case '?': *d++ = '\?'; break; // \? Who knew? - case '\'': *d++ = '\''; break; - case '"': *d++ = '\"'; break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': { - // octal digit: 1 to 3 digits - const char* octal_start = p; - unsigned int ch = *p - '0'; - if (p < last_byte && is_octal_digit(p[1])) ch = ch * 8 + *++p - '0'; - if (p < last_byte && is_octal_digit(p[1])) - ch = ch * 8 + *++p - '0'; // now points at last digit - if (ch > 0xff) { - if (error) { - *error = "Value of \\" + - std::string(octal_start, p + 1 - octal_start) + - " exceeds 0xff"; - } - return false; - } - if ((ch == 0) && leave_nulls_escaped) { - // Copy the escape sequence for the null character - const ptrdiff_t octal_size = p + 1 - octal_start; - *d++ = '\\'; - memmove(d, octal_start, octal_size); - d += octal_size; - break; - } - *d++ = ch; - break; - } - case 'x': - case 'X': { - if (p >= last_byte) { - if (error) *error = "String cannot end with \\x"; - return false; - } else if (!absl::ascii_isxdigit(p[1])) { - if (error) *error = "\\x cannot be followed by a non-hex digit"; - return false; - } - unsigned int ch = 0; - const char* hex_start = p; - while (p < last_byte && absl::ascii_isxdigit(p[1])) - // Arbitrarily many hex digits - ch = (ch << 4) + hex_digit_to_int(*++p); - if (ch > 0xFF) { - if (error) { - *error = "Value of \\" + - std::string(hex_start, p + 1 - hex_start) + - " exceeds 0xff"; - } - return false; - } - if ((ch == 0) && leave_nulls_escaped) { - // Copy the escape sequence for the null character - const ptrdiff_t hex_size = p + 1 - hex_start; - *d++ = '\\'; - memmove(d, hex_start, hex_size); - d += hex_size; - break; - } - *d++ = ch; - break; - } - case 'u': { - // \uhhhh => convert 4 hex digits to UTF-8 - char32_t rune = 0; - const char* hex_start = p; - if (p + 4 >= end) { - if (error) { - *error = "\\u must be followed by 4 hex digits: \\" + - std::string(hex_start, p + 1 - hex_start); - } - return false; - } - for (int i = 0; i < 4; ++i) { - // Look one char ahead. - if (absl::ascii_isxdigit(p[1])) { - rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p. - } else { - if (error) { - *error = "\\u must be followed by 4 hex digits: \\" + - std::string(hex_start, p + 1 - hex_start); - } - return false; - } - } - if ((rune == 0) && leave_nulls_escaped) { - // Copy the escape sequence for the null character - *d++ = '\\'; - memmove(d, hex_start, 5); // u0000 - d += 5; - break; - } - if (IsSurrogate(rune, absl::string_view(hex_start, 5), error)) { - return false; - } - d += strings_internal::EncodeUTF8Char(d, rune); - break; - } - case 'U': { - // \Uhhhhhhhh => convert 8 hex digits to UTF-8 - char32_t rune = 0; - const char* hex_start = p; - if (p + 8 >= end) { - if (error) { - *error = "\\U must be followed by 8 hex digits: \\" + - std::string(hex_start, p + 1 - hex_start); - } - return false; - } - for (int i = 0; i < 8; ++i) { - // Look one char ahead. - if (absl::ascii_isxdigit(p[1])) { - // Don't change rune until we're sure this - // is within the Unicode limit, but do advance p. - uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p); - if (newrune > 0x10FFFF) { - if (error) { - *error = "Value of \\" + - std::string(hex_start, p + 1 - hex_start) + - " exceeds Unicode limit (0x10FFFF)"; - } - return false; - } else { - rune = newrune; - } - } else { - if (error) { - *error = "\\U must be followed by 8 hex digits: \\" + - std::string(hex_start, p + 1 - hex_start); - } - return false; - } - } - if ((rune == 0) && leave_nulls_escaped) { - // Copy the escape sequence for the null character - *d++ = '\\'; - memmove(d, hex_start, 9); // U00000000 - d += 9; - break; - } - if (IsSurrogate(rune, absl::string_view(hex_start, 9), error)) { - return false; - } - d += strings_internal::EncodeUTF8Char(d, rune); - break; - } - default: { - if (error) *error = std::string("Unknown escape sequence: \\") + *p; - return false; - } - } - p++; // read past letter we escaped - } - } - *dest_len = d - dest; - return true; -} - -// ---------------------------------------------------------------------- -// CUnescapeInternal() -// -// Same as above but uses a std::string for output. 'source' and 'dest' -// may be the same. -// ---------------------------------------------------------------------- -bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped, - std::string* dest, std::string* error) { - strings_internal::STLStringResizeUninitialized(dest, source.size()); - - ptrdiff_t dest_size; - if (!CUnescapeInternal(source, - leave_nulls_escaped, - &(*dest)[0], - &dest_size, - error)) { - return false; - } - dest->erase(dest_size); - return true; -} - -// ---------------------------------------------------------------------- -// CEscape() -// CHexEscape() -// Utf8SafeCEscape() -// Utf8SafeCHexEscape() -// Escapes 'src' using C-style escape sequences. This is useful for -// preparing query flags. The 'Hex' version uses hexadecimal rather than -// octal sequences. The 'Utf8Safe' version does not touch UTF-8 bytes. -// -// Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint(). -// ---------------------------------------------------------------------- -std::string CEscapeInternal(absl::string_view src, bool use_hex, - bool utf8_safe) { - std::string dest; - bool last_hex_escape = false; // true if last output char was \xNN. - - for (unsigned char c : src) { - bool is_hex_escape = false; - switch (c) { - case '\n': dest.append("\\" "n"); break; - case '\r': dest.append("\\" "r"); break; - case '\t': dest.append("\\" "t"); break; - case '\"': dest.append("\\" "\""); break; - case '\'': dest.append("\\" "'"); break; - case '\\': dest.append("\\" "\\"); break; - default: - // Note that if we emit \xNN and the src character after that is a hex - // digit then that digit must be escaped too to prevent it being - // interpreted as part of the character code by C. - if ((!utf8_safe || c < 0x80) && - (!absl::ascii_isprint(c) || - (last_hex_escape && absl::ascii_isxdigit(c)))) { - if (use_hex) { - dest.append("\\" "x"); - dest.push_back(numbers_internal::kHexChar[c / 16]); - dest.push_back(numbers_internal::kHexChar[c % 16]); - is_hex_escape = true; - } else { - dest.append("\\"); - dest.push_back(numbers_internal::kHexChar[c / 64]); - dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]); - dest.push_back(numbers_internal::kHexChar[c % 8]); - } - } else { - dest.push_back(c); - break; - } - } - last_hex_escape = is_hex_escape; - } - - return dest; -} - -/* clang-format off */ -constexpr char c_escaped_len[256] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", ' - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9' - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O' - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\' - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o' - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, -}; -/* clang-format on */ - -// Calculates the length of the C-style escaped version of 'src'. -// Assumes that non-printable characters are escaped using octal sequences, and -// that UTF-8 bytes are not handled specially. -inline size_t CEscapedLength(absl::string_view src) { - size_t escaped_len = 0; - for (unsigned char c : src) escaped_len += c_escaped_len[c]; - return escaped_len; -} - -void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) { - size_t escaped_len = CEscapedLength(src); - if (escaped_len == src.size()) { - dest->append(src.data(), src.size()); - return; - } - - size_t cur_dest_len = dest->size(); - strings_internal::STLStringResizeUninitialized(dest, - cur_dest_len + escaped_len); - char* append_ptr = &(*dest)[cur_dest_len]; - - for (unsigned char c : src) { - int char_len = c_escaped_len[c]; - if (char_len == 1) { - *append_ptr++ = c; - } else if (char_len == 2) { - switch (c) { - case '\n': - *append_ptr++ = '\\'; - *append_ptr++ = 'n'; - break; - case '\r': - *append_ptr++ = '\\'; - *append_ptr++ = 'r'; - break; - case '\t': - *append_ptr++ = '\\'; - *append_ptr++ = 't'; - break; - case '\"': - *append_ptr++ = '\\'; - *append_ptr++ = '\"'; - break; - case '\'': - *append_ptr++ = '\\'; - *append_ptr++ = '\''; - break; - case '\\': - *append_ptr++ = '\\'; - *append_ptr++ = '\\'; - break; - } - } else { - *append_ptr++ = '\\'; - *append_ptr++ = '0' + c / 64; - *append_ptr++ = '0' + (c % 64) / 8; - *append_ptr++ = '0' + c % 8; - } - } -} - -bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest, - size_t szdest, const signed char* unbase64, - size_t* len) { - static const char kPad64Equals = '='; - static const char kPad64Dot = '.'; - - size_t destidx = 0; - int decode = 0; - int state = 0; - unsigned int ch = 0; - unsigned int temp = 0; - - // If "char" is signed by default, using *src as an array index results in - // accessing negative array elements. Treat the input as a pointer to - // unsigned char to avoid this. - const unsigned char* src = reinterpret_cast<const unsigned char*>(src_param); - - // 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 - // 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. -#define GET_INPUT(label, remain) \ - label: \ - --szsrc; \ - ch = *src++; \ - decode = unbase64[ch]; \ - if (decode < 0) { \ - if (absl::ascii_isspace(ch) && szsrc >= remain) goto label; \ - state = 4 - remain; \ - break; \ - } - - // if dest is null, we're just checking to see if it's legal input - // rather than producing output. (I suspect this could just be done - // with a regexp...). We duplicate the loop so this test can be - // outside it instead of in every iteration. - - 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 - // 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 - // (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). - - if (!src[0] || !src[1] || !src[2] || - ((temp = ((unsigned(unbase64[src[0]]) << 18) | - (unsigned(unbase64[src[1]]) << 12) | - (unsigned(unbase64[src[2]]) << 6) | - (unsigned(unbase64[src[3]])))) & - 0x80000000)) { - // Iff any of those four characters was bad (null, illegal, - // whitespace, padding), then temp's high bit will be set - // (because unbase64[] is -1 for all bad characters). - // - // We'll back up and resort to the slower decoder, which knows - // how to handle those cases. - - GET_INPUT(first, 4); - temp = decode; - GET_INPUT(second, 3); - temp = (temp << 6) | decode; - GET_INPUT(third, 2); - temp = (temp << 6) | decode; - GET_INPUT(fourth, 1); - temp = (temp << 6) | decode; - } else { - // We really did have four good data bytes, so advance four - // characters in the string. - - szsrc -= 4; - src += 4; - } - - // temp has 24 bits of input, so write that out as three bytes. - - if (destidx + 3 > szdest) return false; - dest[destidx + 2] = temp; - temp >>= 8; - dest[destidx + 1] = temp; - temp >>= 8; - dest[destidx] = temp; - destidx += 3; - } - } else { - while (szsrc >= 4) { - if (!src[0] || !src[1] || !src[2] || - ((temp = ((unsigned(unbase64[src[0]]) << 18) | - (unsigned(unbase64[src[1]]) << 12) | - (unsigned(unbase64[src[2]]) << 6) | - (unsigned(unbase64[src[3]])))) & - 0x80000000)) { - GET_INPUT(first_no_dest, 4); - GET_INPUT(second_no_dest, 3); - GET_INPUT(third_no_dest, 2); - GET_INPUT(fourth_no_dest, 1); - } else { - szsrc -= 4; - src += 4; - } - destidx += 3; - } - } - -#undef GET_INPUT - - // if the loop terminated because we read a bad character, return - // now. - if (decode < 0 && ch != kPad64Equals && ch != kPad64Dot && - !absl::ascii_isspace(ch)) - return false; - - if (ch == kPad64Equals || ch == kPad64Dot) { - // if we stopped by hitting an '=' or '.', un-read that character -- we'll - // look at it again when we count to check for the proper number of - // equals signs at the end. - ++szsrc; - --src; - } else { - // This loop consumes 1 input byte per iteration. It's used to - // clean up the 0-3 input bytes remaining when the first, faster - // loop finishes. 'temp' contains the data from 'state' input - // characters read by the first loop. - while (szsrc > 0) { - --szsrc; - ch = *src++; - decode = unbase64[ch]; - if (decode < 0) { - if (absl::ascii_isspace(ch)) { - continue; - } else if (ch == kPad64Equals || ch == kPad64Dot) { - // back up one character; we'll read it again when we check - // for the correct number of pad characters at the end. - ++szsrc; - --src; - break; - } else { - return false; - } - } - - // Each input character gives us six bits of output. - temp = (temp << 6) | decode; - ++state; - if (state == 4) { - // If we've accumulated 24 bits of output, write that out as - // three bytes. - if (dest) { - if (destidx + 3 > szdest) return false; - dest[destidx + 2] = temp; - temp >>= 8; - dest[destidx + 1] = temp; - temp >>= 8; - dest[destidx] = temp; - } - destidx += 3; - state = 0; - temp = 0; - } - } - } - - // Process the leftover data contained in 'temp' at the end of the input. - int expected_equals = 0; - switch (state) { - case 0: - // Nothing left over; output is a multiple of 3 bytes. - break; - - case 1: - // Bad input; we have 6 bits left over. - return false; - - case 2: - // Produce one more output byte from the 12 input bits we have left. - if (dest) { - if (destidx + 1 > szdest) return false; - temp >>= 4; - dest[destidx] = temp; - } - ++destidx; - expected_equals = 2; - break; - - case 3: - // Produce two more output bytes from the 18 input bits we have left. - if (dest) { - if (destidx + 2 > szdest) return false; - temp >>= 2; - dest[destidx + 1] = temp; - temp >>= 8; - dest[destidx] = temp; - } - destidx += 2; - expected_equals = 1; - break; - - default: - // state should have no other values at this point. - ABSL_RAW_LOG(FATAL, "This can't happen; base64 decoder state = %d", - state); - } - - // The remainder of the string should be all whitespace, mixed with - // exactly 0 equals signs, or exactly 'expected_equals' equals - // signs. (Always accepting 0 equals signs is an Abseil extension - // not covered in the RFC, as is accepting dot as the pad character.) - - int equals = 0; - while (szsrc > 0) { - if (*src == kPad64Equals || *src == kPad64Dot) - ++equals; - else if (!absl::ascii_isspace(*src)) - return false; - --szsrc; - ++src; - } - - const bool ok = (equals == 0 || equals == expected_equals); - if (ok) *len = destidx; - return ok; -} - -// The arrays below were generated by the following code -// #include <sys/time.h> -// #include <stdlib.h> -// #include <string.h> -// main() -// { -// static const char Base64[] = -// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -// char* pos; -// int idx, i, j; -// printf(" "); -// for (i = 0; i < 255; i += 8) { -// for (j = i; j < i + 8; j++) { -// pos = strchr(Base64, j); -// if ((pos == nullptr) || (j == 0)) -// idx = -1; -// else -// idx = pos - Base64; -// if (idx == -1) -// printf(" %2d, ", idx); -// else -// printf(" %2d/*%c*/,", idx, j); -// } -// printf("\n "); -// } -// } -// -// where the value of "Base64[]" was replaced by one of the base-64 conversion -// tables from the functions below. -/* clang-format off */ -constexpr signed char kUnBase64[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, - 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, - 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, - -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, - 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, - 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, - -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, - 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, - 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, - 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -constexpr signed char kUnWebSafeBase64[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 62/*-*/, -1, -1, - 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, - 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, - -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, - 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, - 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, - -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, - 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, - 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, - 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; -/* clang-format on */ - -constexpr char kWebSafeBase64Chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - -template <typename String> -bool Base64UnescapeInternal(const char* src, size_t slen, String* dest, - const signed char* unbase64) { - // Determine the size of the output string. Base64 encodes every 3 bytes into - // 4 characters. any leftover chars are added directly for good measure. - // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 - const size_t dest_len = 3 * (slen / 4) + (slen % 4); - - 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 *. - size_t len; - const bool ok = - Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len); - if (!ok) { - dest->clear(); - return false; - } - - // could be shorter if there was padding - assert(len <= dest_len); - dest->erase(len); - - return true; -} - -/* clang-format off */ -constexpr char kHexValueLenient[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9' - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f' - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -/* clang-format on */ - -// This is a templated function so that T can be either a char* -// or a string. This works because we use the [] operator to access -// individual characters at a time. -template <typename T> -void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) { - for (int i = 0; i < num; i++) { - to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) + - (kHexValueLenient[from[i * 2 + 1] & 0xFF]); - } -} - -// This is a templated function so that T can be either a char* or a -// std::string. -template <typename T> -void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) { - auto dest_ptr = &dest[0]; - for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) { - const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2]; - std::copy(hex_p, hex_p + 2, dest_ptr); - } -} - -} // namespace - -// ---------------------------------------------------------------------- -// CUnescape() -// -// See CUnescapeInternal() for implementation details. -// ---------------------------------------------------------------------- -bool CUnescape(absl::string_view source, std::string* dest, - std::string* error) { - return CUnescapeInternal(source, kUnescapeNulls, dest, error); -} - -std::string CEscape(absl::string_view src) { - std::string dest; - CEscapeAndAppendInternal(src, &dest); - return dest; -} - -std::string CHexEscape(absl::string_view src) { - return CEscapeInternal(src, true, false); -} - -std::string Utf8SafeCEscape(absl::string_view src) { - return CEscapeInternal(src, false, true); -} - -std::string Utf8SafeCHexEscape(absl::string_view src) { - return CEscapeInternal(src, true, true); -} - -// ---------------------------------------------------------------------- -// Base64Unescape() - base64 decoder -// Base64Escape() - base64 encoder -// WebSafeBase64Unescape() - Google's variation of base64 decoder -// WebSafeBase64Escape() - Google's variation of base64 encoder -// -// Check out -// http://tools.ietf.org/html/rfc2045 for formal description, but what we -// care about is that... -// Take the encoded stuff in groups of 4 characters and turn each -// character into a code 0 to 63 thus: -// A-Z map to 0 to 25 -// a-z map to 26 to 51 -// 0-9 map to 52 to 61 -// +(- for WebSafe) maps to 62 -// /(_ for WebSafe) maps to 63 -// There will be four numbers, all less than 64 which can be represented -// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively). -// Arrange the 6 digit binary numbers into three bytes as such: -// aaaaaabb bbbbcccc ccdddddd -// Equals signs (one or two) are used at the end of the encoded block to -// indicate that the text was not an integer multiple of three bytes long. -// ---------------------------------------------------------------------- - -bool Base64Unescape(absl::string_view src, std::string* dest) { - return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); -} - -bool WebSafeBase64Unescape(absl::string_view src, std::string* dest) { - return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); -} - -void Base64Escape(absl::string_view src, std::string* dest) { - strings_internal::Base64EscapeInternal( - reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest, - true, strings_internal::kBase64Chars); -} - -void WebSafeBase64Escape(absl::string_view src, std::string* dest) { - strings_internal::Base64EscapeInternal( - reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest, - false, kWebSafeBase64Chars); -} - -std::string Base64Escape(absl::string_view src) { - std::string dest; - strings_internal::Base64EscapeInternal( - reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest, - true, strings_internal::kBase64Chars); - return dest; -} - -std::string WebSafeBase64Escape(absl::string_view src) { - std::string dest; - strings_internal::Base64EscapeInternal( - reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest, - false, kWebSafeBase64Chars); - return dest; -} - -std::string HexStringToBytes(absl::string_view from) { - std::string result; - const auto num = from.size() / 2; - strings_internal::STLStringResizeUninitialized(&result, num); - absl::HexStringToBytesInternal<std::string&>(from.data(), result, num); - return result; -} - -std::string BytesToHexString(absl::string_view from) { - std::string result; - strings_internal::STLStringResizeUninitialized(&result, 2 * from.size()); - absl::BytesToHexStringInternal<std::string&>( - reinterpret_cast<const unsigned char*>(from.data()), result, from.size()); - return result; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/escaping.h b/third_party/abseil_cpp/absl/strings/escaping.h deleted file mode 100644 index f5ca26c5dadb..000000000000 --- a/third_party/abseil_cpp/absl/strings/escaping.h +++ /dev/null @@ -1,164 +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. -// -// ----------------------------------------------------------------------------- -// File: escaping.h -// ----------------------------------------------------------------------------- -// -// This header file contains string utilities involved in escaping and -// unescaping strings in various ways. - -#ifndef ABSL_STRINGS_ESCAPING_H_ -#define ABSL_STRINGS_ESCAPING_H_ - -#include <cstddef> -#include <string> -#include <vector> - -#include "absl/base/macros.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_join.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// CUnescape() -// -// Unescapes a `source` string and copies it into `dest`, rewriting C-style -// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into -// their proper code point equivalents, returning `true` if successful. -// -// The following unescape sequences can be handled: -// -// * ASCII escape sequences ('\n','\r','\\', etc.) to their ASCII equivalents -// * Octal escape sequences ('\nnn') to byte nnn. The unescaped value must -// resolve to a single byte or an error will occur. E.g. values greater than -// 0xff will produce an error. -// * Hexadecimal escape sequences ('\xnn') to byte nn. While an arbitrary -// number of following digits are allowed, the unescaped value must resolve -// to a single byte or an error will occur. E.g. '\x0045' is equivalent to -// '\x45', but '\x1234' will produce an error. -// * Unicode escape sequences ('\unnnn' for exactly four hex digits or -// '\Unnnnnnnn' for exactly eight hex digits, which will be encoded in -// UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and -// 0x99). -// -// If any errors are encountered, this function returns `false`, leaving the -// `dest` output parameter in an unspecified state, and stores the first -// encountered error in `error`. To disable error reporting, set `error` to -// `nullptr` or use the overload with no error reporting below. -// -// Example: -// -// std::string s = "foo\\rbar\\nbaz\\t"; -// std::string unescaped_s; -// if (!absl::CUnescape(s, &unescaped_s) { -// ... -// } -// EXPECT_EQ(unescaped_s, "foo\rbar\nbaz\t"); -bool CUnescape(absl::string_view source, std::string* dest, std::string* error); - -// Overload of `CUnescape()` with no error reporting. -inline bool CUnescape(absl::string_view source, std::string* dest) { - return CUnescape(source, dest, nullptr); -} - -// CEscape() -// -// Escapes a 'src' string using C-style escapes sequences -// (https://en.cppreference.com/w/cpp/language/escape), escaping other -// non-printable/non-whitespace bytes as octal sequences (e.g. "\377"). -// -// Example: -// -// std::string s = "foo\rbar\tbaz\010\011\012\013\014\x0d\n"; -// std::string escaped_s = absl::CEscape(s); -// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\010\\t\\n\\013\\014\\r\\n"); -std::string CEscape(absl::string_view src); - -// CHexEscape() -// -// Escapes a 'src' string using C-style escape sequences, escaping -// other non-printable/non-whitespace bytes as hexadecimal sequences (e.g. -// "\xFF"). -// -// Example: -// -// std::string s = "foo\rbar\tbaz\010\011\012\013\014\x0d\n"; -// std::string escaped_s = absl::CHexEscape(s); -// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\x08\\t\\n\\x0b\\x0c\\r\\n"); -std::string CHexEscape(absl::string_view src); - -// Utf8SafeCEscape() -// -// Escapes a 'src' string using C-style escape sequences, escaping bytes as -// octal sequences, and passing through UTF-8 characters without conversion. -// I.e., when encountering any bytes with their high bit set, this function -// will not escape those values, whether or not they are valid UTF-8. -std::string Utf8SafeCEscape(absl::string_view src); - -// Utf8SafeCHexEscape() -// -// Escapes a 'src' string using C-style escape sequences, escaping bytes as -// hexadecimal sequences, and passing through UTF-8 characters without -// conversion. -std::string Utf8SafeCHexEscape(absl::string_view src); - -// Base64Unescape() -// -// Converts a `src` string encoded in Base64 to its binary equivalent, writing -// it to a `dest` buffer, returning `true` on success. If `src` contains invalid -// characters, `dest` is cleared and returns `false`. -bool Base64Unescape(absl::string_view src, std::string* dest); - -// WebSafeBase64Unescape() -// -// Converts a `src` string encoded in Base64 to its binary equivalent, writing -// it to a `dest` buffer, but using '-' instead of '+', and '_' instead of '/'. -// If `src` contains invalid characters, `dest` is cleared and returns `false`. -bool WebSafeBase64Unescape(absl::string_view src, std::string* dest); - -// Base64Escape() -// -// Encodes a `src` string into a base64-encoded string, with padding characters. -// This function conforms with RFC 4648 section 4 (base64). -void Base64Escape(absl::string_view src, std::string* dest); -std::string Base64Escape(absl::string_view src); - -// WebSafeBase64Escape() -// -// Encodes a `src` string into a base64-like string, using '-' instead of '+' -// and '_' instead of '/', and without padding. This function conforms with RFC -// 4648 section 5 (base64url). -void WebSafeBase64Escape(absl::string_view src, std::string* dest); -std::string WebSafeBase64Escape(absl::string_view src); - -// HexStringToBytes() -// -// Converts an ASCII hex string into bytes, returning binary data of length -// `from.size()/2`. -std::string HexStringToBytes(absl::string_view from); - -// BytesToHexString() -// -// Converts binary data into an ASCII text string, returning a string of size -// `2*from.size()`. -std::string BytesToHexString(absl::string_view from); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_ESCAPING_H_ diff --git a/third_party/abseil_cpp/absl/strings/escaping_benchmark.cc b/third_party/abseil_cpp/absl/strings/escaping_benchmark.cc deleted file mode 100644 index 10d5b033c520..000000000000 --- a/third_party/abseil_cpp/absl/strings/escaping_benchmark.cc +++ /dev/null @@ -1,94 +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/strings/escaping.h" - -#include <cstdio> -#include <cstring> -#include <random> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/internal/escaping_test_common.h" - -namespace { - -void BM_CUnescapeHexString(benchmark::State& state) { - std::string src; - for (int i = 0; i < 50; i++) { - src += "\\x55"; - } - std::string dest; - for (auto _ : state) { - absl::CUnescape(src, &dest); - } -} -BENCHMARK(BM_CUnescapeHexString); - -void BM_WebSafeBase64Escape_string(benchmark::State& state) { - std::string raw; - for (int i = 0; i < 10; ++i) { - for (const auto& test_set : absl::strings_internal::base64_strings()) { - raw += std::string(test_set.plaintext); - } - } - - // The actual benchmark loop is tiny... - std::string escaped; - for (auto _ : state) { - absl::WebSafeBase64Escape(raw, &escaped); - } - - // We want to be sure the compiler doesn't throw away the loop above, - // and the easiest way to ensure that is to round-trip the results and verify - // them. - std::string round_trip; - absl::WebSafeBase64Unescape(escaped, &round_trip); - ABSL_RAW_CHECK(round_trip == raw, ""); -} -BENCHMARK(BM_WebSafeBase64Escape_string); - -// Used for the CEscape benchmarks -const char kStringValueNoEscape[] = "1234567890"; -const char kStringValueSomeEscaped[] = "123\n56789\xA1"; -const char kStringValueMostEscaped[] = "\xA1\xA2\ny\xA4\xA5\xA6z\b\r"; - -void CEscapeBenchmarkHelper(benchmark::State& state, const char* string_value, - int max_len) { - std::string src; - while (src.size() < max_len) { - absl::StrAppend(&src, string_value); - } - - for (auto _ : state) { - absl::CEscape(src); - } -} - -void BM_CEscape_NoEscape(benchmark::State& state) { - CEscapeBenchmarkHelper(state, kStringValueNoEscape, state.range(0)); -} -BENCHMARK(BM_CEscape_NoEscape)->Range(1, 1 << 14); - -void BM_CEscape_SomeEscaped(benchmark::State& state) { - CEscapeBenchmarkHelper(state, kStringValueSomeEscaped, state.range(0)); -} -BENCHMARK(BM_CEscape_SomeEscaped)->Range(1, 1 << 14); - -void BM_CEscape_MostEscaped(benchmark::State& state) { - CEscapeBenchmarkHelper(state, kStringValueMostEscaped, state.range(0)); -} -BENCHMARK(BM_CEscape_MostEscaped)->Range(1, 1 << 14); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/escaping_test.cc b/third_party/abseil_cpp/absl/strings/escaping_test.cc deleted file mode 100644 index 45671a0ed598..000000000000 --- a/third_party/abseil_cpp/absl/strings/escaping_test.cc +++ /dev/null @@ -1,664 +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/strings/escaping.h" - -#include <array> -#include <cstdio> -#include <cstring> -#include <memory> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/fixed_array.h" -#include "absl/strings/str_cat.h" - -#include "absl/strings/internal/escaping_test_common.h" - -namespace { - -struct epair { - std::string escaped; - std::string unescaped; -}; - -TEST(CEscape, EscapeAndUnescape) { - const std::string inputs[] = { - std::string("foo\nxx\r\b\0023"), - std::string(""), - std::string("abc"), - std::string("\1chad_rules"), - std::string("\1arnar_drools"), - std::string("xxxx\r\t'\"\\"), - std::string("\0xx\0", 4), - std::string("\x01\x31"), - std::string("abc\xb\x42\141bc"), - std::string("123\1\x31\x32\x33"), - std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"), - std::string( - "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"), - }; - // Do this twice, once for octal escapes and once for hex escapes. - for (int kind = 0; kind < 4; kind++) { - for (const std::string& original : inputs) { - std::string escaped; - switch (kind) { - case 0: - escaped = absl::CEscape(original); - break; - case 1: - escaped = absl::CHexEscape(original); - break; - case 2: - escaped = absl::Utf8SafeCEscape(original); - break; - case 3: - escaped = absl::Utf8SafeCHexEscape(original); - break; - } - std::string unescaped_str; - EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str)); - EXPECT_EQ(unescaped_str, original); - - unescaped_str.erase(); - std::string error; - EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str, &error)); - EXPECT_EQ(error, ""); - - // Check in-place unescaping - std::string s = escaped; - EXPECT_TRUE(absl::CUnescape(s, &s)); - ASSERT_EQ(s, original); - } - } - // Check that all possible two character strings can be escaped then - // unescaped successfully. - for (int char0 = 0; char0 < 256; char0++) { - for (int char1 = 0; char1 < 256; char1++) { - char chars[2]; - chars[0] = char0; - chars[1] = char1; - std::string s(chars, 2); - std::string escaped = absl::CHexEscape(s); - std::string unescaped; - EXPECT_TRUE(absl::CUnescape(escaped, &unescaped)); - EXPECT_EQ(s, unescaped); - } - } -} - -TEST(CEscape, BasicEscaping) { - epair oct_values[] = { - {"foo\\rbar\\nbaz\\t", "foo\rbar\nbaz\t"}, - {"\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", - "'full of \"sound\" and \"fury\"'"}, - {"signi\\\\fying\\\\ nothing\\\\", "signi\\fying\\ nothing\\"}, - {"\\010\\t\\n\\013\\014\\r", "\010\011\012\013\014\015"} - }; - epair hex_values[] = { - {"ubik\\rubik\\nubik\\t", "ubik\rubik\nubik\t"}, - {"I\\\'ve just seen a \\\"face\\\"", - "I've just seen a \"face\""}, - {"hel\\\\ter\\\\skel\\\\ter\\\\", "hel\\ter\\skel\\ter\\"}, - {"\\x08\\t\\n\\x0b\\x0c\\r", "\010\011\012\013\014\015"} - }; - epair utf8_oct_values[] = { - {"\xe8\xb0\xb7\xe6\xad\x8c\\r\xe8\xb0\xb7\xe6\xad\x8c\\nbaz\\t", - "\xe8\xb0\xb7\xe6\xad\x8c\r\xe8\xb0\xb7\xe6\xad\x8c\nbaz\t"}, - {"\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name", - "\"\xe8\xb0\xb7\xe6\xad\x8c\" is Google\'s Chinese name"}, - {"\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\\\are\\\\Japanese\\\\chars\\\\", - "\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\are\\Japanese\\chars\\"}, - {"\xed\x81\xac\xeb\xa1\xac\\010\\t\\n\\013\\014\\r", - "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"} - }; - epair utf8_hex_values[] = { - {"\x20\xe4\xbd\xa0\\t\xe5\xa5\xbd,\\r!\\n", - "\x20\xe4\xbd\xa0\t\xe5\xa5\xbd,\r!\n"}, - {"\xe8\xa9\xa6\xe9\xa8\x93\\\' means \\\"test\\\"", - "\xe8\xa9\xa6\xe9\xa8\x93\' means \"test\""}, - {"\\\\\xe6\x88\x91\\\\:\\\\\xe6\x9d\xa8\xe6\xac\xa2\\\\", - "\\\xe6\x88\x91\\:\\\xe6\x9d\xa8\xe6\xac\xa2\\"}, - {"\xed\x81\xac\xeb\xa1\xac\\x08\\t\\n\\x0b\\x0c\\r", - "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"} - }; - - for (const epair& val : oct_values) { - std::string escaped = absl::CEscape(val.unescaped); - EXPECT_EQ(escaped, val.escaped); - } - for (const epair& val : hex_values) { - std::string escaped = absl::CHexEscape(val.unescaped); - EXPECT_EQ(escaped, val.escaped); - } - for (const epair& val : utf8_oct_values) { - std::string escaped = absl::Utf8SafeCEscape(val.unescaped); - EXPECT_EQ(escaped, val.escaped); - } - for (const epair& val : utf8_hex_values) { - std::string escaped = absl::Utf8SafeCHexEscape(val.unescaped); - EXPECT_EQ(escaped, val.escaped); - } -} - -TEST(Unescape, BasicFunction) { - epair tests[] = - {{"", ""}, - {"\\u0030", "0"}, - {"\\u00A3", "\xC2\xA3"}, - {"\\u22FD", "\xE2\x8B\xBD"}, - {"\\U00010000", "\xF0\x90\x80\x80"}, - {"\\U0010FFFD", "\xF4\x8F\xBF\xBD"}}; - for (const epair& val : tests) { - std::string out; - EXPECT_TRUE(absl::CUnescape(val.escaped, &out)); - EXPECT_EQ(out, val.unescaped); - } - std::string bad[] = {"\\u1", // too short - "\\U1", // too short - "\\Uffffff", // exceeds 0x10ffff (largest Unicode) - "\\U00110000", // exceeds 0x10ffff (largest Unicode) - "\\uD835", // surrogate character (D800-DFFF) - "\\U0000DD04", // surrogate character (D800-DFFF) - "\\777", // exceeds 0xff - "\\xABCD"}; // exceeds 0xff - for (const std::string& e : bad) { - std::string error; - std::string out; - EXPECT_FALSE(absl::CUnescape(e, &out, &error)); - EXPECT_FALSE(error.empty()); - - out.erase(); - EXPECT_FALSE(absl::CUnescape(e, &out)); - } -} - -class CUnescapeTest : public testing::Test { - protected: - static const char kStringWithMultipleOctalNulls[]; - static const char kStringWithMultipleHexNulls[]; - static const char kStringWithMultipleUnicodeNulls[]; - - std::string result_string_; -}; - -const char CUnescapeTest::kStringWithMultipleOctalNulls[] = - "\\0\\n" // null escape \0 plus newline - "0\\n" // just a number 0 (not a null escape) plus newline - "\\00\\12" // null escape \00 plus octal newline code - "\\000"; // null escape \000 - -// This has the same ingredients as kStringWithMultipleOctalNulls -// but with \x hex escapes instead of octal escapes. -const char CUnescapeTest::kStringWithMultipleHexNulls[] = - "\\x0\\n" - "0\\n" - "\\x00\\xa" - "\\x000"; - -const char CUnescapeTest::kStringWithMultipleUnicodeNulls[] = - "\\u0000\\n" // short-form (4-digit) null escape plus newline - "0\\n" // just a number 0 (not a null escape) plus newline - "\\U00000000"; // long-form (8-digit) null escape - -TEST_F(CUnescapeTest, Unescapes1CharOctalNull) { - std::string original_string = "\\0"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes2CharOctalNull) { - std::string original_string = "\\00"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes3CharOctalNull) { - std::string original_string = "\\000"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes1CharHexNull) { - std::string original_string = "\\x0"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes2CharHexNull) { - std::string original_string = "\\x00"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes3CharHexNull) { - std::string original_string = "\\x000"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes4CharUnicodeNull) { - std::string original_string = "\\u0000"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, Unescapes8CharUnicodeNull) { - std::string original_string = "\\U00000000"; - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0", 1), result_string_); -} - -TEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) { - std::string original_string(kStringWithMultipleOctalNulls); - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - // All escapes, including newlines and null escapes, should have been - // converted to the equivalent characters. - EXPECT_EQ(std::string("\0\n" - "0\n" - "\0\n" - "\0", - 7), - result_string_); -} - - -TEST_F(CUnescapeTest, UnescapesMultipleHexNulls) { - std::string original_string(kStringWithMultipleHexNulls); - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0\n" - "0\n" - "\0\n" - "\0", - 7), - result_string_); -} - -TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) { - std::string original_string(kStringWithMultipleUnicodeNulls); - EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); - EXPECT_EQ(std::string("\0\n" - "0\n" - "\0", - 5), - result_string_); -} - -static struct { - absl::string_view plaintext; - absl::string_view cyphertext; -} const base64_tests[] = { - // Empty string. - {{"", 0}, {"", 0}}, - {{nullptr, 0}, - {"", 0}}, // if length is zero, plaintext ptr must be ignored! - - // Basic bit patterns; - // values obtained with "echo -n '...' | uuencode -m test" - - {{"\000", 1}, "AA=="}, - {{"\001", 1}, "AQ=="}, - {{"\002", 1}, "Ag=="}, - {{"\004", 1}, "BA=="}, - {{"\010", 1}, "CA=="}, - {{"\020", 1}, "EA=="}, - {{"\040", 1}, "IA=="}, - {{"\100", 1}, "QA=="}, - {{"\200", 1}, "gA=="}, - - {{"\377", 1}, "/w=="}, - {{"\376", 1}, "/g=="}, - {{"\375", 1}, "/Q=="}, - {{"\373", 1}, "+w=="}, - {{"\367", 1}, "9w=="}, - {{"\357", 1}, "7w=="}, - {{"\337", 1}, "3w=="}, - {{"\277", 1}, "vw=="}, - {{"\177", 1}, "fw=="}, - {{"\000\000", 2}, "AAA="}, - {{"\000\001", 2}, "AAE="}, - {{"\000\002", 2}, "AAI="}, - {{"\000\004", 2}, "AAQ="}, - {{"\000\010", 2}, "AAg="}, - {{"\000\020", 2}, "ABA="}, - {{"\000\040", 2}, "ACA="}, - {{"\000\100", 2}, "AEA="}, - {{"\000\200", 2}, "AIA="}, - {{"\001\000", 2}, "AQA="}, - {{"\002\000", 2}, "AgA="}, - {{"\004\000", 2}, "BAA="}, - {{"\010\000", 2}, "CAA="}, - {{"\020\000", 2}, "EAA="}, - {{"\040\000", 2}, "IAA="}, - {{"\100\000", 2}, "QAA="}, - {{"\200\000", 2}, "gAA="}, - - {{"\377\377", 2}, "//8="}, - {{"\377\376", 2}, "//4="}, - {{"\377\375", 2}, "//0="}, - {{"\377\373", 2}, "//s="}, - {{"\377\367", 2}, "//c="}, - {{"\377\357", 2}, "/+8="}, - {{"\377\337", 2}, "/98="}, - {{"\377\277", 2}, "/78="}, - {{"\377\177", 2}, "/38="}, - {{"\376\377", 2}, "/v8="}, - {{"\375\377", 2}, "/f8="}, - {{"\373\377", 2}, "+/8="}, - {{"\367\377", 2}, "9/8="}, - {{"\357\377", 2}, "7/8="}, - {{"\337\377", 2}, "3/8="}, - {{"\277\377", 2}, "v/8="}, - {{"\177\377", 2}, "f/8="}, - - {{"\000\000\000", 3}, "AAAA"}, - {{"\000\000\001", 3}, "AAAB"}, - {{"\000\000\002", 3}, "AAAC"}, - {{"\000\000\004", 3}, "AAAE"}, - {{"\000\000\010", 3}, "AAAI"}, - {{"\000\000\020", 3}, "AAAQ"}, - {{"\000\000\040", 3}, "AAAg"}, - {{"\000\000\100", 3}, "AABA"}, - {{"\000\000\200", 3}, "AACA"}, - {{"\000\001\000", 3}, "AAEA"}, - {{"\000\002\000", 3}, "AAIA"}, - {{"\000\004\000", 3}, "AAQA"}, - {{"\000\010\000", 3}, "AAgA"}, - {{"\000\020\000", 3}, "ABAA"}, - {{"\000\040\000", 3}, "ACAA"}, - {{"\000\100\000", 3}, "AEAA"}, - {{"\000\200\000", 3}, "AIAA"}, - {{"\001\000\000", 3}, "AQAA"}, - {{"\002\000\000", 3}, "AgAA"}, - {{"\004\000\000", 3}, "BAAA"}, - {{"\010\000\000", 3}, "CAAA"}, - {{"\020\000\000", 3}, "EAAA"}, - {{"\040\000\000", 3}, "IAAA"}, - {{"\100\000\000", 3}, "QAAA"}, - {{"\200\000\000", 3}, "gAAA"}, - - {{"\377\377\377", 3}, "////"}, - {{"\377\377\376", 3}, "///+"}, - {{"\377\377\375", 3}, "///9"}, - {{"\377\377\373", 3}, "///7"}, - {{"\377\377\367", 3}, "///3"}, - {{"\377\377\357", 3}, "///v"}, - {{"\377\377\337", 3}, "///f"}, - {{"\377\377\277", 3}, "//+/"}, - {{"\377\377\177", 3}, "//9/"}, - {{"\377\376\377", 3}, "//7/"}, - {{"\377\375\377", 3}, "//3/"}, - {{"\377\373\377", 3}, "//v/"}, - {{"\377\367\377", 3}, "//f/"}, - {{"\377\357\377", 3}, "/+//"}, - {{"\377\337\377", 3}, "/9//"}, - {{"\377\277\377", 3}, "/7//"}, - {{"\377\177\377", 3}, "/3//"}, - {{"\376\377\377", 3}, "/v//"}, - {{"\375\377\377", 3}, "/f//"}, - {{"\373\377\377", 3}, "+///"}, - {{"\367\377\377", 3}, "9///"}, - {{"\357\377\377", 3}, "7///"}, - {{"\337\377\377", 3}, "3///"}, - {{"\277\377\377", 3}, "v///"}, - {{"\177\377\377", 3}, "f///"}, - - // Random numbers: values obtained with - // - // #! /bin/bash - // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random - // od -N $1 -t o1 /tmp/bar.random - // uuencode -m test < /tmp/bar.random - // - // where $1 is the number of bytes (2, 3) - - {{"\243\361", 2}, "o/E="}, - {{"\024\167", 2}, "FHc="}, - {{"\313\252", 2}, "y6o="}, - {{"\046\041", 2}, "JiE="}, - {{"\145\236", 2}, "ZZ4="}, - {{"\254\325", 2}, "rNU="}, - {{"\061\330", 2}, "Mdg="}, - {{"\245\032", 2}, "pRo="}, - {{"\006\000", 2}, "BgA="}, - {{"\375\131", 2}, "/Vk="}, - {{"\303\210", 2}, "w4g="}, - {{"\040\037", 2}, "IB8="}, - {{"\261\372", 2}, "sfo="}, - {{"\335\014", 2}, "3Qw="}, - {{"\233\217", 2}, "m48="}, - {{"\373\056", 2}, "+y4="}, - {{"\247\232", 2}, "p5o="}, - {{"\107\053", 2}, "Rys="}, - {{"\204\077", 2}, "hD8="}, - {{"\276\211", 2}, "vok="}, - {{"\313\110", 2}, "y0g="}, - {{"\363\376", 2}, "8/4="}, - {{"\251\234", 2}, "qZw="}, - {{"\103\262", 2}, "Q7I="}, - {{"\142\312", 2}, "Yso="}, - {{"\067\211", 2}, "N4k="}, - {{"\220\001", 2}, "kAE="}, - {{"\152\240", 2}, "aqA="}, - {{"\367\061", 2}, "9zE="}, - {{"\133\255", 2}, "W60="}, - {{"\176\035", 2}, "fh0="}, - {{"\032\231", 2}, "Gpk="}, - - {{"\013\007\144", 3}, "Cwdk"}, - {{"\030\112\106", 3}, "GEpG"}, - {{"\047\325\046", 3}, "J9Um"}, - {{"\310\160\022", 3}, "yHAS"}, - {{"\131\100\237", 3}, "WUCf"}, - {{"\064\342\134", 3}, "NOJc"}, - {{"\010\177\004", 3}, "CH8E"}, - {{"\345\147\205", 3}, "5WeF"}, - {{"\300\343\360", 3}, "wOPw"}, - {{"\061\240\201", 3}, "MaCB"}, - {{"\225\333\044", 3}, "ldsk"}, - {{"\215\137\352", 3}, "jV/q"}, - {{"\371\147\160", 3}, "+Wdw"}, - {{"\030\320\051", 3}, "GNAp"}, - {{"\044\174\241", 3}, "JHyh"}, - {{"\260\127\037", 3}, "sFcf"}, - {{"\111\045\033", 3}, "SSUb"}, - {{"\202\114\107", 3}, "gkxH"}, - {{"\057\371\042", 3}, "L/ki"}, - {{"\223\247\244", 3}, "k6ek"}, - {{"\047\216\144", 3}, "J45k"}, - {{"\203\070\327", 3}, "gzjX"}, - {{"\247\140\072", 3}, "p2A6"}, - {{"\124\115\116", 3}, "VE1O"}, - {{"\157\162\050", 3}, "b3Io"}, - {{"\357\223\004", 3}, "75ME"}, - {{"\052\117\156", 3}, "Kk9u"}, - {{"\347\154\000", 3}, "52wA"}, - {{"\303\012\142", 3}, "wwpi"}, - {{"\060\035\362", 3}, "MB3y"}, - {{"\130\226\361", 3}, "WJbx"}, - {{"\173\013\071", 3}, "ews5"}, - {{"\336\004\027", 3}, "3gQX"}, - {{"\357\366\234", 3}, "7/ac"}, - {{"\353\304\111", 3}, "68RJ"}, - {{"\024\264\131", 3}, "FLRZ"}, - {{"\075\114\251", 3}, "PUyp"}, - {{"\315\031\225", 3}, "zRmV"}, - {{"\154\201\276", 3}, "bIG+"}, - {{"\200\066\072", 3}, "gDY6"}, - {{"\142\350\267", 3}, "Yui3"}, - {{"\033\000\166", 3}, "GwB2"}, - {{"\210\055\077", 3}, "iC0/"}, - {{"\341\037\124", 3}, "4R9U"}, - {{"\161\103\152", 3}, "cUNq"}, - {{"\270\142\131", 3}, "uGJZ"}, - {{"\337\076\074", 3}, "3z48"}, - {{"\375\106\362", 3}, "/Uby"}, - {{"\227\301\127", 3}, "l8FX"}, - {{"\340\002\234", 3}, "4AKc"}, - {{"\121\064\033", 3}, "UTQb"}, - {{"\157\134\143", 3}, "b1xj"}, - {{"\247\055\327", 3}, "py3X"}, - {{"\340\142\005", 3}, "4GIF"}, - {{"\060\260\143", 3}, "MLBj"}, - {{"\075\203\170", 3}, "PYN4"}, - {{"\143\160\016", 3}, "Y3AO"}, - {{"\313\013\063", 3}, "ywsz"}, - {{"\174\236\135", 3}, "fJ5d"}, - {{"\103\047\026", 3}, "QycW"}, - {{"\365\005\343", 3}, "9QXj"}, - {{"\271\160\223", 3}, "uXCT"}, - {{"\362\255\172", 3}, "8q16"}, - {{"\113\012\015", 3}, "SwoN"}, - - // various lengths, generated by this python script: - // - // from std::string import lowercase as lc - // for i in range(27): - // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i), - // lc[:i].encode('base64').strip()) - - {{"", 0}, {"", 0}}, - {"a", "YQ=="}, - {"ab", "YWI="}, - {"abc", "YWJj"}, - {"abcd", "YWJjZA=="}, - {"abcde", "YWJjZGU="}, - {"abcdef", "YWJjZGVm"}, - {"abcdefg", "YWJjZGVmZw=="}, - {"abcdefgh", "YWJjZGVmZ2g="}, - {"abcdefghi", "YWJjZGVmZ2hp"}, - {"abcdefghij", "YWJjZGVmZ2hpag=="}, - {"abcdefghijk", "YWJjZGVmZ2hpams="}, - {"abcdefghijkl", "YWJjZGVmZ2hpamts"}, - {"abcdefghijklm", "YWJjZGVmZ2hpamtsbQ=="}, - {"abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4="}, - {"abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v"}, - {"abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA=="}, - {"abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE="}, - {"abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy"}, - {"abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw=="}, - {"abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q="}, - {"abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1"}, - {"abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg=="}, - {"abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc="}, - {"abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"}, - {"abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ=="}, - {"abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="}, -}; - -template <typename StringType> -void TestEscapeAndUnescape() { - // Check the short strings; this tests the math (and boundaries) - for (const auto& tc : base64_tests) { - StringType encoded("this junk should be ignored"); - absl::Base64Escape(tc.plaintext, &encoded); - EXPECT_EQ(encoded, tc.cyphertext); - EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext); - - StringType decoded("this junk should be ignored"); - EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded)); - EXPECT_EQ(decoded, tc.plaintext); - - StringType websafe(tc.cyphertext); - for (int c = 0; c < websafe.size(); ++c) { - if ('+' == websafe[c]) websafe[c] = '-'; - if ('/' == websafe[c]) websafe[c] = '_'; - if ('=' == websafe[c]) { - websafe.resize(c); - break; - } - } - - encoded = "this junk should be ignored"; - absl::WebSafeBase64Escape(tc.plaintext, &encoded); - EXPECT_EQ(encoded, websafe); - EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe); - - // Let's try the string version of the decoder - decoded = "this junk should be ignored"; - EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded)); - EXPECT_EQ(decoded, tc.plaintext); - } - - // Now try the long strings, this tests the streaming - for (const auto& tc : absl::strings_internal::base64_strings()) { - StringType buffer; - absl::WebSafeBase64Escape(tc.plaintext, &buffer); - EXPECT_EQ(tc.cyphertext, buffer); - EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext); - } - - // Verify the behavior when decoding bad data - { - absl::string_view data_set[] = {"ab-/", absl::string_view("\0bcd", 4), - absl::string_view("abc.\0", 5)}; - for (absl::string_view bad_data : data_set) { - StringType buf; - EXPECT_FALSE(absl::Base64Unescape(bad_data, &buf)); - EXPECT_FALSE(absl::WebSafeBase64Unescape(bad_data, &buf)); - EXPECT_TRUE(buf.empty()); - } - } -} - -TEST(Base64, EscapeAndUnescape) { - TestEscapeAndUnescape<std::string>(); -} - -TEST(Base64, DISABLED_HugeData) { - const size_t kSize = size_t(3) * 1000 * 1000 * 1000; - static_assert(kSize % 3 == 0, "kSize must be divisible by 3"); - const std::string huge(kSize, 'x'); - - std::string escaped; - absl::Base64Escape(huge, &escaped); - - // Generates the string that should match a base64 encoded "xxx..." string. - // "xxx" in base64 is "eHh4". - std::string expected_encoding; - expected_encoding.reserve(kSize / 3 * 4); - for (size_t i = 0; i < kSize / 3; ++i) { - expected_encoding.append("eHh4"); - } - EXPECT_EQ(expected_encoding, escaped); - - std::string unescaped; - EXPECT_TRUE(absl::Base64Unescape(escaped, &unescaped)); - EXPECT_EQ(huge, unescaped); -} - -TEST(HexAndBack, HexStringToBytes_and_BytesToHexString) { - std::string hex_mixed = "0123456789abcdefABCDEF"; - std::string bytes_expected = "\x01\x23\x45\x67\x89\xab\xcd\xef\xAB\xCD\xEF"; - std::string hex_only_lower = "0123456789abcdefabcdef"; - - std::string bytes_result = absl::HexStringToBytes(hex_mixed); - EXPECT_EQ(bytes_expected, bytes_result); - - std::string prefix_valid = hex_mixed + "?"; - std::string prefix_valid_result = absl::HexStringToBytes( - absl::string_view(prefix_valid.data(), prefix_valid.size() - 1)); - EXPECT_EQ(bytes_expected, prefix_valid_result); - - std::string infix_valid = "?" + hex_mixed + "???"; - std::string infix_valid_result = absl::HexStringToBytes( - absl::string_view(infix_valid.data() + 1, hex_mixed.size())); - EXPECT_EQ(bytes_expected, infix_valid_result); - - std::string hex_result = absl::BytesToHexString(bytes_expected); - EXPECT_EQ(hex_only_lower, hex_result); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/char_map.h b/third_party/abseil_cpp/absl/strings/internal/char_map.h deleted file mode 100644 index 61484de0b795..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/char_map.h +++ /dev/null @@ -1,156 +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. -// -// Character Map Class -// -// A fast, bit-vector map for 8-bit unsigned characters. -// This class is useful for non-character purposes as well. - -#ifndef ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ -#define ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ - -#include <cstddef> -#include <cstdint> -#include <cstring> - -#include "absl/base/macros.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -class Charmap { - public: - constexpr Charmap() : m_() {} - - // Initializes with a given char*. Note that NUL is not treated as - // a terminator, but rather a char to be flicked. - Charmap(const char* str, int len) : m_() { - while (len--) SetChar(*str++); - } - - // Initializes with a given char*. NUL is treated as a terminator - // and will not be in the charmap. - explicit Charmap(const char* str) : m_() { - while (*str) SetChar(*str++); - } - - constexpr bool contains(unsigned char c) const { - return (m_[c / 64] >> (c % 64)) & 0x1; - } - - // Returns true if and only if a character exists in both maps. - bool IntersectsWith(const Charmap& c) const { - for (size_t i = 0; i < ABSL_ARRAYSIZE(m_); ++i) { - if ((m_[i] & c.m_[i]) != 0) return true; - } - return false; - } - - bool IsZero() const { - for (uint64_t c : m_) { - if (c != 0) return false; - } - return true; - } - - // Containing only a single specified char. - static constexpr Charmap Char(char x) { - return Charmap(CharMaskForWord(x, 0), CharMaskForWord(x, 1), - CharMaskForWord(x, 2), CharMaskForWord(x, 3)); - } - - // Containing all the chars in the C-string 's'. - // Note that this is expensively recursive because of the C++11 constexpr - // formulation. Use only in constexpr initializers. - static constexpr Charmap FromString(const char* s) { - return *s == 0 ? Charmap() : (Char(*s) | FromString(s + 1)); - } - - // Containing all the chars in the closed interval [lo,hi]. - static constexpr Charmap Range(char lo, char hi) { - return Charmap(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1), - RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3)); - } - - friend constexpr Charmap operator&(const Charmap& a, const Charmap& b) { - return Charmap(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2], - a.m_[3] & b.m_[3]); - } - - friend constexpr Charmap operator|(const Charmap& a, const Charmap& b) { - return Charmap(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2], - a.m_[3] | b.m_[3]); - } - - friend constexpr Charmap operator~(const Charmap& a) { - return Charmap(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]); - } - - private: - constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3) - : m_{b0, b1, b2, b3} {} - - static constexpr uint64_t RangeForWord(unsigned char lo, unsigned char hi, - uint64_t word) { - return OpenRangeFromZeroForWord(hi + 1, word) & - ~OpenRangeFromZeroForWord(lo, word); - } - - // All the chars in the specified word of the range [0, upper). - static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper, - uint64_t word) { - return (upper <= 64 * word) - ? 0 - : (upper >= 64 * (word + 1)) - ? ~static_cast<uint64_t>(0) - : (~static_cast<uint64_t>(0) >> (64 - upper % 64)); - } - - static constexpr uint64_t CharMaskForWord(unsigned char x, uint64_t word) { - return (x / 64 == word) ? (static_cast<uint64_t>(1) << (x % 64)) : 0; - } - - private: - void SetChar(unsigned char c) { - m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64); - } - - uint64_t m_[4]; -}; - -// Mirror the char-classifying predicates in <cctype> -constexpr Charmap UpperCharmap() { return Charmap::Range('A', 'Z'); } -constexpr Charmap LowerCharmap() { return Charmap::Range('a', 'z'); } -constexpr Charmap DigitCharmap() { return Charmap::Range('0', '9'); } -constexpr Charmap AlphaCharmap() { return LowerCharmap() | UpperCharmap(); } -constexpr Charmap AlnumCharmap() { return DigitCharmap() | AlphaCharmap(); } -constexpr Charmap XDigitCharmap() { - return DigitCharmap() | Charmap::Range('A', 'F') | Charmap::Range('a', 'f'); -} -constexpr Charmap PrintCharmap() { return Charmap::Range(0x20, 0x7e); } -constexpr Charmap SpaceCharmap() { return Charmap::FromString("\t\n\v\f\r "); } -constexpr Charmap CntrlCharmap() { - return Charmap::Range(0, 0x7f) & ~PrintCharmap(); -} -constexpr Charmap BlankCharmap() { return Charmap::FromString("\t "); } -constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); } -constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); } - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/char_map_benchmark.cc b/third_party/abseil_cpp/absl/strings/internal/char_map_benchmark.cc deleted file mode 100644 index 5cef967b3087..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/char_map_benchmark.cc +++ /dev/null @@ -1,61 +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/strings/internal/char_map.h" - -#include <cstdint> - -#include "benchmark/benchmark.h" - -namespace { - -absl::strings_internal::Charmap MakeBenchmarkMap() { - absl::strings_internal::Charmap m; - uint32_t x[] = {0x0, 0x1, 0x2, 0x3, 0xf, 0xe, 0xd, 0xc}; - for (uint32_t& t : x) t *= static_cast<uint32_t>(0x11111111UL); - for (uint32_t i = 0; i < 256; ++i) { - if ((x[i / 32] >> (i % 32)) & 1) - m = m | absl::strings_internal::Charmap::Char(i); - } - return m; -} - -// Micro-benchmark for Charmap::contains. -void BM_Contains(benchmark::State& state) { - // Loop-body replicated 10 times to increase time per iteration. - // Argument continuously changed to avoid generating common subexpressions. - const absl::strings_internal::Charmap benchmark_map = MakeBenchmarkMap(); - unsigned char c = 0; - int ops = 0; - for (auto _ : state) { - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - ops += benchmark_map.contains(c++); - } - benchmark::DoNotOptimize(ops); -} -BENCHMARK(BM_Contains); - -// We don't bother benchmarking Charmap::IsZero or Charmap::IntersectsWith; -// their running time is data-dependent and it is not worth characterizing -// "typical" data. - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/char_map_test.cc b/third_party/abseil_cpp/absl/strings/internal/char_map_test.cc deleted file mode 100644 index d3306241a404..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/char_map_test.cc +++ /dev/null @@ -1,172 +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/strings/internal/char_map.h" - -#include <cctype> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace { - -constexpr absl::strings_internal::Charmap everything_map = - ~absl::strings_internal::Charmap(); -constexpr absl::strings_internal::Charmap nothing_map{}; - -TEST(Charmap, AllTests) { - const absl::strings_internal::Charmap also_nothing_map("", 0); - ASSERT_TRUE(everything_map.contains('\0')); - ASSERT_TRUE(!nothing_map.contains('\0')); - ASSERT_TRUE(!also_nothing_map.contains('\0')); - for (unsigned char ch = 1; ch != 0; ++ch) { - ASSERT_TRUE(everything_map.contains(ch)); - ASSERT_TRUE(!nothing_map.contains(ch)); - ASSERT_TRUE(!also_nothing_map.contains(ch)); - } - - const absl::strings_internal::Charmap symbols("&@#@^!@?", 5); - ASSERT_TRUE(symbols.contains('&')); - ASSERT_TRUE(symbols.contains('@')); - ASSERT_TRUE(symbols.contains('#')); - ASSERT_TRUE(symbols.contains('^')); - ASSERT_TRUE(!symbols.contains('!')); - ASSERT_TRUE(!symbols.contains('?')); - int cnt = 0; - for (unsigned char ch = 1; ch != 0; ++ch) - cnt += symbols.contains(ch); - ASSERT_EQ(cnt, 4); - - const absl::strings_internal::Charmap lets("^abcde", 3); - const absl::strings_internal::Charmap lets2("fghij\0klmnop", 10); - const absl::strings_internal::Charmap lets3("fghij\0klmnop"); - ASSERT_TRUE(lets2.contains('k')); - ASSERT_TRUE(!lets3.contains('k')); - - ASSERT_TRUE(symbols.IntersectsWith(lets)); - ASSERT_TRUE(!lets2.IntersectsWith(lets)); - ASSERT_TRUE(lets.IntersectsWith(symbols)); - ASSERT_TRUE(!lets.IntersectsWith(lets2)); - - ASSERT_TRUE(nothing_map.IsZero()); - ASSERT_TRUE(!lets.IsZero()); -} - -namespace { -std::string Members(const absl::strings_internal::Charmap& m) { - std::string r; - for (size_t i = 0; i < 256; ++i) - if (m.contains(i)) r.push_back(i); - return r; -} - -std::string ClosedRangeString(unsigned char lo, unsigned char hi) { - // Don't depend on lo<hi. Just increment until lo==hi. - std::string s; - while (true) { - s.push_back(lo); - if (lo == hi) break; - ++lo; - } - return s; -} - -} // namespace - -TEST(Charmap, Constexpr) { - constexpr absl::strings_internal::Charmap kEmpty = nothing_map; - EXPECT_THAT(Members(kEmpty), ""); - constexpr absl::strings_internal::Charmap kA = - absl::strings_internal::Charmap::Char('A'); - EXPECT_THAT(Members(kA), "A"); - constexpr absl::strings_internal::Charmap kAZ = - absl::strings_internal::Charmap::Range('A', 'Z'); - EXPECT_THAT(Members(kAZ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - constexpr absl::strings_internal::Charmap kIdentifier = - absl::strings_internal::Charmap::Range('0', '9') | - absl::strings_internal::Charmap::Range('A', 'Z') | - absl::strings_internal::Charmap::Range('a', 'z') | - absl::strings_internal::Charmap::Char('_'); - EXPECT_THAT(Members(kIdentifier), - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "_" - "abcdefghijklmnopqrstuvwxyz"); - constexpr absl::strings_internal::Charmap kAll = everything_map; - for (size_t i = 0; i < 256; ++i) { - EXPECT_TRUE(kAll.contains(i)) << i; - } - constexpr absl::strings_internal::Charmap kHello = - absl::strings_internal::Charmap::FromString("Hello, world!"); - EXPECT_THAT(Members(kHello), " !,Hdelorw"); - - // test negation and intersection - constexpr absl::strings_internal::Charmap kABC = - absl::strings_internal::Charmap::Range('A', 'Z') & - ~absl::strings_internal::Charmap::Range('D', 'Z'); - EXPECT_THAT(Members(kABC), "ABC"); -} - -TEST(Charmap, Range) { - // Exhaustive testing takes too long, so test some of the boundaries that - // are perhaps going to cause trouble. - std::vector<size_t> poi = {0, 1, 2, 3, 4, 7, 8, 9, 15, - 16, 17, 30, 31, 32, 33, 63, 64, 65, - 127, 128, 129, 223, 224, 225, 254, 255}; - for (auto lo = poi.begin(); lo != poi.end(); ++lo) { - SCOPED_TRACE(*lo); - for (auto hi = lo; hi != poi.end(); ++hi) { - SCOPED_TRACE(*hi); - EXPECT_THAT(Members(absl::strings_internal::Charmap::Range(*lo, *hi)), - ClosedRangeString(*lo, *hi)); - } - } -} - -bool AsBool(int x) { return static_cast<bool>(x); } - -TEST(CharmapCtype, Match) { - for (int c = 0; c < 256; ++c) { - SCOPED_TRACE(c); - SCOPED_TRACE(static_cast<char>(c)); - EXPECT_EQ(AsBool(std::isupper(c)), - absl::strings_internal::UpperCharmap().contains(c)); - EXPECT_EQ(AsBool(std::islower(c)), - absl::strings_internal::LowerCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isdigit(c)), - absl::strings_internal::DigitCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isalpha(c)), - absl::strings_internal::AlphaCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isalnum(c)), - absl::strings_internal::AlnumCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isxdigit(c)), - absl::strings_internal::XDigitCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isprint(c)), - absl::strings_internal::PrintCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isspace(c)), - absl::strings_internal::SpaceCharmap().contains(c)); - EXPECT_EQ(AsBool(std::iscntrl(c)), - absl::strings_internal::CntrlCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isblank(c)), - absl::strings_internal::BlankCharmap().contains(c)); - EXPECT_EQ(AsBool(std::isgraph(c)), - absl::strings_internal::GraphCharmap().contains(c)); - EXPECT_EQ(AsBool(std::ispunct(c)), - absl::strings_internal::PunctCharmap().contains(c)); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.cc deleted file mode 100644 index ebf8c0791af9..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.cc +++ /dev/null @@ -1,359 +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/strings/internal/charconv_bigint.h" - -#include <algorithm> -#include <cassert> -#include <string> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -namespace { - -// Table containing some large powers of 5, for fast computation. - -// Constant step size for entries in the kLargePowersOfFive table. Each entry -// is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep -// (or 5**27). -// -// In other words, the Nth entry in the table is 5**(27*N). -// -// 5**27 is the largest power of 5 that fits in 64 bits. -constexpr int kLargePowerOfFiveStep = 27; - -// The largest legal index into the kLargePowersOfFive table. -// -// In other words, the largest precomputed power of 5 is 5**(27*20). -constexpr int kLargestPowerOfFiveIndex = 20; - -// Table of powers of (5**27), up to (5**27)**20 == 5**540. -// -// Used to generate large powers of 5 while limiting the number of repeated -// multiplications required. -// -// clang-format off -const uint32_t kLargePowersOfFive[] = { -// 5**27 (i=1), start=0, end=2 - 0xfa10079dU, 0x6765c793U, -// 5**54 (i=2), start=2, end=6 - 0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U, -// 5**81 (i=3), start=6, end=12 - 0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U, -// 5**108 (i=4), start=12, end=20 - 0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU, - 0x20d3846fU, 0x06d00f73U, -// 5**135 (i=5), start=20, end=30 - 0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U, - 0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU, -// 5**162 (i=6), start=30, end=42 - 0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU, - 0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU, -// 5**189 (i=7), start=42, end=56 - 0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U, - 0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U, - 0x94151217U, 0x0072e9f7U, -// 5**216 (i=8), start=56, end=72 - 0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU, - 0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU, - 0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U, -// 5**243 (i=9), start=72, end=90 - 0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U, - 0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U, - 0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U, -// 5**270 (i=10), start=90, end=110 - 0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U, - 0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U, - 0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U, - 0x0d39e796U, 0x00079250U, -// 5**297 (i=11), start=110, end=132 - 0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U, - 0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U, - 0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U, - 0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U, -// 5**324 (i=12), start=132, end=156 - 0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U, - 0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU, - 0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U, - 0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U, -// 5**351 (i=13), start=156, end=182 - 0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU, - 0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U, - 0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U, - 0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU, - 0x859a4940U, 0x00007fb6U, -// 5**378 (i=14), start=182, end=210 - 0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U, - 0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU, - 0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU, - 0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U, - 0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U, -// 5**405 (i=15), start=210, end=240 - 0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U, - 0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U, - 0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U, - 0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU, - 0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U, -// 5**432 (i=16), start=240, end=272 - 0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU, - 0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U, - 0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U, - 0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU, - 0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U, - 0x3364ea62U, 0x0000086aU, -// 5**459 (i=17), start=272, end=306 - 0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU, - 0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U, - 0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U, - 0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U, - 0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU, - 0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U, -// 5**486 (i=18), start=306, end=342 - 0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU, - 0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U, - 0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU, - 0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U, - 0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU, - 0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU, -// 5**513 (i=19), start=342, end=380 - 0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U, - 0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU, - 0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU, - 0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U, - 0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U, - 0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU, - 0xf0046d27U, 0x0000008dU, -// 5**540 (i=20), start=380, end=420 - 0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU, - 0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U, - 0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U, - 0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U, - 0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U, - 0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU, - 0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U, -}; -// clang-format on - -// Returns a pointer to the big integer data for (5**27)**i. i must be -// between 1 and 20, inclusive. -const uint32_t* LargePowerOfFiveData(int i) { - return kLargePowersOfFive + i * (i - 1); -} - -// Returns the size of the big integer data for (5**27)**i, in words. i must be -// between 1 and 20, inclusive. -int LargePowerOfFiveSize(int i) { return 2 * i; } -} // namespace - -ABSL_DLL const uint32_t kFiveToNth[14] = { - 1, 5, 25, 125, 625, 3125, 15625, - 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125, -}; - -ABSL_DLL const uint32_t kTenToNth[10] = { - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, -}; - -template <int max_words> -int BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp, - int significant_digits) { - SetToZero(); - assert(fp.type == FloatType::kNumber); - - if (fp.subrange_begin == nullptr) { - // We already exactly parsed the mantissa, so no more work is necessary. - words_[0] = fp.mantissa & 0xffffffffu; - words_[1] = fp.mantissa >> 32; - if (words_[1]) { - size_ = 2; - } else if (words_[0]) { - size_ = 1; - } - return fp.exponent; - } - int exponent_adjust = - ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits); - return fp.literal_exponent + exponent_adjust; -} - -template <int max_words> -int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end, - int significant_digits) { - assert(significant_digits <= Digits10() + 1); - SetToZero(); - - bool after_decimal_point = false; - // Discard any leading zeroes before the decimal point - while (begin < end && *begin == '0') { - ++begin; - } - int dropped_digits = 0; - // Discard any trailing zeroes. These may or may not be after the decimal - // point. - while (begin < end && *std::prev(end) == '0') { - --end; - ++dropped_digits; - } - if (begin < end && *std::prev(end) == '.') { - // If the string ends in '.', either before or after dropping zeroes, then - // drop the decimal point and look for more digits to drop. - dropped_digits = 0; - --end; - while (begin < end && *std::prev(end) == '0') { - --end; - ++dropped_digits; - } - } else if (dropped_digits) { - // We dropped digits, and aren't sure if they're before or after the decimal - // point. Figure that out now. - const char* dp = std::find(begin, end, '.'); - if (dp != end) { - // The dropped trailing digits were after the decimal point, so don't - // count them. - dropped_digits = 0; - } - } - // Any non-fraction digits we dropped need to be accounted for in our exponent - // adjustment. - int exponent_adjust = dropped_digits; - - uint32_t queued = 0; - int digits_queued = 0; - for (; begin != end && significant_digits > 0; ++begin) { - if (*begin == '.') { - after_decimal_point = true; - continue; - } - if (after_decimal_point) { - // For each fractional digit we emit in our parsed integer, adjust our - // decimal exponent to compensate. - --exponent_adjust; - } - int digit = (*begin - '0'); - --significant_digits; - if (significant_digits == 0 && std::next(begin) != end && - (digit == 0 || digit == 5)) { - // If this is the very last significant digit, but insignificant digits - // remain, we know that the last of those remaining significant digits is - // nonzero. (If it wasn't, we would have stripped it before we got here.) - // So if this final digit is a 0 or 5, adjust it upward by 1. - // - // This adjustment is what allows incredibly large mantissas ending in - // 500000...000000000001 to correctly round up, rather than to nearest. - ++digit; - } - queued = 10 * queued + digit; - ++digits_queued; - if (digits_queued == kMaxSmallPowerOfTen) { - MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]); - AddWithCarry(0, queued); - queued = digits_queued = 0; - } - } - // Encode any remaining digits. - if (digits_queued) { - MultiplyBy(kTenToNth[digits_queued]); - AddWithCarry(0, queued); - } - - // If any insignificant digits remain, we will drop them. But if we have not - // yet read the decimal point, then we have to adjust the exponent to account - // for the dropped digits. - if (begin < end && !after_decimal_point) { - // This call to std::find will result in a pointer either to the decimal - // point, or to the end of our buffer if there was none. - // - // Either way, [begin, decimal_point) will contain the set of dropped digits - // that require an exponent adjustment. - const char* decimal_point = std::find(begin, end, '.'); - exponent_adjust += (decimal_point - begin); - } - return exponent_adjust; -} - -template <int max_words> -/* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth( - int n) { - BigUnsigned answer(1u); - - // Seed from the table of large powers, if possible. - bool first_pass = true; - while (n >= kLargePowerOfFiveStep) { - int big_power = - std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex); - if (first_pass) { - // just copy, rather than multiplying by 1 - std::copy( - LargePowerOfFiveData(big_power), - LargePowerOfFiveData(big_power) + LargePowerOfFiveSize(big_power), - answer.words_); - answer.size_ = LargePowerOfFiveSize(big_power); - first_pass = false; - } else { - answer.MultiplyBy(LargePowerOfFiveSize(big_power), - LargePowerOfFiveData(big_power)); - } - n -= kLargePowerOfFiveStep * big_power; - } - answer.MultiplyByFiveToTheNth(n); - return answer; -} - -template <int max_words> -void BigUnsigned<max_words>::MultiplyStep(int original_size, - const uint32_t* other_words, - int other_size, int step) { - int this_i = std::min(original_size - 1, step); - int other_i = step - this_i; - - uint64_t this_word = 0; - uint64_t carry = 0; - for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) { - uint64_t product = words_[this_i]; - product *= other_words[other_i]; - this_word += product; - carry += (this_word >> 32); - this_word &= 0xffffffff; - } - AddWithCarry(step + 1, carry); - words_[step] = this_word & 0xffffffff; - if (this_word > 0 && size_ <= step) { - size_ = step + 1; - } -} - -template <int max_words> -std::string BigUnsigned<max_words>::ToString() const { - BigUnsigned<max_words> copy = *this; - std::string result; - // Build result in reverse order - while (copy.size() > 0) { - int next_digit = copy.DivMod<10>(); - result.push_back('0' + next_digit); - } - if (result.empty()) { - result.push_back('0'); - } - std::reverse(result.begin(), result.end()); - return result; -} - -template class BigUnsigned<4>; -template class BigUnsigned<84>; - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.h b/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.h deleted file mode 100644 index 8f702976a80d..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint.h +++ /dev/null @@ -1,423 +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. - -#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_ -#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_ - -#include <algorithm> -#include <cstdint> -#include <iostream> -#include <string> - -#include "absl/base/config.h" -#include "absl/strings/ascii.h" -#include "absl/strings/internal/charconv_parse.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// The largest power that 5 that can be raised to, and still fit in a uint32_t. -constexpr int kMaxSmallPowerOfFive = 13; -// The largest power that 10 that can be raised to, and still fit in a uint32_t. -constexpr int kMaxSmallPowerOfTen = 9; - -ABSL_DLL extern const uint32_t - kFiveToNth[kMaxSmallPowerOfFive + 1]; -ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1]; - -// Large, fixed-width unsigned integer. -// -// Exact rounding for decimal-to-binary floating point conversion requires very -// large integer math, but a design goal of absl::from_chars is to avoid -// allocating memory. The integer precision needed for decimal-to-binary -// conversions is large but bounded, so a huge fixed-width integer class -// suffices. -// -// This is an intentionally limited big integer class. Only needed operations -// are implemented. All storage lives in an array data member, and all -// arithmetic is done in-place, to avoid requiring separate storage for operand -// and result. -// -// This is an internal class. Some methods live in the .cc file, and are -// instantiated only for the values of max_words we need. -template <int max_words> -class BigUnsigned { - public: - static_assert(max_words == 4 || max_words == 84, - "unsupported max_words value"); - - BigUnsigned() : size_(0), words_{} {} - explicit constexpr BigUnsigned(uint64_t v) - : size_((v >> 32) ? 2 : v ? 1 : 0), - words_{static_cast<uint32_t>(v & 0xffffffffu), - 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 - // instead. - explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} { - // Check for valid input, returning a 0 otherwise. This is reasonable - // behavior only because this constructor is for unit tests. - if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() || - sv.empty()) { - return; - } - int exponent_adjust = - ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1); - if (exponent_adjust > 0) { - MultiplyByTenToTheNth(exponent_adjust); - } - } - - // Loads the mantissa value of a previously-parsed float. - // - // Returns the associated decimal exponent. The value of the parsed float is - // exactly *this * 10**exponent. - int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits); - - // Returns the number of decimal digits of precision this type provides. All - // numbers with this many decimal digits or fewer are representable by this - // type. - // - // Analagous to std::numeric_limits<BigUnsigned>::digits10. - static constexpr int Digits10() { - // 9975007/1035508 is very slightly less than log10(2**32). - return static_cast<uint64_t>(max_words) * 9975007 / 1035508; - } - - // Shifts left by the given number of bits. - void ShiftLeft(int count) { - if (count > 0) { - const int word_shift = count / 32; - if (word_shift >= max_words) { - SetToZero(); - return; - } - size_ = (std::min)(size_ + word_shift, max_words); - count %= 32; - if (count == 0) { - std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_); - } else { - for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) { - words_[i] = (words_[i - word_shift] << count) | - (words_[i - word_shift - 1] >> (32 - count)); - } - words_[word_shift] = words_[0] << count; - // Grow size_ if necessary. - if (size_ < max_words && words_[size_]) { - ++size_; - } - } - std::fill(words_, words_ + word_shift, 0u); - } - } - - - // Multiplies by v in-place. - void MultiplyBy(uint32_t v) { - if (size_ == 0 || v == 1) { - return; - } - if (v == 0) { - SetToZero(); - return; - } - const uint64_t factor = v; - uint64_t window = 0; - for (int i = 0; i < size_; ++i) { - window += factor * words_[i]; - words_[i] = window & 0xffffffff; - window >>= 32; - } - // If carry bits remain and there's space for them, grow size_. - if (window && size_ < max_words) { - words_[size_] = window & 0xffffffff; - ++size_; - } - } - - void MultiplyBy(uint64_t v) { - uint32_t words[2]; - words[0] = static_cast<uint32_t>(v); - words[1] = static_cast<uint32_t>(v >> 32); - if (words[1] == 0) { - MultiplyBy(words[0]); - } else { - MultiplyBy(2, words); - } - } - - // Multiplies in place by 5 to the power of n. n must be non-negative. - void MultiplyByFiveToTheNth(int n) { - while (n >= kMaxSmallPowerOfFive) { - MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]); - n -= kMaxSmallPowerOfFive; - } - if (n > 0) { - MultiplyBy(kFiveToNth[n]); - } - } - - // Multiplies in place by 10 to the power of n. n must be non-negative. - void MultiplyByTenToTheNth(int n) { - if (n > kMaxSmallPowerOfTen) { - // For large n, raise to a power of 5, then shift left by the same amount. - // (10**n == 5**n * 2**n.) This requires fewer multiplications overall. - MultiplyByFiveToTheNth(n); - ShiftLeft(n); - } else if (n > 0) { - // We can do this more quickly for very small N by using a single - // multiplication. - MultiplyBy(kTenToNth[n]); - } - } - - // Returns the value of 5**n, for non-negative n. This implementation uses - // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling - // MultiplyByFiveToTheNth(). - static BigUnsigned FiveToTheNth(int n); - - // Multiplies by another BigUnsigned, in-place. - template <int M> - void MultiplyBy(const BigUnsigned<M>& other) { - MultiplyBy(other.size(), other.words()); - } - - void SetToZero() { - std::fill(words_, words_ + size_, 0u); - size_ = 0; - } - - // Returns the value of the nth word of this BigUnsigned. This is - // range-checked, and returns 0 on out-of-bounds accesses. - uint32_t GetWord(int index) const { - if (index < 0 || index >= size_) { - return 0; - } - return words_[index]; - } - - // Returns this integer as a decimal string. This is not used in the decimal- - // to-binary conversion; it is intended to aid in testing. - std::string ToString() const; - - int size() const { return size_; } - const uint32_t* words() const { return words_; } - - private: - // Reads the number between [begin, end), possibly containing a decimal point, - // into this BigUnsigned. - // - // Callers are required to ensure [begin, end) contains a valid number, with - // one or more decimal digits and at most one decimal point. This routine - // will behave unpredictably if these preconditions are not met. - // - // Only the first `significant_digits` digits are read. Digits beyond this - // limit are "sticky": If the final significant digit is 0 or 5, and if any - // dropped digit is nonzero, then that final significant digit is adjusted up - // to 1 or 6. This adjustment allows for precise rounding. - // - // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to - // account for the decimal point and for dropped significant digits. After - // this function returns, - // actual_value_of_parsed_string ~= *this * 10**exponent_adjustment. - int ReadDigits(const char* begin, const char* end, int significant_digits); - - // Performs a step of big integer multiplication. This computes the full - // (64-bit-wide) values that should be added at the given index (step), and - // adds to that location in-place. - // - // Because our math all occurs in place, we must multiply starting from the - // highest word working downward. (This is a bit more expensive due to the - // extra carries involved.) - // - // This must be called in steps, for each word to be calculated, starting from - // the high end and working down to 0. The first value of `step` should be - // `std::min(original_size + other.size_ - 2, max_words - 1)`. - // The reason for this expression is that multiplying the i'th word from one - // multiplicand and the j'th word of another multiplicand creates a - // two-word-wide value to be stored at the (i+j)'th element. The highest - // word indices we will access are `original_size - 1` from this object, and - // `other.size_ - 1` from our operand. Therefore, - // `original_size + other.size_ - 2` is the first step we should calculate, - // but limited on an upper bound by max_words. - - // Working from high-to-low ensures that we do not overwrite the portions of - // the initial value of *this which are still needed for later steps. - // - // Once called with step == 0, *this contains the result of the - // multiplication. - // - // `original_size` is the size_ of *this before the first call to - // MultiplyStep(). `other_words` and `other_size` are the contents of our - // operand. `step` is the step to perform, as described above. - void MultiplyStep(int original_size, const uint32_t* other_words, - int other_size, int step); - - void MultiplyBy(int other_size, const uint32_t* other_words) { - const int original_size = size_; - const int first_step = - (std::min)(original_size + other_size - 2, max_words - 1); - for (int step = first_step; step >= 0; --step) { - MultiplyStep(original_size, other_words, other_size, step); - } - } - - // Adds a 32-bit value to the index'th word, with carry. - void AddWithCarry(int index, uint32_t value) { - if (value) { - while (index < max_words && value > 0) { - words_[index] += value; - // carry if we overflowed in this word: - if (value > words_[index]) { - value = 1; - ++index; - } else { - value = 0; - } - } - size_ = (std::min)(max_words, (std::max)(index + 1, size_)); - } - } - - void AddWithCarry(int index, uint64_t value) { - if (value && index < max_words) { - uint32_t high = value >> 32; - uint32_t low = value & 0xffffffff; - words_[index] += low; - if (words_[index] < low) { - ++high; - if (high == 0) { - // Carry from the low word caused our high word to overflow. - // Short circuit here to do the right thing. - AddWithCarry(index + 2, static_cast<uint32_t>(1)); - return; - } - } - if (high > 0) { - AddWithCarry(index + 1, high); - } else { - // Normally 32-bit AddWithCarry() sets size_, but since we don't call - // it when `high` is 0, do it ourselves here. - size_ = (std::min)(max_words, (std::max)(index + 1, size_)); - } - } - } - - // Divide this in place by a constant divisor. Returns the remainder of the - // division. - template <uint32_t divisor> - uint32_t DivMod() { - uint64_t accumulator = 0; - for (int i = size_ - 1; i >= 0; --i) { - accumulator <<= 32; - accumulator += words_[i]; - // accumulator / divisor will never overflow an int32_t in this loop - words_[i] = static_cast<uint32_t>(accumulator / divisor); - accumulator = accumulator % divisor; - } - while (size_ > 0 && words_[size_ - 1] == 0) { - --size_; - } - return static_cast<uint32_t>(accumulator); - } - - // The number of elements in words_ that may carry significant values. - // All elements beyond this point are 0. - // - // When size_ is 0, this BigUnsigned stores the value 0. - // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is - // nonzero. This can occur due to overflow truncation. - // In particular, x.size_ != y.size_ does *not* imply x != y. - int size_; - uint32_t words_[max_words]; -}; - -// Compares two big integer instances. -// -// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs. -template <int N, int M> -int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - int limit = (std::max)(lhs.size(), rhs.size()); - for (int i = limit - 1; i >= 0; --i) { - const uint32_t lhs_word = lhs.GetWord(i); - const uint32_t rhs_word = rhs.GetWord(i); - if (lhs_word < rhs_word) { - return -1; - } else if (lhs_word > rhs_word) { - return 1; - } - } - return 0; -} - -template <int N, int M> -bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - int limit = (std::max)(lhs.size(), rhs.size()); - for (int i = 0; i < limit; ++i) { - if (lhs.GetWord(i) != rhs.GetWord(i)) { - return false; - } - } - return true; -} - -template <int N, int M> -bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - return !(lhs == rhs); -} - -template <int N, int M> -bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - return Compare(lhs, rhs) == -1; -} - -template <int N, int M> -bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - return rhs < lhs; -} -template <int N, int M> -bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - return !(rhs < lhs); -} -template <int N, int M> -bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) { - return !(lhs < rhs); -} - -// Output operator for BigUnsigned, for testing purposes only. -template <int N> -std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) { - return os << num.ToString(); -} - -// Explicit instantiation declarations for the sizes of BigUnsigned that we -// are using. -// -// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is -// still bigger than an int128, and 84 is a large value we will want to use -// in the from_chars implementation. -// -// Comments justifying the use of 84 belong in the from_chars implementation, -// and will be added in a follow-up CL. -extern template class BigUnsigned<4>; -extern template class BigUnsigned<84>; - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc deleted file mode 100644 index a8b9945829e8..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc +++ /dev/null @@ -1,260 +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/strings/internal/charconv_bigint.h" - -#include <string> - -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -TEST(BigUnsigned, ShiftLeft) { - { - // Check that 3 * 2**100 is calculated correctly - BigUnsigned<4> num(3u); - num.ShiftLeft(100); - EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128")); - } - { - // Test that overflow is truncated properly. - // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint. - // Shifting left by 125 bits should truncate off the high bit, so that - // 15 << 125 == 7 << 125 - // after truncation. - BigUnsigned<4> a(15u); - BigUnsigned<4> b(7u); - BigUnsigned<4> c(3u); - a.ShiftLeft(125); - b.ShiftLeft(125); - c.ShiftLeft(125); - EXPECT_EQ(a, b); - EXPECT_NE(a, c); - } - { - // Same test, larger bigint: - BigUnsigned<84> a(15u); - BigUnsigned<84> b(7u); - BigUnsigned<84> c(3u); - a.ShiftLeft(84 * 32 - 3); - b.ShiftLeft(84 * 32 - 3); - c.ShiftLeft(84 * 32 - 3); - EXPECT_EQ(a, b); - EXPECT_NE(a, c); - } - { - // Check that incrementally shifting has the same result as doing it all at - // once (attempting to capture corner cases.) - const std::string seed = "1234567890123456789012345678901234567890"; - BigUnsigned<84> a(seed); - for (int i = 1; i <= 84 * 32; ++i) { - a.ShiftLeft(1); - BigUnsigned<84> b(seed); - b.ShiftLeft(i); - EXPECT_EQ(a, b); - } - // 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) { - const BigUnsigned<84> factorial_100( - "933262154439441526816992388562667004907159682643816214685929638952175999" - "932299156089414639761565182862536979208272237582511852109168640000000000" - "00000000000000"); - BigUnsigned<84> a(1u); - for (uint32_t i = 1; i <= 100; ++i) { - a.MultiplyBy(i); - } - EXPECT_EQ(a, BigUnsigned<84>(factorial_100)); -} - -TEST(BigUnsigned, MultiplyByBigUnsigned) { - { - // Put the terms of factorial_200 into two bigints, and multiply them - // together. - const BigUnsigned<84> factorial_200( - "7886578673647905035523632139321850622951359776871732632947425332443594" - "4996340334292030428401198462390417721213891963883025764279024263710506" - "1926624952829931113462857270763317237396988943922445621451664240254033" - "2918641312274282948532775242424075739032403212574055795686602260319041" - "7032406235170085879617892222278962370389737472000000000000000000000000" - "0000000000000000000000000"); - BigUnsigned<84> evens(1u); - BigUnsigned<84> odds(1u); - for (uint32_t i = 1; i < 200; i += 2) { - odds.MultiplyBy(i); - evens.MultiplyBy(i + 1); - } - evens.MultiplyBy(odds); - EXPECT_EQ(evens, factorial_200); - } - { - // Multiply various powers of 10 together. - for (int a = 0 ; a < 700; a += 25) { - SCOPED_TRACE(a); - BigUnsigned<84> a_value("3" + std::string(a, '0')); - for (int b = 0; b < (700 - a); b += 25) { - SCOPED_TRACE(b); - BigUnsigned<84> b_value("2" + std::string(b, '0')); - BigUnsigned<84> expected_product("6" + std::string(a + b, '0')); - b_value.MultiplyBy(a_value); - EXPECT_EQ(b_value, expected_product); - } - } - } -} - -TEST(BigUnsigned, MultiplyByOverflow) { - { - // Check that multiplcation overflow predictably truncates. - - // A big int with all bits on. - BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455"); - // Modulo 2**128, this is equal to -1. Therefore the square of this, - // modulo 2**128, should be 1. - all_bits_on.MultiplyBy(all_bits_on); - EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u)); - } - { - // Try multiplying a large bigint by 2**50, and compare the result to - // shifting. - BigUnsigned<4> value_1("12345678901234567890123456789012345678"); - BigUnsigned<4> value_2("12345678901234567890123456789012345678"); - BigUnsigned<4> two_to_fiftieth(1u); - two_to_fiftieth.ShiftLeft(50); - - value_1.ShiftLeft(50); - value_2.MultiplyBy(two_to_fiftieth); - EXPECT_EQ(value_1, value_2); - } -} - -TEST(BigUnsigned, FiveToTheNth) { - { - // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to - // and including overflow. - for (int i = 0; i < 1160; ++i) { - SCOPED_TRACE(i); - BigUnsigned<84> value_1(123u); - BigUnsigned<84> value_2(123u); - value_1.MultiplyByFiveToTheNth(i); - for (int j = 0; j < i; j++) { - value_2.MultiplyBy(5u); - } - EXPECT_EQ(value_1, value_2); - } - } - { - // Check that the faster, table-lookup-based static method returns the same - // result that multiplying in-place would return, up to and including - // overflow. - for (int i = 0; i < 1160; ++i) { - SCOPED_TRACE(i); - BigUnsigned<84> value_1(1u); - value_1.MultiplyByFiveToTheNth(i); - BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i); - EXPECT_EQ(value_1, value_2); - } - } -} - -TEST(BigUnsigned, TenToTheNth) { - { - // Sanity check MultiplyByTenToTheNth. - for (int i = 0; i < 800; ++i) { - SCOPED_TRACE(i); - BigUnsigned<84> value_1(123u); - BigUnsigned<84> value_2(123u); - value_1.MultiplyByTenToTheNth(i); - for (int j = 0; j < i; j++) { - value_2.MultiplyBy(10u); - } - EXPECT_EQ(value_1, value_2); - } - } - { - // Alternate testing approach, taking advantage of the decimal parser. - for (int i = 0; i < 200; ++i) { - SCOPED_TRACE(i); - BigUnsigned<84> value_1(135u); - value_1.MultiplyByTenToTheNth(i); - BigUnsigned<84> value_2("135" + std::string(i, '0')); - EXPECT_EQ(value_1, value_2); - } - } -} - - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc deleted file mode 100644 index 8b11868c887a..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc +++ /dev/null @@ -1,504 +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/strings/internal/charconv_parse.h" -#include "absl/strings/charconv.h" - -#include <cassert> -#include <cstdint> -#include <limits> - -#include "absl/strings/internal/memutil.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -// ParseFloat<10> will read the first 19 significant digits of the mantissa. -// This number was chosen for multiple reasons. -// -// (a) First, for whatever integer type we choose to represent the mantissa, we -// want to choose the largest possible number of decimal digits for that integer -// type. We are using uint64_t, which can express any 19-digit unsigned -// integer. -// -// (b) Second, we need to parse enough digits that the binary value of any -// mantissa we capture has more bits of resolution than the mantissa -// representation in the target float. Our algorithm requires at least 3 bits -// of headway, but 19 decimal digits give a little more than that. -// -// The following static assertions verify the above comments: -constexpr int kDecimalMantissaDigitsMax = 19; - -static_assert(std::numeric_limits<uint64_t>::digits10 == - kDecimalMantissaDigitsMax, - "(a) above"); - -// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa. -static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed"); -static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact"); -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"); - -// ParseFloat<16> will read the first 15 significant digits of the mantissa. -// -// Because a base-16-to-base-2 conversion can be done exactly, we do not need -// to maximize the number of scanned hex digits to improve our conversion. What -// is required is to scan two more bits than the mantissa can represent, so that -// we always round correctly. -// -// (One extra bit does not suffice to perform correct rounding, since a number -// exactly halfway between two representable floats has unique rounding rules, -// so we need to differentiate between a "halfway between" number and a "closer -// to the larger value" number.) -constexpr int kHexadecimalMantissaDigitsMax = 15; - -// The minimum number of significant bits that will be read from -// kHexadecimalMantissaDigitsMax hex digits. We must subtract by three, since -// the most significant digit can be a "1", which only contributes a single -// significant bit. -constexpr int kGuaranteedHexadecimalMantissaBitPrecision = - 4 * kHexadecimalMantissaDigitsMax - 3; - -static_assert(kGuaranteedHexadecimalMantissaBitPrecision > - std::numeric_limits<double>::digits + 2, - "kHexadecimalMantissaDigitsMax too small"); - -// We also impose a limit on the number of significant digits we will read from -// an exponent, to avoid having to deal with integer overflow. We use 9 for -// this purpose. -// -// If we read a 9 digit exponent, the end result of the conversion will -// necessarily be infinity or zero, depending on the sign of the exponent. -// Therefore we can just drop extra digits on the floor without any extra -// logic. -constexpr int kDecimalExponentDigitsMax = 9; -static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax, - "int type too small"); - -// To avoid incredibly large inputs causing integer overflow for our exponent, -// we impose an arbitrary but very large limit on the number of significant -// digits we will accept. The implementation refuses to match a string with -// more consecutive significant mantissa digits than this. -constexpr int kDecimalDigitLimit = 50000000; - -// Corresponding limit for hexadecimal digit inputs. This is one fourth the -// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires -// a binary exponent adjustment of 4. -constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4; - -// The largest exponent we can read is 999999999 (per -// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get -// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these -// comfortably fits in an integer. -// -// We count kDecimalDigitLimit twice because there are independent limits for -// numbers before and after the decimal point. (In the case where there are no -// significant digits before the decimal point, there are independent limits for -// post-decimal-point leading zeroes and for significant digits.) -static_assert(999999999 + 2 * kDecimalDigitLimit < - std::numeric_limits<int>::max(), - "int type too small"); -static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) < - std::numeric_limits<int>::max(), - "int type too small"); - -// Returns true if the provided bitfield allows parsing an exponent value -// (e.g., "1.5e100"). -bool AllowExponent(chars_format flags) { - bool fixed = (flags & chars_format::fixed) == chars_format::fixed; - bool scientific = - (flags & chars_format::scientific) == chars_format::scientific; - return scientific || !fixed; -} - -// Returns true if the provided bitfield requires an exponent value be present. -bool RequireExponent(chars_format flags) { - bool fixed = (flags & chars_format::fixed) == chars_format::fixed; - bool scientific = - (flags & chars_format::scientific) == chars_format::scientific; - return scientific && !fixed; -} - -const int8_t kAsciiToInt[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1}; - -// Returns true if `ch` is a digit in the given base -template <int base> -bool IsDigit(char ch); - -// Converts a valid `ch` to its digit value in the given base. -template <int base> -unsigned ToDigit(char ch); - -// Returns true if `ch` is the exponent delimiter for the given base. -template <int base> -bool IsExponentCharacter(char ch); - -// Returns the maximum number of significant digits we will read for a float -// in the given base. -template <int base> -constexpr int MantissaDigitsMax(); - -// Returns the largest consecutive run of digits we will accept when parsing a -// number in the given base. -template <int base> -constexpr int DigitLimit(); - -// Returns the amount the exponent must be adjusted by for each dropped digit. -// (For decimal this is 1, since the digits are in base 10 and the exponent base -// is also 10, but for hexadecimal this is 4, since the digits are base 16 but -// the exponent base is 2.) -template <int base> -constexpr int DigitMagnitude(); - -template <> -bool IsDigit<10>(char ch) { - return ch >= '0' && ch <= '9'; -} -template <> -bool IsDigit<16>(char ch) { - return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0; -} - -template <> -unsigned ToDigit<10>(char ch) { - return ch - '0'; -} -template <> -unsigned ToDigit<16>(char ch) { - return kAsciiToInt[static_cast<unsigned char>(ch)]; -} - -template <> -bool IsExponentCharacter<10>(char ch) { - return ch == 'e' || ch == 'E'; -} - -template <> -bool IsExponentCharacter<16>(char ch) { - return ch == 'p' || ch == 'P'; -} - -template <> -constexpr int MantissaDigitsMax<10>() { - return kDecimalMantissaDigitsMax; -} -template <> -constexpr int MantissaDigitsMax<16>() { - return kHexadecimalMantissaDigitsMax; -} - -template <> -constexpr int DigitLimit<10>() { - return kDecimalDigitLimit; -} -template <> -constexpr int DigitLimit<16>() { - return kHexadecimalDigitLimit; -} - -template <> -constexpr int DigitMagnitude<10>() { - return 1; -} -template <> -constexpr int DigitMagnitude<16>() { - return 4; -} - -// Reads decimal digits from [begin, end) into *out. Returns the number of -// digits consumed. -// -// After max_digits has been read, keeps consuming characters, but no longer -// adjusts *out. If a nonzero digit is dropped this way, *dropped_nonzero_digit -// is set; otherwise, it is left unmodified. -// -// If no digits are matched, returns 0 and leaves *out unchanged. -// -// 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) { - if (base == 10) { - assert(max_digits <= std::numeric_limits<T>::digits10); - } else if (base == 16) { - assert(max_digits * 4 <= std::numeric_limits<T>::digits); - } - const char* const original_begin = begin; - - // Skip leading zeros, but only if *out is zero. - // They don't cause an overflow so we don't have to count them for - // `max_digits`. - while (!*out && end != begin && *begin == '0') ++begin; - - T accumulator = *out; - const char* significant_digits_end = - (end - begin > max_digits) ? begin + max_digits : end; - while (begin < significant_digits_end && IsDigit<base>(*begin)) { - // Do not guard against *out overflow; max_digits was chosen to avoid this. - // Do assert against it, to detect problems in debug builds. - auto digit = static_cast<T>(ToDigit<base>(*begin)); - assert(accumulator * base >= accumulator); - accumulator *= base; - assert(accumulator + digit >= accumulator); - accumulator += digit; - ++begin; - } - bool dropped_nonzero = false; - while (begin < end && IsDigit<base>(*begin)) { - dropped_nonzero = dropped_nonzero || (*begin != '0'); - ++begin; - } - if (dropped_nonzero && dropped_nonzero_digit != nullptr) { - *dropped_nonzero_digit = true; - } - *out = accumulator; - return static_cast<int>(begin - original_begin); -} - -// Returns true if `v` is one of the chars allowed inside parentheses following -// a NaN. -bool IsNanChar(char v) { - return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') || - (v >= 'A' && v <= 'Z'); -} - -// Checks the range [begin, end) for a strtod()-formatted infinity or NaN. If -// one is found, sets `out` appropriately and returns true. -bool ParseInfinityOrNan(const char* begin, const char* end, - strings_internal::ParsedFloat* out) { - if (end - begin < 3) { - return false; - } - switch (*begin) { - case 'i': - case 'I': { - // An infinity string consists of the characters "inf" or "infinity", - // case insensitive. - if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) { - return false; - } - out->type = strings_internal::FloatType::kInfinity; - if (end - begin >= 8 && - strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) { - out->end = begin + 8; - } else { - out->end = begin + 3; - } - return true; - } - case 'n': - case 'N': { - // A NaN consists of the characters "nan", case insensitive, optionally - // followed by a parenthesized sequence of zero or more alphanumeric - // characters and/or underscores. - if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) { - return false; - } - out->type = strings_internal::FloatType::kNan; - out->end = begin + 3; - // NaN is allowed to be followed by a parenthesized string, consisting of - // only the characters [a-zA-Z0-9_]. Match that if it's present. - begin += 3; - if (begin < end && *begin == '(') { - const char* nan_begin = begin + 1; - while (nan_begin < end && IsNanChar(*nan_begin)) { - ++nan_begin; - } - if (nan_begin < end && *nan_begin == ')') { - // We found an extra NaN specifier range - out->subrange_begin = begin + 1; - out->subrange_end = nan_begin; - out->end = nan_begin + 1; - } - } - return true; - } - default: - return false; - } -} -} // namespace - -namespace strings_internal { - -template <int base> -strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end, - chars_format format_flags) { - strings_internal::ParsedFloat result; - - // Exit early if we're given an empty range. - if (begin == end) return result; - - // Handle the infinity and NaN cases. - if (ParseInfinityOrNan(begin, end, &result)) { - return result; - } - - const char* const mantissa_begin = begin; - while (begin < end && *begin == '0') { - ++begin; // skip leading zeros - } - uint64_t mantissa = 0; - - int exponent_adjustment = 0; - bool mantissa_is_inexact = false; - int pre_decimal_digits = ConsumeDigits<base>( - begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact); - begin += pre_decimal_digits; - int digits_left; - if (pre_decimal_digits >= DigitLimit<base>()) { - // refuse to parse pathological inputs - return result; - } else if (pre_decimal_digits > MantissaDigitsMax<base>()) { - // We dropped some non-fraction digits on the floor. Adjust our exponent - // to compensate. - exponent_adjustment = - static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>()); - digits_left = 0; - } else { - digits_left = - static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits); - } - if (begin < end && *begin == '.') { - ++begin; - if (mantissa == 0) { - // If we haven't seen any nonzero digits yet, keep skipping zeros. We - // have to adjust the exponent to reflect the changed place value. - const char* begin_zeros = begin; - while (begin < end && *begin == '0') { - ++begin; - } - int zeros_skipped = static_cast<int>(begin - begin_zeros); - if (zeros_skipped >= DigitLimit<base>()) { - // refuse to parse pathological inputs - return result; - } - exponent_adjustment -= static_cast<int>(zeros_skipped); - } - int post_decimal_digits = ConsumeDigits<base>( - begin, end, digits_left, &mantissa, &mantissa_is_inexact); - begin += post_decimal_digits; - - // Since `mantissa` is an integer, each significant digit we read after - // the decimal point requires an adjustment to the exponent. "1.23e0" will - // be stored as `mantissa` == 123 and `exponent` == -2 (that is, - // "123e-2"). - if (post_decimal_digits >= DigitLimit<base>()) { - // refuse to parse pathological inputs - return result; - } else if (post_decimal_digits > digits_left) { - exponent_adjustment -= digits_left; - } else { - exponent_adjustment -= post_decimal_digits; - } - } - // If we've found no mantissa whatsoever, this isn't a number. - if (mantissa_begin == begin) { - return result; - } - // A bare "." doesn't count as a mantissa either. - if (begin - mantissa_begin == 1 && *mantissa_begin == '.') { - return result; - } - - if (mantissa_is_inexact) { - // We dropped significant digits on the floor. Handle this appropriately. - if (base == 10) { - // If we truncated significant decimal digits, store the full range of the - // mantissa for future big integer math for exact rounding. - result.subrange_begin = mantissa_begin; - result.subrange_end = begin; - } else if (base == 16) { - // If we truncated hex digits, reflect this fact by setting the low - // ("sticky") bit. This allows for correct rounding in all cases. - mantissa |= 1; - } - } - result.mantissa = mantissa; - - const char* const exponent_begin = begin; - result.literal_exponent = 0; - bool found_exponent = false; - if (AllowExponent(format_flags) && begin < end && - IsExponentCharacter<base>(*begin)) { - bool negative_exponent = false; - ++begin; - if (begin < end && *begin == '-') { - negative_exponent = true; - ++begin; - } else if (begin < end && *begin == '+') { - ++begin; - } - const char* const exponent_digits_begin = begin; - // Exponent is always expressed in decimal, even for hexadecimal floats. - begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax, - &result.literal_exponent, nullptr); - if (begin == exponent_digits_begin) { - // there were no digits where we expected an exponent. We failed to read - // an exponent and should not consume the 'e' after all. Rewind 'begin'. - found_exponent = false; - begin = exponent_begin; - } else { - found_exponent = true; - if (negative_exponent) { - result.literal_exponent = -result.literal_exponent; - } - } - } - - if (!found_exponent && RequireExponent(format_flags)) { - // Provided flags required an exponent, but none was found. This results - // in a failure to scan. - return result; - } - - // Success! - result.type = strings_internal::FloatType::kNumber; - if (result.mantissa > 0) { - result.exponent = result.literal_exponent + - (DigitMagnitude<base>() * exponent_adjustment); - } else { - result.exponent = 0; - } - result.end = begin; - return result; -} - -template ParsedFloat ParseFloat<10>(const char* begin, const char* end, - chars_format format_flags); -template ParsedFloat ParseFloat<16>(const char* begin, const char* end, - chars_format format_flags); - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.h b/third_party/abseil_cpp/absl/strings/internal/charconv_parse.h deleted file mode 100644 index 505998b5394a..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.h +++ /dev/null @@ -1,99 +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. - -#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_ -#define ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_ - -#include <cstdint> - -#include "absl/base/config.h" -#include "absl/strings/charconv.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// Enum indicating whether a parsed float is a number or special value. -enum class FloatType { kNumber, kInfinity, kNan }; - -// The decomposed parts of a parsed `float` or `double`. -struct ParsedFloat { - // Representation of the parsed mantissa, with the decimal point adjusted to - // make it an integer. - // - // During decimal scanning, this contains 19 significant digits worth of - // mantissa value. If digits beyond this point are found, they - // are truncated, and if any of these dropped digits are nonzero, then - // `mantissa` is inexact, and the full mantissa is stored in [subrange_begin, - // subrange_end). - // - // During hexadecimal scanning, this contains 15 significant hex digits worth - // of mantissa value. Digits beyond this point are sticky -- they are - // truncated, but if any dropped digits are nonzero, the low bit of mantissa - // will be set. (This allows for precise rounding, and avoids the need - // to store the full mantissa in [subrange_begin, subrange_end).) - uint64_t mantissa = 0; - - // Floating point expontent. This reflects any decimal point adjustments and - // any truncated digits from the mantissa. The absolute value of the parsed - // number is represented by mantissa * (base ** exponent), where base==10 for - // decimal floats, and base==2 for hexadecimal floats. - int exponent = 0; - - // The literal exponent value scanned from the input, or 0 if none was - // present. This does not reflect any adjustments applied to mantissa. - int literal_exponent = 0; - - // The type of number scanned. - FloatType type = FloatType::kNumber; - - // When non-null, [subrange_begin, subrange_end) marks a range of characters - // that require further processing. The meaning is dependent on float type. - // If type == kNumber and this is set, this is a "wide input": the input - // mantissa contained more than 19 digits. The range contains the full - // mantissa. It plus `literal_exponent` need to be examined to find the best - // floating point match. - // If type == kNan and this is set, the range marks the contents of a - // matched parenthesized character region after the NaN. - const char* subrange_begin = nullptr; - const char* subrange_end = nullptr; - - // One-past-the-end of the successfully parsed region, or nullptr if no - // matching pattern was found. - const char* end = nullptr; -}; - -// Read the floating point number in the provided range, and populate -// ParsedFloat accordingly. -// -// format_flags is a bitmask value specifying what patterns this API will match. -// `scientific` and `fixed` are honored per std::from_chars rules -// ([utility.from.chars], C++17): if exactly one of these bits is set, then an -// exponent is required, or dislallowed, respectively. -// -// Template parameter `base` must be either 10 or 16. For base 16, a "0x" is -// *not* consumed. The `hex` bit from format_flags is ignored by ParseFloat. -template <int base> -ParsedFloat ParseFloat(const char* begin, const char* end, - absl::chars_format format_flags); - -extern template ParsedFloat ParseFloat<10>(const char* begin, const char* end, - absl::chars_format format_flags); -extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end, - absl::chars_format format_flags); - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_parse_test.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_parse_test.cc deleted file mode 100644 index bc2d11187651..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/charconv_parse_test.cc +++ /dev/null @@ -1,357 +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/strings/internal/charconv_parse.h" - -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/str_cat.h" - -using absl::chars_format; -using absl::strings_internal::FloatType; -using absl::strings_internal::ParsedFloat; -using absl::strings_internal::ParseFloat; - -namespace { - -// Check that a given string input is parsed to the expected mantissa and -// exponent. -// -// Input string `s` must contain a '$' character. It marks the end of the -// characters that should be consumed by the match. It is stripped from the -// input to ParseFloat. -// -// If input string `s` contains '[' and ']' characters, these mark the region -// of characters that should be marked as the "subrange". For NaNs, this is -// the location of the extended NaN string. For numbers, this is the location -// of the full, over-large mantissa. -template <int base> -void ExpectParsedFloat(std::string s, absl::chars_format format_flags, - FloatType expected_type, uint64_t expected_mantissa, - int expected_exponent, - int expected_literal_exponent = -999) { - SCOPED_TRACE(s); - - int begin_subrange = -1; - int end_subrange = -1; - // If s contains '[' and ']', then strip these characters and set the subrange - // indices appropriately. - std::string::size_type open_bracket_pos = s.find('['); - if (open_bracket_pos != std::string::npos) { - begin_subrange = static_cast<int>(open_bracket_pos); - s.replace(open_bracket_pos, 1, ""); - std::string::size_type close_bracket_pos = s.find(']'); - ABSL_RAW_CHECK(close_bracket_pos != absl::string_view::npos, - "Test input contains [ without matching ]"); - end_subrange = static_cast<int>(close_bracket_pos); - s.replace(close_bracket_pos, 1, ""); - } - const std::string::size_type expected_characters_matched = s.find('$'); - ABSL_RAW_CHECK(expected_characters_matched != std::string::npos, - "Input string must contain $"); - s.replace(expected_characters_matched, 1, ""); - - ParsedFloat parsed = - ParseFloat<base>(s.data(), s.data() + s.size(), format_flags); - - EXPECT_NE(parsed.end, nullptr); - if (parsed.end == nullptr) { - return; // The following tests are not useful if we fully failed to parse - } - EXPECT_EQ(parsed.type, expected_type); - if (begin_subrange == -1) { - EXPECT_EQ(parsed.subrange_begin, nullptr); - EXPECT_EQ(parsed.subrange_end, nullptr); - } else { - EXPECT_EQ(parsed.subrange_begin, s.data() + begin_subrange); - EXPECT_EQ(parsed.subrange_end, s.data() + end_subrange); - } - if (parsed.type == FloatType::kNumber) { - EXPECT_EQ(parsed.mantissa, expected_mantissa); - EXPECT_EQ(parsed.exponent, expected_exponent); - if (expected_literal_exponent != -999) { - EXPECT_EQ(parsed.literal_exponent, expected_literal_exponent); - } - } - auto characters_matched = static_cast<int>(parsed.end - s.data()); - EXPECT_EQ(characters_matched, expected_characters_matched); -} - -// Check that a given string input is parsed to the expected mantissa and -// exponent. -// -// Input string `s` must contain a '$' character. It marks the end of the -// characters that were consumed by the match. -template <int base> -void ExpectNumber(std::string s, absl::chars_format format_flags, - uint64_t expected_mantissa, int expected_exponent, - int expected_literal_exponent = -999) { - ExpectParsedFloat<base>(std::move(s), format_flags, FloatType::kNumber, - expected_mantissa, expected_exponent, - expected_literal_exponent); -} - -// Check that a given string input is parsed to the given special value. -// -// This tests against both number bases, since infinities and NaNs have -// identical representations in both modes. -void ExpectSpecial(const std::string& s, absl::chars_format format_flags, - FloatType type) { - ExpectParsedFloat<10>(s, format_flags, type, 0, 0); - ExpectParsedFloat<16>(s, format_flags, type, 0, 0); -} - -// Check that a given input string is not matched by Float. -template <int base> -void ExpectFailedParse(absl::string_view s, absl::chars_format format_flags) { - ParsedFloat parsed = - ParseFloat<base>(s.data(), s.data() + s.size(), format_flags); - EXPECT_EQ(parsed.end, nullptr); -} - -TEST(ParseFloat, SimpleValue) { - // Test that various forms of floating point numbers all parse correctly. - ExpectNumber<10>("1.23456789e5$", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e+5$", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789E5$", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e05$", chars_format::general, 123456789, -3); - ExpectNumber<10>("123.456789e3$", chars_format::general, 123456789, -3); - ExpectNumber<10>("0.000123456789e9$", chars_format::general, 123456789, -3); - ExpectNumber<10>("123456.789$", chars_format::general, 123456789, -3); - ExpectNumber<10>("123456789e-3$", chars_format::general, 123456789, -3); - - ExpectNumber<16>("1.234abcdefp28$", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1.234abcdefp+28$", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1.234ABCDEFp28$", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1.234AbCdEfP0028$", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("123.4abcdefp20$", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("0.0001234abcdefp44$", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("1234abcd.ef$", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1234abcdefp-8$", chars_format::general, 0x1234abcdef, -8); - - // ExpectNumber does not attempt to drop trailing zeroes. - ExpectNumber<10>("0001.2345678900e005$", chars_format::general, 12345678900, - -5); - ExpectNumber<16>("0001.234abcdef000p28$", chars_format::general, - 0x1234abcdef000, -20); - - // Ensure non-matching characters after a number are ignored, even when they - // look like potentially matching characters. - ExpectNumber<10>("1.23456789e5$ ", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e5$e5e5", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e5$.25", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e5$-", chars_format::general, 123456789, -3); - ExpectNumber<10>("1.23456789e5$PUPPERS!!!", chars_format::general, 123456789, - -3); - ExpectNumber<10>("123456.789$efghij", chars_format::general, 123456789, -3); - ExpectNumber<10>("123456.789$e", chars_format::general, 123456789, -3); - ExpectNumber<10>("123456.789$p5", chars_format::general, 123456789, -3); - ExpectNumber<10>("123456.789$.10", chars_format::general, 123456789, -3); - - ExpectNumber<16>("1.234abcdefp28$ ", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("1.234abcdefp28$p28", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("1.234abcdefp28$.125", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("1.234abcdefp28$-", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1.234abcdefp28$KITTEHS!!!", chars_format::general, - 0x1234abcdef, -8); - ExpectNumber<16>("1234abcd.ef$ghijk", chars_format::general, 0x1234abcdef, - -8); - ExpectNumber<16>("1234abcd.ef$p", chars_format::general, 0x1234abcdef, -8); - ExpectNumber<16>("1234abcd.ef$.10", chars_format::general, 0x1234abcdef, -8); - - // Ensure we can read a full resolution mantissa without overflow. - ExpectNumber<10>("9999999999999999999$", chars_format::general, - 9999999999999999999u, 0); - ExpectNumber<16>("fffffffffffffff$", chars_format::general, - 0xfffffffffffffffu, 0); - - // Check that zero is consistently read. - ExpectNumber<10>("0$", chars_format::general, 0, 0); - ExpectNumber<16>("0$", chars_format::general, 0, 0); - ExpectNumber<10>("000000000000000000000000000000000000000$", - chars_format::general, 0, 0); - ExpectNumber<16>("000000000000000000000000000000000000000$", - chars_format::general, 0, 0); - ExpectNumber<10>("0000000000000000000000.000000000000000000$", - chars_format::general, 0, 0); - ExpectNumber<16>("0000000000000000000000.000000000000000000$", - chars_format::general, 0, 0); - ExpectNumber<10>("0.00000000000000000000000000000000e123456$", - chars_format::general, 0, 0); - ExpectNumber<16>("0.00000000000000000000000000000000p123456$", - chars_format::general, 0, 0); -} - -TEST(ParseFloat, LargeDecimalMantissa) { - // After 19 significant decimal digits in the mantissa, ParsedFloat will - // truncate additional digits. We need to test that: - // 1) the truncation to 19 digits happens - // 2) the returned exponent reflects the dropped significant digits - // 3) a correct literal_exponent is set - // - // If and only if a significant digit is found after 19 digits, then the - // entirety of the mantissa in case the exact value is needed to make a - // rounding decision. The [ and ] characters below denote where such a - // subregion was marked by by ParseFloat. They are not part of the input. - - // Mark a capture group only if a dropped digit is significant (nonzero). - ExpectNumber<10>("100000000000000000000000000$", chars_format::general, - 1000000000000000000, - /* adjusted exponent */ 8); - - ExpectNumber<10>("123456789123456789100000000$", chars_format::general, - 1234567891234567891, - /* adjusted exponent */ 8); - - ExpectNumber<10>("[123456789123456789123456789]$", chars_format::general, - 1234567891234567891, - /* adjusted exponent */ 8, - /* literal exponent */ 0); - - ExpectNumber<10>("[123456789123456789100000009]$", chars_format::general, - 1234567891234567891, - /* adjusted exponent */ 8, - /* literal exponent */ 0); - - ExpectNumber<10>("[123456789123456789120000000]$", chars_format::general, - 1234567891234567891, - /* adjusted exponent */ 8, - /* literal exponent */ 0); - - // Leading zeroes should not count towards the 19 significant digit limit - ExpectNumber<10>("[00000000123456789123456789123456789]$", - chars_format::general, 1234567891234567891, - /* adjusted exponent */ 8, - /* literal exponent */ 0); - - ExpectNumber<10>("00000000123456789123456789100000000$", - chars_format::general, 1234567891234567891, - /* adjusted exponent */ 8); - - // Truncated digits after the decimal point should not cause a further - // exponent adjustment. - ExpectNumber<10>("1.234567891234567891e123$", chars_format::general, - 1234567891234567891, 105); - ExpectNumber<10>("[1.23456789123456789123456789]e123$", chars_format::general, - 1234567891234567891, - /* adjusted exponent */ 105, - /* literal exponent */ 123); - - // Ensure we truncate, and not round. (The from_chars algorithm we use - // depends on our guess missing low, if it misses, so we need the rounding - // error to be downward.) - ExpectNumber<10>("[1999999999999999999999]$", chars_format::general, - 1999999999999999999, - /* adjusted exponent */ 3, - /* literal exponent */ 0); -} - -TEST(ParseFloat, LargeHexadecimalMantissa) { - // After 15 significant hex digits in the mantissa, ParsedFloat will treat - // additional digits as sticky, We need to test that: - // 1) The truncation to 15 digits happens - // 2) The returned exponent reflects the dropped significant digits - // 3) If a nonzero digit is dropped, the low bit of mantissa is set. - - ExpectNumber<16>("123456789abcdef123456789abcdef$", chars_format::general, - 0x123456789abcdef, 60); - - // Leading zeroes should not count towards the 15 significant digit limit - ExpectNumber<16>("000000123456789abcdef123456789abcdef$", - chars_format::general, 0x123456789abcdef, 60); - - // Truncated digits after the radix point should not cause a further - // exponent adjustment. - ExpectNumber<16>("1.23456789abcdefp100$", chars_format::general, - 0x123456789abcdef, 44); - ExpectNumber<16>("1.23456789abcdef123456789abcdefp100$", - chars_format::general, 0x123456789abcdef, 44); - - // test sticky digit behavior. The low bit should be set iff any dropped - // digit is nonzero. - ExpectNumber<16>("123456789abcdee123456789abcdee$", chars_format::general, - 0x123456789abcdef, 60); - ExpectNumber<16>("123456789abcdee000000000000001$", chars_format::general, - 0x123456789abcdef, 60); - ExpectNumber<16>("123456789abcdee000000000000000$", chars_format::general, - 0x123456789abcdee, 60); -} - -TEST(ParseFloat, ScientificVsFixed) { - // In fixed mode, an exponent is never matched (but the remainder of the - // number will be matched.) - ExpectNumber<10>("1.23456789$e5", chars_format::fixed, 123456789, -8); - ExpectNumber<10>("123456.789$", chars_format::fixed, 123456789, -3); - ExpectNumber<16>("1.234abcdef$p28", chars_format::fixed, 0x1234abcdef, -36); - ExpectNumber<16>("1234abcd.ef$", chars_format::fixed, 0x1234abcdef, -8); - - // In scientific mode, numbers don't match *unless* they have an exponent. - ExpectNumber<10>("1.23456789e5$", chars_format::scientific, 123456789, -3); - ExpectFailedParse<10>("-123456.789$", chars_format::scientific); - ExpectNumber<16>("1.234abcdefp28$", chars_format::scientific, 0x1234abcdef, - -8); - ExpectFailedParse<16>("1234abcd.ef$", chars_format::scientific); -} - -TEST(ParseFloat, Infinity) { - ExpectFailedParse<10>("in", chars_format::general); - ExpectFailedParse<16>("in", chars_format::general); - ExpectFailedParse<10>("inx", chars_format::general); - ExpectFailedParse<16>("inx", chars_format::general); - ExpectSpecial("inf$", chars_format::general, FloatType::kInfinity); - ExpectSpecial("Inf$", chars_format::general, FloatType::kInfinity); - ExpectSpecial("INF$", chars_format::general, FloatType::kInfinity); - ExpectSpecial("inf$inite", chars_format::general, FloatType::kInfinity); - ExpectSpecial("iNfInItY$", chars_format::general, FloatType::kInfinity); - ExpectSpecial("infinity$!!!", chars_format::general, FloatType::kInfinity); -} - -TEST(ParseFloat, NaN) { - ExpectFailedParse<10>("na", chars_format::general); - ExpectFailedParse<16>("na", chars_format::general); - ExpectFailedParse<10>("nah", chars_format::general); - ExpectFailedParse<16>("nah", chars_format::general); - ExpectSpecial("nan$", chars_format::general, FloatType::kNan); - ExpectSpecial("NaN$", chars_format::general, FloatType::kNan); - ExpectSpecial("nAn$", chars_format::general, FloatType::kNan); - ExpectSpecial("NAN$", chars_format::general, FloatType::kNan); - ExpectSpecial("NaN$aNaNaNaNaBatman!", chars_format::general, FloatType::kNan); - - // A parenthesized sequence of the characters [a-zA-Z0-9_] is allowed to - // appear after an NaN. Check that this is allowed, and that the correct - // characters are grouped. - // - // (The characters [ and ] in the pattern below delimit the expected matched - // subgroup; they are not part of the input passed to ParseFloat.) - ExpectSpecial("nan([0xabcdef])$", chars_format::general, FloatType::kNan); - ExpectSpecial("nan([0xabcdef])$...", chars_format::general, FloatType::kNan); - ExpectSpecial("nan([0xabcdef])$)...", chars_format::general, FloatType::kNan); - ExpectSpecial("nan([])$", chars_format::general, FloatType::kNan); - ExpectSpecial("nan([aAzZ09_])$", chars_format::general, FloatType::kNan); - // If the subgroup contains illegal characters, don't match it at all. - ExpectSpecial("nan$(bad-char)", chars_format::general, FloatType::kNan); - // Also cope with a missing close paren. - ExpectSpecial("nan$(0xabcdef", chars_format::general, FloatType::kNan); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/cord_internal.h b/third_party/abseil_cpp/absl/strings/internal/cord_internal.h deleted file mode 100644 index aa91a691b949..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/cord_internal.h +++ /dev/null @@ -1,270 +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_INTERNAL_H_ -#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_ - -#include <atomic> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <type_traits> - -#include "absl/base/internal/invoke.h" -#include "absl/container/internal/compressed_tuple.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace cord_internal { - -// Wraps std::atomic for reference counting. -class Refcount { - public: - constexpr Refcount() : count_{kRefIncrement} {} - struct Immortal {}; - explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {} - - // Increments the reference count. Imposes no memory ordering. - inline void Increment() { - count_.fetch_add(kRefIncrement, std::memory_order_relaxed); - } - - // Asserts that the current refcount is greater than 0. If the refcount is - // greater than 1, decrements the reference count. - // - // Returns false if there are no references outstanding; true otherwise. - // Inserts barriers to ensure that state written before this method returns - // false will be visible to a thread that just observed this method returning - // false. - inline bool Decrement() { - int32_t refcount = count_.load(std::memory_order_acquire); - assert(refcount > 0 || refcount & kImmortalTag); - return refcount != kRefIncrement && - count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) != - kRefIncrement; - } - - // Same as Decrement but expect that refcount is greater than 1. - inline bool DecrementExpectHighRefcount() { - int32_t refcount = - count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel); - assert(refcount > 0 || refcount & kImmortalTag); - return refcount != kRefIncrement; - } - - // Returns the current reference count using acquire semantics. - inline int32_t Get() const { - return count_.load(std::memory_order_acquire) >> kImmortalShift; - } - - // Returns whether the atomic integer is 1. - // If the reference count is used in the conventional way, a - // reference count of 1 implies that the current thread owns the - // reference and no other thread shares it. - // This call performs the test for a reference count of one, and - // performs the memory barrier needed for the owning thread - // to act on the object, knowing that it has exclusive access to the - // object. - inline bool IsOne() { - return count_.load(std::memory_order_acquire) == kRefIncrement; - } - - bool IsImmortal() const { - return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0; - } - - private: - // We reserve the bottom bit to tag a reference count as immortal. - // By making it `1` we ensure that we never reach `0` when adding/subtracting - // `2`, thus it never looks as if it should be destroyed. - // These are used for the StringConstant constructor where we do not increase - // the refcount at construction time (due to constinit requirements) but we - // will still decrease it at destruction time to avoid branching on Unref. - enum { - kImmortalShift = 1, - kRefIncrement = 1 << kImmortalShift, - kImmortalTag = kRefIncrement - 1 - }; - - std::atomic<int32_t> count_; -}; - -// The overhead of a vtable is too much for Cord, so we roll our own subclasses -// using only a single byte to differentiate classes from each other - the "tag" -// byte. Define the subclasses first so we can provide downcasting helper -// functions in the base class. - -struct CordRepConcat; -struct CordRepSubstring; -struct CordRepExternal; - -// 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, -}; - -struct CordRep { - CordRep() = default; - constexpr CordRep(Refcount::Immortal immortal, size_t l) - : length(l), refcount(immortal), tag(EXTERNAL), data{} {} - - // The following three fields have to be less than 32 bytes since - // that is the smallest supported flat node size. - size_t length; - Refcount refcount; - // If tag < FLAT, it represents CordRepKind and indicates the type of node. - // Otherwise, the node type is CordRepFlat and the tag is the encoded size. - uint8_t tag; - char data[1]; // Starting point for flat array: MUST BE LAST FIELD of CordRep - - inline CordRepConcat* concat(); - inline const CordRepConcat* concat() const; - inline CordRepSubstring* substring(); - inline const CordRepSubstring* substring() const; - inline CordRepExternal* external(); - inline const CordRepExternal* external() const; -}; - -struct CordRepConcat : public CordRep { - CordRep* left; - CordRep* right; - - 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 { - size_t start; // Starting offset of substring in child - CordRep* child; -}; - -// Type for function pointer that will invoke the releaser function and also -// delete the `CordRepExternalImpl` corresponding to the passed in -// `CordRepExternal`. -using ExternalReleaserInvoker = void (*)(CordRepExternal*); - -// External CordReps are allocated together with a type erased releaser. The -// releaser is stored in the memory directly following the CordRepExternal. -struct CordRepExternal : public CordRep { - CordRepExternal() = default; - explicit constexpr CordRepExternal(absl::string_view str) - : CordRep(Refcount::Immortal{}, str.size()), - base(str.data()), - releaser_invoker(nullptr) {} - - const char* base; - // Pointer to function that knows how to call and destroy the releaser. - ExternalReleaserInvoker releaser_invoker; -}; - -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); - } -}; - -template <typename Str> -struct ConstInitExternalStorage { - ABSL_CONST_INIT static CordRepExternal value; -}; - -template <typename Str> -CordRepExternal ConstInitExternalStorage<Str>::value(Str::value); - -enum { - kMaxInline = 15, - // Tag byte & kMaxInline means we are storing a pointer. - kTreeFlag = 1 << 4, - // Tag byte & kProfiledFlag means we are profiling the Cord. - kProfiledFlag = 1 << 5 -}; - -// If the data has length <= kMaxInline, we store it in `as_chars`, and -// store the size in `tagged_size`. -// 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`. -struct AsTree { - absl::cord_internal::CordRep* rep; - char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1]; - char tagged_size; -}; - -constexpr char GetOrNull(absl::string_view data, size_t pos) { - return pos < data.size() ? data[pos] : '\0'; -} - -union InlineData { - constexpr InlineData() : as_chars{} {} - explicit constexpr InlineData(AsTree tree) : as_tree(tree) {} - 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())} {} - - AsTree as_tree; - char as_chars[kMaxInline + 1]; -}; -static_assert(sizeof(InlineData) == kMaxInline + 1, ""); -static_assert(sizeof(AsTree) == sizeof(InlineData), ""); -static_assert(offsetof(AsTree, tagged_size) == kMaxInline, ""); - -} // 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/escaping.cc b/third_party/abseil_cpp/absl/strings/internal/escaping.cc deleted file mode 100644 index c5271286ad00..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/escaping.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 "absl/strings/internal/escaping.h" - -#include "absl/base/internal/endian.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -const char kBase64Chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) { - // Base64 encodes three bytes of input at a time. If the input is not - // divisible by three, we pad as appropriate. - // - // (from https://tools.ietf.org/html/rfc3548) - // Special processing is performed if fewer than 24 bits are available - // at the end of the data being encoded. A full encoding quantum is - // always completed at the end of a quantity. When fewer than 24 input - // bits are available in an input group, zero bits are added (on the - // right) to form an integral number of 6-bit groups. Padding at the - // end of the data is performed using the '=' character. Since all base - // 64 input is an integral number of octets, only the following cases - // can arise: - - // Base64 encodes each three bytes of input into four bytes of output. - size_t len = (input_len / 3) * 4; - - if (input_len % 3 == 0) { - // (from https://tools.ietf.org/html/rfc3548) - // (1) the final quantum of encoding input is an integral multiple of 24 - // bits; here, the final unit of encoded output will be an integral - // multiple of 4 characters with no "=" padding, - } else if (input_len % 3 == 1) { - // (from https://tools.ietf.org/html/rfc3548) - // (2) the final quantum of encoding input is exactly 8 bits; here, the - // final unit of encoded output will be two characters followed by two - // "=" padding characters, or - len += 2; - if (do_padding) { - len += 2; - } - } else { // (input_len % 3 == 2) - // (from https://tools.ietf.org/html/rfc3548) - // (3) the final quantum of encoding input is exactly 16 bits; here, the - // final unit of encoded output will be three characters followed by one - // "=" padding character. - len += 3; - if (do_padding) { - len += 1; - } - } - - assert(len >= input_len); // make sure we didn't overflow - return len; -} - -size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest, - size_t szdest, const char* base64, - bool do_padding) { - static const char kPad64 = '='; - - if (szsrc * 4 > szdest * 3) return 0; - - char* cur_dest = dest; - const unsigned char* cur_src = src; - - char* const limit_dest = dest + szdest; - const unsigned char* const limit_src = src + szsrc; - - // Three bytes of data encodes to four characters of cyphertext. - // So we can pump through three-byte chunks atomically. - if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3. - while (cur_src < limit_src - 3) { // While we have >= 32 bits. - uint32_t in = absl::big_endian::Load32(cur_src) >> 8; - - cur_dest[0] = base64[in >> 18]; - in &= 0x3FFFF; - cur_dest[1] = base64[in >> 12]; - in &= 0xFFF; - cur_dest[2] = base64[in >> 6]; - in &= 0x3F; - cur_dest[3] = base64[in]; - - cur_dest += 4; - cur_src += 3; - } - } - // To save time, we didn't update szdest or szsrc in the loop. So do it now. - szdest = limit_dest - cur_dest; - szsrc = limit_src - cur_src; - - /* now deal with the tail (<=3 bytes) */ - switch (szsrc) { - case 0: - // Nothing left; nothing more to do. - break; - case 1: { - // One byte left: this encodes to two characters, and (optionally) - // two pad characters to round out the four-character cypherblock. - if (szdest < 2) return 0; - uint32_t in = cur_src[0]; - cur_dest[0] = base64[in >> 2]; - in &= 0x3; - cur_dest[1] = base64[in << 4]; - cur_dest += 2; - szdest -= 2; - if (do_padding) { - if (szdest < 2) return 0; - cur_dest[0] = kPad64; - cur_dest[1] = kPad64; - cur_dest += 2; - szdest -= 2; - } - break; - } - case 2: { - // Two bytes left: this encodes to three characters, and (optionally) - // one pad character to round out the four-character cypherblock. - if (szdest < 3) return 0; - uint32_t in = absl::big_endian::Load16(cur_src); - cur_dest[0] = base64[in >> 10]; - in &= 0x3FF; - cur_dest[1] = base64[in >> 4]; - in &= 0x00F; - cur_dest[2] = base64[in << 2]; - cur_dest += 3; - szdest -= 3; - if (do_padding) { - if (szdest < 1) return 0; - cur_dest[0] = kPad64; - cur_dest += 1; - szdest -= 1; - } - break; - } - case 3: { - // Three bytes left: same as in the big loop above. We can't do this in - // the loop because the loop above always reads 4 bytes, and the fourth - // byte is past the end of the input. - if (szdest < 4) return 0; - uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1); - cur_dest[0] = base64[in >> 18]; - in &= 0x3FFFF; - cur_dest[1] = base64[in >> 12]; - in &= 0xFFF; - cur_dest[2] = base64[in >> 6]; - in &= 0x3F; - cur_dest[3] = base64[in]; - cur_dest += 4; - szdest -= 4; - break; - } - default: - // Should not be reached: blocks of 4 bytes are handled - // in the while loop before this switch statement. - ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc); - break; - } - return (cur_dest - dest); -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/escaping.h b/third_party/abseil_cpp/absl/strings/internal/escaping.h deleted file mode 100644 index 6a9ce602d9ed..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/escaping.h +++ /dev/null @@ -1,58 +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_ESCAPING_H_ -#define ABSL_STRINGS_INTERNAL_ESCAPING_H_ - -#include <cassert> - -#include "absl/strings/internal/resize_uninitialized.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -ABSL_CONST_INIT extern const char kBase64Chars[]; - -// Calculates how long a string will be when it is base64 encoded given its -// length and whether or not the result should be padded. -size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding); - -// Base64-encodes `src` using the alphabet provided in `base64` and writes the -// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars -// until its length is a multiple of 3. Returns the length of `dest`. -size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest, - size_t szdest, const char* base64, bool do_padding); - -// Base64-encodes `src` using the alphabet provided in `base64` and writes the -// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars -// until its length is a multiple of 3. -template <typename String> -void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest, - bool do_padding, const char* base64_chars) { - const size_t calc_escaped_size = - CalculateBase64EscapedLenInternal(szsrc, do_padding); - STLStringResizeUninitialized(dest, calc_escaped_size); - - const size_t escaped_len = Base64EscapeInternal( - src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding); - assert(calc_escaped_size == escaped_len); - dest->erase(escaped_len); -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_ESCAPING_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/escaping_test_common.h b/third_party/abseil_cpp/absl/strings/internal/escaping_test_common.h deleted file mode 100644 index 7b18017a0890..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/escaping_test_common.h +++ /dev/null @@ -1,133 +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 test contains common things needed by both escaping_test.cc and -// escaping_benchmark.cc. - -#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_ -#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_ - -#include <array> -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -struct base64_testcase { - absl::string_view plaintext; - absl::string_view cyphertext; -}; - -inline const std::array<base64_testcase, 5>& base64_strings() { - static const std::array<base64_testcase, 5> testcase{{ - // Some google quotes - // Cyphertext created with "uuencode (GNU sharutils) 4.6.3" - // (Note that we're testing the websafe encoding, though, so if - // you add messages, be sure to run "tr -- '+/' '-_'" on the output) - { "I was always good at math and science, and I never realized " - "that was unusual or somehow undesirable. So one of the things " - "I care a lot about is helping to remove that stigma, " - "to show girls that you can be feminine, you can like the things " - "that girls like, but you can also be really good at technology. " - "You can be really good at building things." - " - Marissa Meyer, Newsweek, 2010-12-22" "\n", - - "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg" - "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu" - "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg" - "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo" - "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp" - "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs" - "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy" - "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll" - "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" }, - - { "Typical first year for a new cluster: " - "~0.5 overheating " - "~1 PDU failure " - "~1 rack-move " - "~1 network rewiring " - "~20 rack failures " - "~5 racks go wonky " - "~8 network maintenances " - "~12 router reloads " - "~3 router failures " - "~dozens of minor 30-second blips for dns " - "~1000 individual machine failures " - "~thousands of hard drive failures " - "slow disks, bad memory, misconfigured machines, flaky machines, etc." - " - Jeff Dean, The Joys of Real Hardware" "\n", - - "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92" - "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3" - "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv" - "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk" - "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv" - "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp" - "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg" - "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs" - "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS" - "ZWFsIEhhcmR3YXJlCg" }, - - { "I'm the head of the webspam team at Google. " - "That means that if you type your name into Google and get porn back, " - "it's my fault. Unless you're a porn star, in which case porn is a " - "completely reasonable response." - " - Matt Cutts, Google Plus" "\n", - - "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg" - "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv" - "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz" - "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg" - "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs" - "IEdvb2dsZSBQbHVzCg" }, - - { "It will still be a long time before machines approach human " - "intelligence. " - "But luckily, machines don't actually have to be intelligent; " - "they just have to fake it. Access to a wealth of information, " - "combined with a rudimentary decision-making capacity, " - "can often be almost as useful. Of course, the results are better yet " - "when coupled with intelligence. A reference librarian with access to " - "a good search engine is a formidable tool." - " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" - "\n", - - "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg" - "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj" - "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg" - "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo" - "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg" - "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0" - "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy" - "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl" - "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu" - "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp" - "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw" - "NAo" }, - - // Degenerate edge case - { "", - "" }, - }}; - - return testcase; -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/memutil.cc b/third_party/abseil_cpp/absl/strings/internal/memutil.cc deleted file mode 100644 index 2519c6881e35..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/memutil.cc +++ /dev/null @@ -1,112 +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/strings/internal/memutil.h" - -#include <cstdlib> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -int memcasecmp(const char* s1, const char* s2, size_t len) { - const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1); - const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2); - - for (size_t i = 0; i < len; i++) { - const int diff = - int{static_cast<unsigned char>(absl::ascii_tolower(us1[i]))} - - int{static_cast<unsigned char>(absl::ascii_tolower(us2[i]))}; - if (diff != 0) return diff; - } - return 0; -} - -char* memdup(const char* s, size_t slen) { - void* copy; - if ((copy = malloc(slen)) == nullptr) return nullptr; - memcpy(copy, s, slen); - return reinterpret_cast<char*>(copy); -} - -char* memrchr(const char* s, int c, size_t slen) { - for (const char* e = s + slen - 1; e >= s; e--) { - if (*e == c) return const_cast<char*>(e); - } - return nullptr; -} - -size_t memspn(const char* s, size_t slen, const char* accept) { - const char* p = s; - const char* spanp; - char c, sc; - -cont: - c = *p++; - if (slen-- == 0) return p - 1 - s; - for (spanp = accept; (sc = *spanp++) != '\0';) - if (sc == c) goto cont; - return p - 1 - s; -} - -size_t memcspn(const char* s, size_t slen, const char* reject) { - const char* p = s; - const char* spanp; - char c, sc; - - while (slen-- != 0) { - c = *p++; - for (spanp = reject; (sc = *spanp++) != '\0';) - if (sc == c) return p - 1 - s; - } - return p - s; -} - -char* mempbrk(const char* s, size_t slen, const char* accept) { - const char* scanp; - int sc; - - for (; slen; ++s, --slen) { - for (scanp = accept; (sc = *scanp++) != '\0';) - if (sc == *s) return const_cast<char*>(s); - } - return nullptr; -} - -// This is significantly faster for case-sensitive matches with very -// few possible matches. See unit test for benchmarks. -const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, - size_t neelen) { - if (0 == neelen) { - return phaystack; // even if haylen is 0 - } - if (haylen < neelen) return nullptr; - - const char* match; - const char* hayend = phaystack + haylen - neelen + 1; - // A static cast is used here to work around the fact that memchr returns - // a void* on Posix-compliant systems and const void* on Windows. - while ((match = static_cast<const char*>( - memchr(phaystack, pneedle[0], hayend - phaystack)))) { - if (memcmp(match, pneedle, neelen) == 0) - return match; - else - phaystack = match + 1; - } - return nullptr; -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/memutil.h b/third_party/abseil_cpp/absl/strings/internal/memutil.h deleted file mode 100644 index 9ad05358086c..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/memutil.h +++ /dev/null @@ -1,148 +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. -// - -// These routines provide mem versions of standard C string routines, -// such as strpbrk. They function exactly the same as the str versions, -// so if you wonder what they are, replace the word "mem" by -// "str" and check out the man page. I could return void*, as the -// strutil.h mem*() routines tend to do, but I return char* instead -// since this is by far the most common way these functions are called. -// -// The difference between the mem and str versions is the mem version -// takes a pointer and a length, rather than a '\0'-terminated string. -// The memcase* routines defined here assume the locale is "C" -// (they use absl::ascii_tolower instead of tolower). -// -// These routines are based on the BSD library. -// -// Here's a list of routines from string.h, and their mem analogues. -// Functions in lowercase are defined in string.h; those in UPPERCASE -// are defined here: -// -// strlen -- -// strcat strncat MEMCAT -// strcpy strncpy memcpy -// -- memccpy (very cool function, btw) -// -- memmove -// -- memset -// strcmp strncmp memcmp -// strcasecmp strncasecmp MEMCASECMP -// strchr memchr -// strcoll -- -// strxfrm -- -// strdup strndup MEMDUP -// strrchr MEMRCHR -// strspn MEMSPN -// strcspn MEMCSPN -// strpbrk MEMPBRK -// strstr MEMSTR MEMMEM -// (g)strcasestr MEMCASESTR MEMCASEMEM -// strtok -- -// strprefix MEMPREFIX (strprefix is from strutil.h) -// strcaseprefix MEMCASEPREFIX (strcaseprefix is from strutil.h) -// strsuffix MEMSUFFIX (strsuffix is from strutil.h) -// strcasesuffix MEMCASESUFFIX (strcasesuffix is from strutil.h) -// -- MEMIS -// -- MEMCASEIS -// strcount MEMCOUNT (strcount is from strutil.h) - -#ifndef ABSL_STRINGS_INTERNAL_MEMUTIL_H_ -#define ABSL_STRINGS_INTERNAL_MEMUTIL_H_ - -#include <cstddef> -#include <cstring> - -#include "absl/base/port.h" // disable some warnings on Windows -#include "absl/strings/ascii.h" // for absl::ascii_tolower - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -inline char* memcat(char* dest, size_t destlen, const char* src, - size_t srclen) { - return reinterpret_cast<char*>(memcpy(dest + destlen, src, srclen)); -} - -int memcasecmp(const char* s1, const char* s2, size_t len); -char* memdup(const char* s, size_t slen); -char* memrchr(const char* s, int c, size_t slen); -size_t memspn(const char* s, size_t slen, const char* accept); -size_t memcspn(const char* s, size_t slen, const char* reject); -char* mempbrk(const char* s, size_t slen, const char* accept); - -// This is for internal use only. Don't call this directly -template <bool case_sensitive> -const char* int_memmatch(const char* haystack, size_t haylen, - const char* needle, size_t neelen) { - if (0 == neelen) { - return haystack; // even if haylen is 0 - } - const char* hayend = haystack + haylen; - const char* needlestart = needle; - const char* needleend = needlestart + neelen; - - for (; haystack < hayend; ++haystack) { - char hay = case_sensitive - ? *haystack - : absl::ascii_tolower(static_cast<unsigned char>(*haystack)); - char nee = case_sensitive - ? *needle - : absl::ascii_tolower(static_cast<unsigned char>(*needle)); - if (hay == nee) { - if (++needle == needleend) { - return haystack + 1 - neelen; - } - } else if (needle != needlestart) { - // must back up haystack in case a prefix matched (find "aab" in "aaab") - haystack -= needle - needlestart; // for loop will advance one more - needle = needlestart; - } - } - return nullptr; -} - -// These are the guys you can call directly -inline const char* memstr(const char* phaystack, size_t haylen, - const char* pneedle) { - return int_memmatch<true>(phaystack, haylen, pneedle, strlen(pneedle)); -} - -inline const char* memcasestr(const char* phaystack, size_t haylen, - const char* pneedle) { - return int_memmatch<false>(phaystack, haylen, pneedle, strlen(pneedle)); -} - -inline const char* memmem(const char* phaystack, size_t haylen, - const char* pneedle, size_t needlelen) { - return int_memmatch<true>(phaystack, haylen, pneedle, needlelen); -} - -inline const char* memcasemem(const char* phaystack, size_t haylen, - const char* pneedle, size_t needlelen) { - return int_memmatch<false>(phaystack, haylen, pneedle, needlelen); -} - -// This is significantly faster for case-sensitive matches with very -// few possible matches. See unit test for benchmarks. -const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, - size_t neelen); - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/memutil_benchmark.cc b/third_party/abseil_cpp/absl/strings/internal/memutil_benchmark.cc deleted file mode 100644 index dc95c3e5e55a..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/memutil_benchmark.cc +++ /dev/null @@ -1,323 +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/strings/internal/memutil.h" - -#include <algorithm> -#include <cstdlib> - -#include "benchmark/benchmark.h" -#include "absl/strings/ascii.h" - -// We fill the haystack with aaaaaaaaaaaaaaaaaa...aaaab. -// That gives us: -// - an easy search: 'b' -// - a medium search: 'ab'. That means every letter is a possible match. -// - a pathological search: 'aaaaaa.......aaaaab' (half as many a's as haytack) -// We benchmark case-sensitive and case-insensitive versions of -// three memmem implementations: -// - memmem() from memutil.h -// - search() from STL -// - memmatch(), a custom implementation using memchr and memcmp. -// Here are sample results: -// -// Run on (12 X 3800 MHz CPU s) -// CPU Caches: -// L1 Data 32K (x6) -// L1 Instruction 32K (x6) -// L2 Unified 256K (x6) -// L3 Unified 15360K (x1) -// ---------------------------------------------------------------- -// Benchmark Time CPU Iterations -// ---------------------------------------------------------------- -// BM_Memmem 3583 ns 3582 ns 196469 2.59966GB/s -// BM_MemmemMedium 13743 ns 13742 ns 50901 693.986MB/s -// BM_MemmemPathological 13695030 ns 13693977 ns 51 713.133kB/s -// BM_Memcasemem 3299 ns 3299 ns 212942 2.82309GB/s -// BM_MemcasememMedium 16407 ns 16406 ns 42170 581.309MB/s -// BM_MemcasememPathological 17267745 ns 17266030 ns 41 565.598kB/s -// BM_Search 1610 ns 1609 ns 431321 5.78672GB/s -// BM_SearchMedium 11111 ns 11110 ns 63001 858.414MB/s -// BM_SearchPathological 12117390 ns 12116397 ns 58 805.984kB/s -// BM_Searchcase 3081 ns 3081 ns 229949 3.02313GB/s -// BM_SearchcaseMedium 16003 ns 16001 ns 44170 595.998MB/s -// BM_SearchcasePathological 15823413 ns 15821909 ns 44 617.222kB/s -// BM_Memmatch 197 ns 197 ns 3584225 47.2951GB/s -// BM_MemmatchMedium 52333 ns 52329 ns 13280 182.244MB/s -// BM_MemmatchPathological 659799 ns 659727 ns 1058 14.4556MB/s -// BM_Memcasematch 5460 ns 5460 ns 127606 1.70586GB/s -// BM_MemcasematchMedium 32861 ns 32857 ns 21258 290.248MB/s -// BM_MemcasematchPathological 15154243 ns 15153089 ns 46 644.464kB/s -// BM_MemmemStartup 5 ns 5 ns 150821500 -// BM_SearchStartup 5 ns 5 ns 150644203 -// BM_MemmatchStartup 7 ns 7 ns 97068802 -// -// Conclusions: -// -// The following recommendations are based on the sample results above. However, -// we have found that the performance of STL search can vary significantly -// depending on compiler and standard library implementation. We recommend you -// run the benchmarks for yourself on relevant platforms. -// -// If you need case-insensitive, STL search is slightly better than memmem for -// all cases. -// -// Case-sensitive is more subtle: -// Custom memmatch is _very_ fast at scanning, so if you have very few possible -// matches in your haystack, that's the way to go. Performance drops -// significantly with more matches. -// -// STL search is slightly faster than memmem in the medium and pathological -// benchmarks. However, the performance of memmem is currently more dependable -// across platforms and build configurations. - -namespace { - -constexpr int kHaystackSize = 10000; -constexpr int64_t kHaystackSize64 = kHaystackSize; -const char* MakeHaystack() { - char* haystack = new char[kHaystackSize]; - for (int i = 0; i < kHaystackSize - 1; ++i) haystack[i] = 'a'; - haystack[kHaystackSize - 1] = 'b'; - return haystack; -} -const char* const kHaystack = MakeHaystack(); - -void BM_Memmem(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memmem(kHaystack, kHaystackSize, "b", 1)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Memmem); - -void BM_MemmemMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memmem(kHaystack, kHaystackSize, "ab", 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemmemMedium); - -void BM_MemmemPathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(absl::strings_internal::memmem( - kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, - kHaystackSize - kHaystackSize / 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemmemPathological); - -void BM_Memcasemem(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memcasemem(kHaystack, kHaystackSize, "b", 1)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Memcasemem); - -void BM_MemcasememMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memcasemem(kHaystack, kHaystackSize, "ab", 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemcasememMedium); - -void BM_MemcasememPathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(absl::strings_internal::memcasemem( - kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, - kHaystackSize - kHaystackSize / 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemcasememPathological); - -bool case_eq(const char a, const char b) { - return absl::ascii_tolower(a) == absl::ascii_tolower(b); -} - -void BM_Search(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize - 1, - kHaystack + kHaystackSize)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Search); - -void BM_SearchMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize - 2, - kHaystack + kHaystackSize)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_SearchMedium); - -void BM_SearchPathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize / 2, - kHaystack + kHaystackSize)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_SearchPathological); - -void BM_Searchcase(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize - 1, - kHaystack + kHaystackSize, case_eq)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Searchcase); - -void BM_SearchcaseMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize - 2, - kHaystack + kHaystackSize, case_eq)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_SearchcaseMedium); - -void BM_SearchcasePathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, - kHaystack + kHaystackSize / 2, - kHaystack + kHaystackSize, case_eq)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_SearchcasePathological); - -char* memcasechr(const char* s, int c, size_t slen) { - c = absl::ascii_tolower(c); - for (; slen; ++s, --slen) { - if (absl::ascii_tolower(*s) == c) return const_cast<char*>(s); - } - return nullptr; -} - -const char* memcasematch(const char* phaystack, size_t haylen, - const char* pneedle, size_t neelen) { - if (0 == neelen) { - return phaystack; // even if haylen is 0 - } - if (haylen < neelen) return nullptr; - - const char* match; - const char* hayend = phaystack + haylen - neelen + 1; - while ((match = static_cast<char*>( - memcasechr(phaystack, pneedle[0], hayend - phaystack)))) { - if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0) - return match; - else - phaystack = match + 1; - } - return nullptr; -} - -void BM_Memmatch(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memmatch(kHaystack, kHaystackSize, "b", 1)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Memmatch); - -void BM_MemmatchMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::strings_internal::memmatch(kHaystack, kHaystackSize, "ab", 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemmatchMedium); - -void BM_MemmatchPathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(absl::strings_internal::memmatch( - kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, - kHaystackSize - kHaystackSize / 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemmatchPathological); - -void BM_Memcasematch(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "b", 1)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_Memcasematch); - -void BM_MemcasematchMedium(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "ab", 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemcasematchMedium); - -void BM_MemcasematchPathological(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, - kHaystack + kHaystackSize / 2, - kHaystackSize - kHaystackSize / 2)); - } - state.SetBytesProcessed(kHaystackSize64 * state.iterations()); -} -BENCHMARK(BM_MemcasematchPathological); - -void BM_MemmemStartup(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(absl::strings_internal::memmem( - kHaystack + kHaystackSize - 10, 10, kHaystack + kHaystackSize - 1, 1)); - } -} -BENCHMARK(BM_MemmemStartup); - -void BM_SearchStartup(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize( - std::search(kHaystack + kHaystackSize - 10, kHaystack + kHaystackSize, - kHaystack + kHaystackSize - 1, kHaystack + kHaystackSize)); - } -} -BENCHMARK(BM_SearchStartup); - -void BM_MemmatchStartup(benchmark::State& state) { - for (auto _ : state) { - benchmark::DoNotOptimize(absl::strings_internal::memmatch( - kHaystack + kHaystackSize - 10, 10, kHaystack + kHaystackSize - 1, 1)); - } -} -BENCHMARK(BM_MemmatchStartup); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/memutil_test.cc b/third_party/abseil_cpp/absl/strings/internal/memutil_test.cc deleted file mode 100644 index d8681ddf4e3b..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/memutil_test.cc +++ /dev/null @@ -1,179 +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. - -// Unit test for memutil.cc - -#include "absl/strings/internal/memutil.h" - -#include <cstdlib> - -#include "gtest/gtest.h" -#include "absl/strings/ascii.h" - -namespace { - -static char* memcasechr(const char* s, int c, size_t slen) { - c = absl::ascii_tolower(c); - for (; slen; ++s, --slen) { - if (absl::ascii_tolower(*s) == c) return const_cast<char*>(s); - } - return nullptr; -} - -static const char* memcasematch(const char* phaystack, size_t haylen, - const char* pneedle, size_t neelen) { - if (0 == neelen) { - return phaystack; // even if haylen is 0 - } - if (haylen < neelen) return nullptr; - - const char* match; - const char* hayend = phaystack + haylen - neelen + 1; - while ((match = static_cast<char*>( - memcasechr(phaystack, pneedle[0], hayend - phaystack)))) { - if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0) - return match; - else - phaystack = match + 1; - } - return nullptr; -} - -TEST(MemUtilTest, AllTests) { - // check memutil functions - char a[1000]; - absl::strings_internal::memcat(a, 0, "hello", sizeof("hello") - 1); - absl::strings_internal::memcat(a, 5, " there", sizeof(" there") - 1); - - EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO there", - sizeof("hello there") - 1), - 0); - EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO therf", - sizeof("hello there") - 1), - -1); - EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO therf", - sizeof("hello there") - 2), - 0); - EXPECT_EQ(absl::strings_internal::memcasecmp(a, "whatever", 0), 0); - - char* p = absl::strings_internal::memdup("hello", 5); - free(p); - - p = absl::strings_internal::memrchr("hello there", 'e', - sizeof("hello there") - 1); - EXPECT_TRUE(p && p[-1] == 'r'); - p = absl::strings_internal::memrchr("hello there", 'e', - sizeof("hello there") - 2); - EXPECT_TRUE(p && p[-1] == 'h'); - p = absl::strings_internal::memrchr("hello there", 'u', - sizeof("hello there") - 1); - EXPECT_TRUE(p == nullptr); - - int len = absl::strings_internal::memspn("hello there", - sizeof("hello there") - 1, "hole"); - EXPECT_EQ(len, sizeof("hello") - 1); - len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1, - "u"); - EXPECT_EQ(len, 0); - len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1, - ""); - EXPECT_EQ(len, 0); - len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1, - "trole h"); - EXPECT_EQ(len, sizeof("hello there") - 1); - len = absl::strings_internal::memspn("hello there!", - sizeof("hello there!") - 1, "trole h"); - EXPECT_EQ(len, sizeof("hello there") - 1); - len = absl::strings_internal::memspn("hello there!", - sizeof("hello there!") - 2, "trole h!"); - EXPECT_EQ(len, sizeof("hello there!") - 2); - - len = absl::strings_internal::memcspn("hello there", - sizeof("hello there") - 1, "leho"); - EXPECT_EQ(len, 0); - len = absl::strings_internal::memcspn("hello there", - sizeof("hello there") - 1, "u"); - EXPECT_EQ(len, sizeof("hello there") - 1); - len = absl::strings_internal::memcspn("hello there", - sizeof("hello there") - 1, ""); - EXPECT_EQ(len, sizeof("hello there") - 1); - len = absl::strings_internal::memcspn("hello there", - sizeof("hello there") - 1, " "); - EXPECT_EQ(len, 5); - - p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1, - "leho"); - EXPECT_TRUE(p && p[1] == 'e' && p[2] == 'l'); - p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1, - "nu"); - EXPECT_TRUE(p == nullptr); - p = absl::strings_internal::mempbrk("hello there!", - sizeof("hello there!") - 2, "!"); - EXPECT_TRUE(p == nullptr); - p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1, - " t "); - EXPECT_TRUE(p && p[-1] == 'o' && p[1] == 't'); - - { - const char kHaystack[] = "0123456789"; - EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 0, "", 0), kHaystack); - EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "012", 3), - kHaystack); - EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "0xx", 1), - kHaystack); - EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "789", 3), - kHaystack + 7); - EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "9xx", 1), - kHaystack + 9); - EXPECT_TRUE(absl::strings_internal::memmem(kHaystack, 10, "9xx", 3) == - nullptr); - EXPECT_TRUE(absl::strings_internal::memmem(kHaystack, 10, "xxx", 1) == - nullptr); - } - { - const char kHaystack[] = "aBcDeFgHiJ"; - EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 0, "", 0), - kHaystack); - EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "Abc", 3), - kHaystack); - EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "Axx", 1), - kHaystack); - EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "hIj", 3), - kHaystack + 7); - EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "jxx", 1), - kHaystack + 9); - EXPECT_TRUE(absl::strings_internal::memcasemem(kHaystack, 10, "jxx", 3) == - nullptr); - EXPECT_TRUE(absl::strings_internal::memcasemem(kHaystack, 10, "xxx", 1) == - nullptr); - } - { - const char kHaystack[] = "0123456789"; - EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 0, "", 0), kHaystack); - EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "012", 3), - kHaystack); - EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "0xx", 1), - kHaystack); - EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "789", 3), - kHaystack + 7); - EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "9xx", 1), - kHaystack + 9); - EXPECT_TRUE(absl::strings_internal::memmatch(kHaystack, 10, "9xx", 3) == - nullptr); - EXPECT_TRUE(absl::strings_internal::memmatch(kHaystack, 10, "xxx", 1) == - nullptr); - } -} - -} // namespace 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 deleted file mode 100644 index eaa88a88975b..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/numbers_test_common.h +++ /dev/null @@ -1,184 +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 contains common things needed by numbers_test.cc, -// numbers_legacy_test.cc and numbers_benchmark.cc. - -#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_ -#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_ - -#include <array> -#include <cstdint> -#include <limits> -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -template <typename IntType> -inline bool Itoa(IntType value, int base, std::string* destination) { - destination->clear(); - if (base <= 1 || base > 36) { - return false; - } - - if (value == 0) { - destination->push_back('0'); - return true; - } - - bool negative = value < 0; - while (value != 0) { - const IntType next_value = value / base; - // Can't use std::abs here because of problems when IntType is unsigned. - int remainder = - static_cast<int>(value > next_value * base ? value - next_value * base - : next_value * base - value); - char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10; - destination->insert(0, 1, c); - value = next_value; - } - - if (negative) { - destination->insert(0, 1, '-'); - } - return true; -} - -struct uint32_test_case { - const char* str; - bool expect_ok; - int base; // base to pass to the conversion function - uint32_t expected; -}; - -inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() { - static const std::array<uint32_test_case, 27> test_cases{{ - {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()}, - {"0x34234324", true, 16, 0x34234324}, - {"34234324", true, 16, 0x34234324}, - {"0", true, 16, 0}, - {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()}, - {" \f\v 46", true, 10, 46}, // must accept weird whitespace - {" \t\n 72717222", true, 8, 072717222}, - {" \t\n 072717222", true, 8, 072717222}, - {" \t\n 072717228", false, 8, 07271722}, - {"0", true, 0, 0}, - - // Base-10 version. - {"34234324", true, 0, 34234324}, - {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()}, - {"34234324 \n\t", true, 10, 34234324}, - - // Unusual base - {"0", true, 3, 0}, - {"2", true, 3, 2}, - {"11", true, 3, 4}, - - // Invalid uints. - {"", false, 0, 0}, - {" ", false, 0, 0}, - {"abc", false, 0, 0}, // would be valid hex, but prefix is missing - {"34234324a", false, 0, 34234324}, - {"34234.3", false, 0, 34234}, - {"-1", false, 0, 0}, - {" -123", false, 0, 0}, - {" \t\n -123", false, 0, 0}, - - // Out of bounds. - {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()}, - {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()}, - {nullptr, false, 0, 0}, - }}; - return test_cases; -} - -struct uint64_test_case { - const char* str; - bool expect_ok; - int base; - uint64_t expected; -}; - -inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() { - static const std::array<uint64_test_case, 34> test_cases{{ - {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}}, - {"3423432448783446", true, 16, int64_t{0x3423432448783446}}, - - {"0", true, 16, 0}, - {"000", true, 0, 0}, - {"0", true, 0, 0}, - {" \t\n 0xffffffffffffffff", true, 16, - (std::numeric_limits<uint64_t>::max)()}, - - {"012345670123456701234", true, 8, int64_t{012345670123456701234}}, - {"12345670123456701234", true, 8, int64_t{012345670123456701234}}, - - {"12845670123456701234", false, 8, 0}, - - // Base-10 version. - {"34234324487834466", true, 0, int64_t{34234324487834466}}, - - {" \t\n 18446744073709551615", true, 0, - (std::numeric_limits<uint64_t>::max)()}, - - {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}}, - - {" \f\v 46", true, 10, 46}, // must accept weird whitespace - - // Unusual base - {"0", true, 3, 0}, - {"2", true, 3, 2}, - {"11", true, 3, 4}, - - {"0", true, 0, 0}, - - // Invalid uints. - {"", false, 0, 0}, - {" ", false, 0, 0}, - {"abc", false, 0, 0}, - {"34234324487834466a", false, 0, 0}, - {"34234487834466.3", false, 0, 0}, - {"-1", false, 0, 0}, - {" -123", false, 0, 0}, - {" \t\n -123", false, 0, 0}, - - // Out of bounds. - {"18446744073709551616", false, 10, 0}, - {"18446744073709551616", false, 0, 0}, - {"0x10000000000000000", false, 16, - (std::numeric_limits<uint64_t>::max)()}, - {"0X10000000000000000", false, 16, - (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x. - {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()}, - {"0X10000000000000000", false, 0, - (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x. - - {"0x1234", true, 16, 0x1234}, - - // Base-10 string version. - {"1234", true, 0, 1234}, - {nullptr, false, 0, 0}, - }}; - return test_cases; -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/ostringstream.cc b/third_party/abseil_cpp/absl/strings/internal/ostringstream.cc deleted file mode 100644 index 05324c780c60..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/ostringstream.cc +++ /dev/null @@ -1,36 +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/strings/internal/ostringstream.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -OStringStream::Buf::int_type OStringStream::overflow(int c) { - assert(s_); - if (!Buf::traits_type::eq_int_type(c, Buf::traits_type::eof())) - s_->push_back(static_cast<char>(c)); - return 1; -} - -std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) { - assert(s_); - s_->append(s, n); - return n; -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/ostringstream.h b/third_party/abseil_cpp/absl/strings/internal/ostringstream.h deleted file mode 100644 index d25d60473f6d..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/ostringstream.h +++ /dev/null @@ -1,89 +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. - -#ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ -#define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ - -#include <cassert> -#include <ostream> -#include <streambuf> -#include <string> - -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// The same as std::ostringstream but appends to a user-specified std::string, -// and is faster. It is ~70% faster to create, ~50% faster to write to, and -// completely free to extract the result std::string. -// -// std::string s; -// OStringStream strm(&s); -// strm << 42 << ' ' << 3.14; // appends to `s` -// -// The stream object doesn't have to be named. Starting from C++11 operator<< -// works with rvalues of std::ostream. -// -// std::string s; -// OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s` -// -// OStringStream is faster to create than std::ostringstream but it's still -// relatively slow. Avoid creating multiple streams where a single stream will -// do. -// -// Creates unnecessary instances of OStringStream: slow. -// -// std::string s; -// OStringStream(&s) << 42; -// OStringStream(&s) << ' '; -// OStringStream(&s) << 3.14; -// -// Creates a single instance of OStringStream and reuses it: fast. -// -// std::string s; -// OStringStream strm(&s); -// strm << 42; -// strm << ' '; -// strm << 3.14; -// -// Note: flush() has no effect. No reason to call it. -class OStringStream : private std::basic_streambuf<char>, public std::ostream { - public: - // The argument can be null, in which case you'll need to call str(p) with a - // non-null argument before you can write to the stream. - // - // The destructor of OStringStream doesn't use the std::string. It's OK to - // destroy the std::string before the stream. - explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {} - - std::string* str() { return s_; } - const std::string* str() const { return s_; } - void str(std::string* s) { s_ = s; } - - private: - using Buf = std::basic_streambuf<char>; - - Buf::int_type overflow(int c) override; - std::streamsize xsputn(const char* s, std::streamsize n) override; - - std::string* s_; -}; - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/ostringstream_benchmark.cc b/third_party/abseil_cpp/absl/strings/internal/ostringstream_benchmark.cc deleted file mode 100644 index 5979f18236e3..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/ostringstream_benchmark.cc +++ /dev/null @@ -1,106 +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/strings/internal/ostringstream.h" - -#include <sstream> -#include <string> - -#include "benchmark/benchmark.h" - -namespace { - -enum StringType { - kNone, - kStdString, -}; - -// Benchmarks for std::ostringstream. -template <StringType kOutput> -void BM_StdStream(benchmark::State& state) { - const int num_writes = state.range(0); - const int bytes_per_write = state.range(1); - const std::string payload(bytes_per_write, 'x'); - for (auto _ : state) { - std::ostringstream strm; - benchmark::DoNotOptimize(strm); - for (int i = 0; i != num_writes; ++i) { - strm << payload; - } - switch (kOutput) { - case kNone: { - break; - } - case kStdString: { - std::string s = strm.str(); - benchmark::DoNotOptimize(s); - break; - } - } - } -} - -// Create the stream, optionally write to it, then destroy it. -BENCHMARK_TEMPLATE(BM_StdStream, kNone) - ->ArgPair(0, 0) - ->ArgPair(1, 16) // 16 bytes is small enough for SSO - ->ArgPair(1, 256) // 256 bytes requires heap allocation - ->ArgPair(1024, 256); -// Create the stream, write to it, get std::string out, then destroy. -BENCHMARK_TEMPLATE(BM_StdStream, kStdString) - ->ArgPair(1, 16) // 16 bytes is small enough for SSO - ->ArgPair(1, 256) // 256 bytes requires heap allocation - ->ArgPair(1024, 256); - -// Benchmarks for OStringStream. -template <StringType kOutput> -void BM_CustomStream(benchmark::State& state) { - const int num_writes = state.range(0); - const int bytes_per_write = state.range(1); - const std::string payload(bytes_per_write, 'x'); - for (auto _ : state) { - std::string out; - absl::strings_internal::OStringStream strm(&out); - benchmark::DoNotOptimize(strm); - for (int i = 0; i != num_writes; ++i) { - strm << payload; - } - switch (kOutput) { - case kNone: { - break; - } - case kStdString: { - std::string s = out; - benchmark::DoNotOptimize(s); - break; - } - } - } -} - -// Create the stream, optionally write to it, then destroy it. -BENCHMARK_TEMPLATE(BM_CustomStream, kNone) - ->ArgPair(0, 0) - ->ArgPair(1, 16) // 16 bytes is small enough for SSO - ->ArgPair(1, 256) // 256 bytes requires heap allocation - ->ArgPair(1024, 256); -// Create the stream, write to it, get std::string out, then destroy. -// It's not useful in practice to extract std::string from OStringStream; we -// measure it for completeness. -BENCHMARK_TEMPLATE(BM_CustomStream, kStdString) - ->ArgPair(1, 16) // 16 bytes is small enough for SSO - ->ArgPair(1, 256) // 256 bytes requires heap allocation - ->ArgPair(1024, 256); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/ostringstream_test.cc b/third_party/abseil_cpp/absl/strings/internal/ostringstream_test.cc deleted file mode 100644 index 2879e50eb38d..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/ostringstream_test.cc +++ /dev/null @@ -1,102 +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/strings/internal/ostringstream.h" - -#include <memory> -#include <ostream> -#include <string> -#include <type_traits> - -#include "gtest/gtest.h" - -namespace { - -TEST(OStringStream, IsOStream) { - static_assert( - std::is_base_of<std::ostream, absl::strings_internal::OStringStream>(), - ""); -} - -TEST(OStringStream, ConstructDestroy) { - { - absl::strings_internal::OStringStream strm(nullptr); - EXPECT_EQ(nullptr, strm.str()); - } - { - std::string s = "abc"; - { - absl::strings_internal::OStringStream strm(&s); - EXPECT_EQ(&s, strm.str()); - } - EXPECT_EQ("abc", s); - } - { - std::unique_ptr<std::string> s(new std::string); - absl::strings_internal::OStringStream strm(s.get()); - s.reset(); - } -} - -TEST(OStringStream, Str) { - std::string s1; - absl::strings_internal::OStringStream strm(&s1); - const absl::strings_internal::OStringStream& c_strm(strm); - - static_assert(std::is_same<decltype(strm.str()), std::string*>(), ""); - static_assert(std::is_same<decltype(c_strm.str()), const std::string*>(), ""); - - EXPECT_EQ(&s1, strm.str()); - EXPECT_EQ(&s1, c_strm.str()); - - strm.str(&s1); - EXPECT_EQ(&s1, strm.str()); - EXPECT_EQ(&s1, c_strm.str()); - - std::string s2; - strm.str(&s2); - EXPECT_EQ(&s2, strm.str()); - EXPECT_EQ(&s2, c_strm.str()); - - strm.str(nullptr); - EXPECT_EQ(nullptr, strm.str()); - EXPECT_EQ(nullptr, c_strm.str()); -} - -TEST(OStreamStream, WriteToLValue) { - std::string s = "abc"; - { - absl::strings_internal::OStringStream strm(&s); - EXPECT_EQ("abc", s); - strm << ""; - EXPECT_EQ("abc", s); - strm << 42; - EXPECT_EQ("abc42", s); - strm << 'x' << 'y'; - EXPECT_EQ("abc42xy", s); - } - EXPECT_EQ("abc42xy", s); -} - -TEST(OStreamStream, WriteToRValue) { - std::string s = "abc"; - absl::strings_internal::OStringStream(&s) << ""; - EXPECT_EQ("abc", s); - absl::strings_internal::OStringStream(&s) << 42; - EXPECT_EQ("abc42", s); - absl::strings_internal::OStringStream(&s) << 'x' << 'y'; - EXPECT_EQ("abc42xy", s); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/pow10_helper.cc b/third_party/abseil_cpp/absl/strings/internal/pow10_helper.cc deleted file mode 100644 index 42e96c3425d2..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/pow10_helper.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. - -#include "absl/strings/internal/pow10_helper.h" - -#include <cmath> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -namespace { - -// The exact value of 1e23 falls precisely halfway between two representable -// doubles. Furthermore, the rounding rules we prefer (break ties by rounding -// to the nearest even) dictate in this case that the number should be rounded -// down, but this is not completely specified for floating-point literals in -// C++. (It just says to use the default rounding mode of the standard -// library.) We ensure the result we want by using a number that has an -// unambiguous correctly rounded answer. -constexpr double k1e23 = 9999999999999999e7; - -constexpr double kPowersOfTen[] = { - 0.0, 1e-323, 1e-322, 1e-321, 1e-320, 1e-319, 1e-318, 1e-317, 1e-316, - 1e-315, 1e-314, 1e-313, 1e-312, 1e-311, 1e-310, 1e-309, 1e-308, 1e-307, - 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, 1e-298, - 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, 1e-289, - 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, 1e-280, - 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271, - 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, - 1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, - 1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, - 1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, - 1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, 1e-226, - 1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, 1e-217, - 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, 1e-208, - 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, 1e-199, - 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, 1e-190, - 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181, - 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, - 1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, - 1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, - 1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, - 1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, 1e-136, - 1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, 1e-127, - 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, 1e-118, - 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, 1e-109, - 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, 1e-100, - 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, - 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, - 1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, - 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, - 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, - 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, - 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38, 1e-37, - 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, - 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, - 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, - 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, - 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, - 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, - 1e+18, 1e+19, 1e+20, 1e+21, 1e+22, k1e23, 1e+24, 1e+25, 1e+26, - 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, - 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+41, 1e+42, 1e+43, 1e+44, - 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, - 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+61, 1e+62, - 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, - 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, - 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, - 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, - 1e+99, 1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, - 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, - 1e+117, 1e+118, 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, - 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, - 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143, - 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152, - 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161, - 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, - 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179, - 1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, - 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, - 1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, - 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, - 1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223, 1e+224, - 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, - 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+241, 1e+242, - 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, - 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260, - 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269, - 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, - 1e+279, 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, - 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, - 1e+297, 1e+298, 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, - 1e+306, 1e+307, 1e+308, -}; - -} // namespace - -double Pow10(int exp) { - if (exp < -324) { - return 0.0; - } else if (exp > 308) { - return INFINITY; - } else { - return kPowersOfTen[exp + 324]; - } -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/pow10_helper.h b/third_party/abseil_cpp/absl/strings/internal/pow10_helper.h deleted file mode 100644 index c37c2c3ffee5..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/pow10_helper.h +++ /dev/null @@ -1,40 +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. -// -// This test helper library contains a table of powers of 10, to guarantee -// precise values are computed across the full range of doubles. We can't rely -// on the pow() function, because not all standard libraries ship a version -// that is precise. -#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_ -#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_ - -#include <vector> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// Computes the precise value of 10^exp. (I.e. the nearest representable -// double to the exact value, rounding to nearest-even in the (single) case of -// being exactly halfway between.) -double Pow10(int exp); - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/pow10_helper_test.cc b/third_party/abseil_cpp/absl/strings/internal/pow10_helper_test.cc deleted file mode 100644 index a4ff76d31e10..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/pow10_helper_test.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. - -#include "absl/strings/internal/pow10_helper.h" - -#include <cmath> - -#include "gtest/gtest.h" -#include "absl/strings/str_format.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -namespace { - -struct TestCase { - int power; // Testing Pow10(power) - uint64_t significand; // Raw bits of the expected value - int radix; // significand is adjusted by 2^radix -}; - -TEST(Pow10HelperTest, Works) { - // The logic in pow10_helper.cc is so simple that theoretically we don't even - // need a test. However, we're paranoid and believe that there may be - // compilers that don't round floating-point literals correctly, even though - // it is specified by the standard. We check various edge cases, just to be - // sure. - constexpr TestCase kTestCases[] = { - // Subnormals - {-323, 0x2, -1074}, - {-322, 0x14, -1074}, - {-321, 0xca, -1074}, - {-320, 0x7e8, -1074}, - {-319, 0x4f10, -1074}, - {-318, 0x316a2, -1074}, - {-317, 0x1ee257, -1074}, - {-316, 0x134d761, -1074}, - {-315, 0xc1069cd, -1074}, - {-314, 0x78a42205, -1074}, - {-313, 0x4b6695433, -1074}, - {-312, 0x2f201d49fb, -1074}, - {-311, 0x1d74124e3d1, -1074}, - {-310, 0x12688b70e62b, -1074}, - {-309, 0xb8157268fdaf, -1074}, - {-308, 0x730d67819e8d2, -1074}, - // Values that are very close to rounding the other way. - // Comment shows difference of significand from the true value. - {-307, 0x11fa182c40c60d, -1072}, // -.4588 - {-290, 0x18f2b061aea072, -1016}, // .4854 - {-276, 0x11BA03F5B21000, -969}, // .4709 - {-259, 0x1899C2F6732210, -913}, // .4830 - {-252, 0x1D53844EE47DD1, -890}, // -.4743 - {-227, 0x1E5297287C2F45, -807}, // -.4708 - {-198, 0x1322E220A5B17E, -710}, // -.4714 - {-195, 0x12B010D3E1CF56, -700}, // .4928 - {-192, 0x123FF06EEA847A, -690}, // .4968 - {-163, 0x1708D0F84D3DE7, -594}, // -.4977 - {-145, 0x13FAAC3E3FA1F3, -534}, // -.4785 - {-111, 0x133D4032C2C7F5, -421}, // .4774 - {-106, 0x1D5B561574765B, -405}, // -.4869 - {-104, 0x16EF5B40C2FC77, -398}, // -.4741 - {-88, 0x197683DF2F268D, -345}, // -.4738 - {-86, 0x13E497065CD61F, -338}, // .4736 - {-76, 0x17288E1271F513, -305}, // -.4761 - {-63, 0x1A53FC9631D10D, -262}, // .4929 - {-30, 0x14484BFEEBC2A0, -152}, // .4758 - {-21, 0x12E3B40A0E9B4F, -122}, // -.4916 - {-5, 0x14F8B588E368F1, -69}, // .4829 - {23, 0x152D02C7E14AF6, 24}, // -.5000 (exactly, round-to-even) - {29, 0x1431E0FAE6D721, 44}, // -.4870 - {34, 0x1ED09BEAD87C03, 60}, // -.4721 - {70, 0x172EBAD6DDC73D, 180}, // .4733 - {105, 0x1BE7ABD3781ECA, 296}, // -.4850 - {126, 0x17A2ECC414A03F, 366}, // -.4999 - {130, 0x1CDA62055B2D9E, 379}, // .4855 - {165, 0x115D847AD00087, 496}, // -.4913 - {172, 0x14B378469B6732, 519}, // .4818 - {187, 0x1262DFEEBBB0F9, 569}, // -.4805 - {210, 0x18557F31326BBB, 645}, // -.4992 - {212, 0x1302CB5E6F642A, 652}, // -.4838 - {215, 0x1290BA9A38C7D1, 662}, // -.4881 - {236, 0x1F736F9B3494E9, 731}, // .4707 - {244, 0x176EC98994F489, 758}, // .4924 - {250, 0x1658E3AB795204, 778}, // -.4963 - {252, 0x117571DDF6C814, 785}, // .4873 - {254, 0x1B4781EAD1989E, 791}, // -.4887 - {260, 0x1A03FDE214CAF1, 811}, // .4784 - {284, 0x1585041B2C477F, 891}, // .4798 - {304, 0x1D2A1BE4048F90, 957}, // -.4987 - // Out-of-range values - {-324, 0x0, 0}, - {-325, 0x0, 0}, - {-326, 0x0, 0}, - {309, 1, 2000}, - {310, 1, 2000}, - {311, 1, 2000}, - }; - for (const TestCase& test_case : kTestCases) { - EXPECT_EQ(Pow10(test_case.power), - std::ldexp(test_case.significand, test_case.radix)) - << absl::StrFormat("Failure for Pow10(%d): %a vs %a", test_case.power, - Pow10(test_case.power), - std::ldexp(test_case.significand, test_case.radix)); - } -} - -} // namespace -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized.h b/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized.h deleted file mode 100644 index e42628e3949a..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized.h +++ /dev/null @@ -1,73 +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. -// - -#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ -#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ - -#include <string> -#include <type_traits> -#include <utility> - -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" // for void_t - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// Is a subclass of true_type or false_type, depending on whether or not -// T has a __resize_default_init member. -template <typename string_type, typename = void> -struct ResizeUninitializedTraits { - using HasMember = std::false_type; - static void Resize(string_type* s, size_t new_size) { s->resize(new_size); } -}; - -// __resize_default_init is provided by libc++ >= 8.0 -template <typename string_type> -struct ResizeUninitializedTraits< - string_type, absl::void_t<decltype(std::declval<string_type&>() - .__resize_default_init(237))> > { - using HasMember = std::true_type; - static void Resize(string_type* s, size_t new_size) { - s->__resize_default_init(new_size); - } -}; - -// Returns true if the std::string implementation supports a resize where -// the new characters added to the std::string are left untouched. -// -// (A better name might be "STLStringSupportsUninitializedResize", alluding to -// the previous function.) -template <typename string_type> -inline constexpr bool STLStringSupportsNontrashingResize(string_type*) { - return ResizeUninitializedTraits<string_type>::HasMember::value; -} - -// Like str->resize(new_size), except any new characters added to "*str" as a -// result of resizing may be left uninitialized, rather than being filled with -// '0' bytes. Typically used when code is then going to overwrite the backing -// store of the std::string with known data. -template <typename string_type, typename = void> -inline void STLStringResizeUninitialized(string_type* s, size_t new_size) { - ResizeUninitializedTraits<string_type>::Resize(s, new_size); -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized_test.cc b/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized_test.cc deleted file mode 100644 index 0f8b3c2a95b8..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/resize_uninitialized_test.cc +++ /dev/null @@ -1,82 +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/strings/internal/resize_uninitialized.h" - -#include "gtest/gtest.h" - -namespace { - -int resize_call_count = 0; - -// A mock string class whose only purpose is to track how many times its -// resize() method has been called. -struct resizable_string { - size_t size() const { return 0; } - char& operator[](size_t) { - static char c = '\0'; - return c; - } - void resize(size_t) { resize_call_count += 1; } -}; - -int resize_default_init_call_count = 0; - -// A mock string class whose only purpose is to track how many times its -// resize() and __resize_default_init() methods have been called. -struct resize_default_init_string { - size_t size() const { return 0; } - char& operator[](size_t) { - static char c = '\0'; - return c; - } - void resize(size_t) { resize_call_count += 1; } - void __resize_default_init(size_t) { resize_default_init_call_count += 1; } -}; - -TEST(ResizeUninit, WithAndWithout) { - resize_call_count = 0; - resize_default_init_call_count = 0; - { - resizable_string rs; - - EXPECT_EQ(resize_call_count, 0); - EXPECT_EQ(resize_default_init_call_count, 0); - EXPECT_FALSE( - absl::strings_internal::STLStringSupportsNontrashingResize(&rs)); - EXPECT_EQ(resize_call_count, 0); - EXPECT_EQ(resize_default_init_call_count, 0); - absl::strings_internal::STLStringResizeUninitialized(&rs, 237); - EXPECT_EQ(resize_call_count, 1); - EXPECT_EQ(resize_default_init_call_count, 0); - } - - resize_call_count = 0; - resize_default_init_call_count = 0; - { - resize_default_init_string rus; - - EXPECT_EQ(resize_call_count, 0); - EXPECT_EQ(resize_default_init_call_count, 0); - EXPECT_TRUE( - absl::strings_internal::STLStringSupportsNontrashingResize(&rus)); - EXPECT_EQ(resize_call_count, 0); - EXPECT_EQ(resize_default_init_call_count, 0); - absl::strings_internal::STLStringResizeUninitialized(&rus, 237); - EXPECT_EQ(resize_call_count, 0); - EXPECT_EQ(resize_default_init_call_count, 1); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/internal/stl_type_traits.h b/third_party/abseil_cpp/absl/strings/internal/stl_type_traits.h deleted file mode 100644 index 6035ca45cbd2..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/stl_type_traits.h +++ /dev/null @@ -1,248 +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. -// - -// Thie file provides the IsStrictlyBaseOfAndConvertibleToSTLContainer type -// trait metafunction to assist in working with the _GLIBCXX_DEBUG debug -// wrappers of STL containers. -// -// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including -// absl/strings/str_split.h. -// -// IWYU pragma: private, include "absl/strings/str_split.h" - -#ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ -#define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ - -#include <array> -#include <bitset> -#include <deque> -#include <forward_list> -#include <list> -#include <map> -#include <set> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -template <typename C, template <typename...> class T> -struct IsSpecializationImpl : std::false_type {}; -template <template <typename...> class T, typename... Args> -struct IsSpecializationImpl<T<Args...>, T> : std::true_type {}; -template <typename C, template <typename...> class T> -using IsSpecialization = IsSpecializationImpl<absl::decay_t<C>, T>; - -template <typename C> -struct IsArrayImpl : std::false_type {}; -template <template <typename, size_t> class A, typename T, size_t N> -struct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {}; -template <typename C> -using IsArray = IsArrayImpl<absl::decay_t<C>>; - -template <typename C> -struct IsBitsetImpl : std::false_type {}; -template <template <size_t> class B, size_t N> -struct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {}; -template <typename C> -using IsBitset = IsBitsetImpl<absl::decay_t<C>>; - -template <typename C> -struct IsSTLContainer - : absl::disjunction< - IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>, - IsSpecialization<C, std::forward_list>, - IsSpecialization<C, std::list>, IsSpecialization<C, std::map>, - IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>, - IsSpecialization<C, std::multiset>, - IsSpecialization<C, std::unordered_map>, - IsSpecialization<C, std::unordered_multimap>, - IsSpecialization<C, std::unordered_set>, - IsSpecialization<C, std::unordered_multiset>, - IsSpecialization<C, std::vector>> {}; - -template <typename C, template <typename...> class T, typename = void> -struct IsBaseOfSpecializationImpl : std::false_type {}; -// IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE -// on the existence of container dependent types and plug them into the STL -// template. -template <typename C, template <typename, typename> class T> -struct IsBaseOfSpecializationImpl< - C, T, absl::void_t<typename C::value_type, typename C::allocator_type>> - : std::is_base_of<C, - T<typename C::value_type, typename C::allocator_type>> {}; -template <typename C, template <typename, typename, typename> class T> -struct IsBaseOfSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::key_compare, - typename C::allocator_type>> - : std::is_base_of<C, T<typename C::key_type, typename C::key_compare, - typename C::allocator_type>> {}; -template <typename C, template <typename, typename, typename, typename> class T> -struct IsBaseOfSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::mapped_type, - typename C::key_compare, typename C::allocator_type>> - : std::is_base_of<C, - T<typename C::key_type, typename C::mapped_type, - typename C::key_compare, typename C::allocator_type>> { -}; -template <typename C, template <typename, typename, typename, typename> class T> -struct IsBaseOfSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::hasher, - typename C::key_equal, typename C::allocator_type>> - : std::is_base_of<C, T<typename C::key_type, typename C::hasher, - typename C::key_equal, typename C::allocator_type>> { -}; -template <typename C, - template <typename, typename, typename, typename, typename> class T> -struct IsBaseOfSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::mapped_type, - typename C::hasher, typename C::key_equal, - typename C::allocator_type>> - : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type, - typename C::hasher, typename C::key_equal, - typename C::allocator_type>> {}; -template <typename C, template <typename...> class T> -using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<absl::decay_t<C>, T>; - -template <typename C> -struct IsBaseOfArrayImpl : std::false_type {}; -template <template <typename, size_t> class A, typename T, size_t N> -struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> { -}; -template <typename C> -using IsBaseOfArray = IsBaseOfArrayImpl<absl::decay_t<C>>; - -template <typename C> -struct IsBaseOfBitsetImpl : std::false_type {}; -template <template <size_t> class B, size_t N> -struct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {}; -template <typename C> -using IsBaseOfBitset = IsBaseOfBitsetImpl<absl::decay_t<C>>; - -template <typename C> -struct IsBaseOfSTLContainer - : absl::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>, - IsBaseOfSpecialization<C, std::deque>, - IsBaseOfSpecialization<C, std::forward_list>, - IsBaseOfSpecialization<C, std::list>, - IsBaseOfSpecialization<C, std::map>, - IsBaseOfSpecialization<C, std::multimap>, - IsBaseOfSpecialization<C, std::set>, - IsBaseOfSpecialization<C, std::multiset>, - IsBaseOfSpecialization<C, std::unordered_map>, - IsBaseOfSpecialization<C, std::unordered_multimap>, - IsBaseOfSpecialization<C, std::unordered_set>, - IsBaseOfSpecialization<C, std::unordered_multiset>, - IsBaseOfSpecialization<C, std::vector>> {}; - -template <typename C, template <typename...> class T, typename = void> -struct IsConvertibleToSpecializationImpl : std::false_type {}; -// IsConvertibleToSpecializationImpl needs multiple partial specializations to -// SFINAE on the existence of container dependent types and plug them into the -// STL template. -template <typename C, template <typename, typename> class T> -struct IsConvertibleToSpecializationImpl< - C, T, absl::void_t<typename C::value_type, typename C::allocator_type>> - : std::is_convertible< - C, T<typename C::value_type, typename C::allocator_type>> {}; -template <typename C, template <typename, typename, typename> class T> -struct IsConvertibleToSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::key_compare, - typename C::allocator_type>> - : std::is_convertible<C, T<typename C::key_type, typename C::key_compare, - typename C::allocator_type>> {}; -template <typename C, template <typename, typename, typename, typename> class T> -struct IsConvertibleToSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::mapped_type, - typename C::key_compare, typename C::allocator_type>> - : std::is_convertible< - C, T<typename C::key_type, typename C::mapped_type, - typename C::key_compare, typename C::allocator_type>> {}; -template <typename C, template <typename, typename, typename, typename> class T> -struct IsConvertibleToSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::hasher, - typename C::key_equal, typename C::allocator_type>> - : std::is_convertible< - C, T<typename C::key_type, typename C::hasher, typename C::key_equal, - typename C::allocator_type>> {}; -template <typename C, - template <typename, typename, typename, typename, typename> class T> -struct IsConvertibleToSpecializationImpl< - C, T, - absl::void_t<typename C::key_type, typename C::mapped_type, - typename C::hasher, typename C::key_equal, - typename C::allocator_type>> - : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type, - typename C::hasher, typename C::key_equal, - typename C::allocator_type>> {}; -template <typename C, template <typename...> class T> -using IsConvertibleToSpecialization = - IsConvertibleToSpecializationImpl<absl::decay_t<C>, T>; - -template <typename C> -struct IsConvertibleToArrayImpl : std::false_type {}; -template <template <typename, size_t> class A, typename T, size_t N> -struct IsConvertibleToArrayImpl<A<T, N>> - : std::is_convertible<A<T, N>, std::array<T, N>> {}; -template <typename C> -using IsConvertibleToArray = IsConvertibleToArrayImpl<absl::decay_t<C>>; - -template <typename C> -struct IsConvertibleToBitsetImpl : std::false_type {}; -template <template <size_t> class B, size_t N> -struct IsConvertibleToBitsetImpl<B<N>> - : std::is_convertible<B<N>, std::bitset<N>> {}; -template <typename C> -using IsConvertibleToBitset = IsConvertibleToBitsetImpl<absl::decay_t<C>>; - -template <typename C> -struct IsConvertibleToSTLContainer - : absl::disjunction< - IsConvertibleToArray<C>, IsConvertibleToBitset<C>, - IsConvertibleToSpecialization<C, std::deque>, - IsConvertibleToSpecialization<C, std::forward_list>, - IsConvertibleToSpecialization<C, std::list>, - IsConvertibleToSpecialization<C, std::map>, - IsConvertibleToSpecialization<C, std::multimap>, - IsConvertibleToSpecialization<C, std::set>, - IsConvertibleToSpecialization<C, std::multiset>, - IsConvertibleToSpecialization<C, std::unordered_map>, - IsConvertibleToSpecialization<C, std::unordered_multimap>, - IsConvertibleToSpecialization<C, std::unordered_set>, - IsConvertibleToSpecialization<C, std::unordered_multiset>, - IsConvertibleToSpecialization<C, std::vector>> {}; - -template <typename C> -struct IsStrictlyBaseOfAndConvertibleToSTLContainer - : absl::conjunction<absl::negation<IsSTLContainer<C>>, - IsBaseOfSTLContainer<C>, - IsConvertibleToSTLContainer<C>> {}; - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ 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 deleted file mode 100644 index e28a29b17169..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.cc +++ /dev/null @@ -1,488 +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. - -// -// POSIX spec: -// http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html -// -#include "absl/strings/internal/str_format/arg.h" - -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <string> -#include <type_traits> - -#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 { - -// Reduce *capacity by s.size(), clipped to a 0 minimum. -void ReducePadding(string_view s, size_t *capacity) { - *capacity = Excess(s.size(), *capacity); -} - -// Reduce *capacity by n, clipped to a 0 minimum. -void ReducePadding(size_t n, size_t *capacity) { - *capacity = Excess(n, *capacity); -} - -template <typename T> -struct MakeUnsigned : std::make_unsigned<T> {}; -template <> -struct MakeUnsigned<absl::int128> { - using type = absl::uint128; -}; -template <> -struct MakeUnsigned<absl::uint128> { - using type = absl::uint128; -}; - -template <typename T> -struct IsSigned : std::is_signed<T> {}; -template <> -struct IsSigned<absl::int128> : std::true_type {}; -template <> -struct IsSigned<absl::uint128> : std::false_type {}; - -// Integral digit printer. -// Call one of the PrintAs* routines after construction once. -// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results. -class IntDigits { - public: - // Print the unsigned integer as octal. - // Supports unsigned integral types and uint128. - template <typename T> - 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; - } - PrintAsDec(u, add_neg); - } - - 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; - } - - // Print the unsigned integer as hex using lowercase. - // Supports unsigned integral types and uint128. - 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; - } - 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; - } - - // 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}; - } - - bool is_negative() const { return start_[0] == '-'; } - - private: - const char *start_; - size_t size_; - // Max size: 128 bit value as octal -> 43 digits, plus sign char - char storage_[128 / 3 + 1 + 1]; -}; - -// Note: 'o' conversions do not have a base indicator, it's just that -// the '#' flag is specified to modify the precision for 'o' conversions. -string_view BaseIndicator(const IntDigits &as_digits, - const FormatConversionSpecImpl conv) { - // always show 0x for %p. - bool alt = conv.has_alt_flag() || - conv.conversion_char() == FormatConversionCharInternal::p; - bool hex = (conv.conversion_char() == FormatConversionCharInternal::x || - conv.conversion_char() == FormatConversionCharInternal::X || - conv.conversion_char() == FormatConversionCharInternal::p); - // From the POSIX description of '#' flag: - // "For x or X conversion specifiers, a non-zero result shall have - // 0x (or 0X) prefixed to it." - if (alt && hex && !as_digits.without_neg_or_zero().empty()) { - return conv.conversion_char() == FormatConversionCharInternal::X ? "0X" - : "0x"; - } - return {}; -} - -string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) { - if (conv.conversion_char() == FormatConversionCharInternal::d || - conv.conversion_char() == FormatConversionCharInternal::i) { - if (neg) return "-"; - if (conv.has_show_pos_flag()) return "+"; - if (conv.has_sign_col_flag()) return " "; - } - return {}; -} - -bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - size_t fill = 0; - if (conv.width() >= 0) fill = conv.width(); - ReducePadding(1, &fill); - if (!conv.has_left_flag()) sink->Append(fill, ' '); - sink->Append(1, v); - if (conv.has_left_flag()) sink->Append(fill, ' '); - return true; -} - -bool ConvertIntImplInnerSlow(const IntDigits &as_digits, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - // Print as a sequence of Substrings: - // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces] - size_t fill = 0; - if (conv.width() >= 0) fill = conv.width(); - - string_view formatted = as_digits.without_neg_or_zero(); - ReducePadding(formatted, &fill); - - string_view sign = SignColumn(as_digits.is_negative(), conv); - ReducePadding(sign, &fill); - - string_view base_indicator = BaseIndicator(as_digits, conv); - ReducePadding(base_indicator, &fill); - - int precision = conv.precision(); - bool precision_specified = precision >= 0; - if (!precision_specified) - precision = 1; - - if (conv.has_alt_flag() && - conv.conversion_char() == FormatConversionCharInternal::o) { - // From POSIX description of the '#' (alt) flag: - // "For o conversion, it increases the precision (if necessary) to - // force the first digit of the result to be zero." - if (formatted.empty() || *formatted.begin() != '0') { - int needed = static_cast<int>(formatted.size()) + 1; - precision = std::max(precision, needed); - } - } - - 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; - - // 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()) { - num_zeroes += num_left_spaces; - num_left_spaces = 0; - } - - sink->Append(num_left_spaces, ' '); - sink->Append(sign); - sink->Append(base_indicator); - sink->Append(num_zeroes, '0'); - sink->Append(formatted); - sink->Append(num_right_spaces, ' '); - return true; -} - -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); - } - - if (conv.is_basic()) { - sink->Append(as_digits.with_neg_and_zero()); - return true; - } - return ConvertIntImplInnerSlow(as_digits, conv, sink); -} - -template <typename T> -bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return FormatConversionCharIsFloat(conv.conversion_char()) && - ConvertFloatImpl(v, conv, sink); -} - -inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - if (conv.is_basic()) { - sink->Append(v); - return true; - } - return sink->PutPaddedString(v, conv.width(), conv.precision(), - conv.has_left_flag()); -} - -} // namespace - -// ==================== Strings ==================== -StringConvertResult FormatConvertImpl(const std::string &v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertStringArg(v, conv, sink)}; -} - -StringConvertResult FormatConvertImpl(string_view v, - const FormatConversionSpecImpl 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) - return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; - size_t len; - if (v == nullptr) { - len = 0; - } else if (conv.precision() < 0) { - len = std::strlen(v); - } else { - // If precision is set, we look for the NUL-terminator on the valid range. - len = std::find(v, v + conv.precision(), '\0') - v; - } - return {ConvertStringArg(string_view(v, len), conv, sink)}; -} - -// ==================== Raw pointers ==================== -ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl( - VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { - if (!v.value) { - sink->Append("(nil)"); - return {true}; - } - IntDigits as_digits; - as_digits.PrintAsHexLower(v.value); - return {ConvertIntImplInnerSlow(as_digits, conv, sink)}; -} - -// ==================== Floats ==================== -FloatingConvertResult FormatConvertImpl(float v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertFloatArg(v, conv, sink)}; -} -FloatingConvertResult FormatConvertImpl(double v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertFloatArg(v, conv, sink)}; -} -FloatingConvertResult FormatConvertImpl(long double v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertFloatArg(v, conv, sink)}; -} - -// ==================== Chars ==================== -IntegralConvertResult FormatConvertImpl(char v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(signed char v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(unsigned char v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} - -// ==================== Ints ==================== -IntegralConvertResult FormatConvertImpl(short v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(int v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(unsigned v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(long v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(absl::int128 v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} -IntegralConvertResult FormatConvertImpl(absl::uint128 v, - const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { - return {ConvertIntArg(v, conv, sink)}; -} - -ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(); - - - -} // namespace str_format_internal - -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 7040c866778e..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.h +++ /dev/null @@ -1,518 +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_STR_FORMAT_ARG_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_ - -#include <string.h> -#include <wchar.h> - -#include <cstdio> -#include <iomanip> -#include <limits> -#include <memory> -#include <sstream> -#include <string> -#include <type_traits> - -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" -#include "absl/numeric/int128.h" -#include "absl/strings/internal/str_format/extension.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class Cord; -class FormatCountCapture; -class FormatSink; - -template <absl::FormatConversionCharSet C> -struct FormatConvertResult; -class FormatConversionSpec; - -namespace str_format_internal { - -template <typename T, typename = void> -struct HasUserDefinedConvert : std::false_type {}; - -template <typename T> -struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert( - std::declval<const T&>(), - std::declval<const FormatConversionSpec&>(), - std::declval<FormatSink*>()))>> - : std::true_type {}; - -void AbslFormatConvert(); // Stops the lexical name lookup -template <typename T> -auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink) - -> decltype(AbslFormatConvert(v, - std::declval<const FormatConversionSpec&>(), - std::declval<FormatSink*>())) { - using FormatConversionSpecT = - absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>; - using FormatSinkT = - absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>; - auto fcs = conv.Wrap<FormatConversionSpecT>(); - auto fs = sink->Wrap<FormatSinkT>(); - return AbslFormatConvert(v, fcs, &fs); -} - -template <typename T> -class StreamedWrapper; - -// If 'v' can be converted (in the printf sense) according to 'conv', -// then convert it, appending to `sink` and return `true`. -// Otherwise fail and return `false`. - -// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v' -// as an extension mechanism. These FormatConvertImpl functions are the default -// implementations. -// The ADL search is augmented via the 'Sink*' parameter, which also -// serves as a disambiguator to reject possible unintended 'AbslFormatConvert' -// functions in the namespaces associated with 'v'. - -// Raw pointers. -struct VoidPtr { - VoidPtr() = default; - template <typename T, - decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0> - VoidPtr(T* ptr) // NOLINT - : 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); - -// Strings. -StringConvertResult FormatConvertImpl(const std::string& v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -StringConvertResult FormatConvertImpl(string_view v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -ArgConvertResult<FormatConversionCharSetUnion( - FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)> -FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv, - FormatSinkImpl* sink); - -template <class AbslCord, typename std::enable_if<std::is_same< - AbslCord, absl::Cord>::value>::type* = nullptr> -StringConvertResult FormatConvertImpl(const AbslCord& value, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink) { - bool is_left = conv.has_left_flag(); - size_t space_remaining = 0; - - int width = conv.width(); - if (width >= 0) space_remaining = width; - - size_t to_write = value.size(); - - int precision = conv.precision(); - if (precision >= 0) - to_write = (std::min)(to_write, static_cast<size_t>(precision)); - - space_remaining = Excess(to_write, space_remaining); - - if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' '); - - for (string_view piece : value.Chunks()) { - if (piece.size() > to_write) { - piece.remove_suffix(piece.size() - to_write); - to_write = 0; - } else { - to_write -= piece.size(); - } - sink->Append(piece); - if (to_write == 0) { - break; - } - } - - if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' '); - return {true}; -} - -using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion( - FormatConversionCharSetInternal::c, - FormatConversionCharSetInternal::kNumeric, - FormatConversionCharSetInternal::kStar)>; -using FloatingConvertResult = - ArgConvertResult<FormatConversionCharSetInternal::kFloating>; - -// Floats. -FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(long double v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); - -// Chars. -IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(signed char v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned char v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); - -// Ints. -IntegralConvertResult FormatConvertImpl(short v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(long v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(uint128 v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0> -IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink) { - return FormatConvertImpl(static_cast<int>(v), conv, sink); -} - -// We provide this function to help the checker, but it is never defined. -// FormatArgImpl will use the underlying Convert functions instead. -template <typename T> -typename std::enable_if<std::is_enum<T>::value && - !HasUserDefinedConvert<T>::value, - IntegralConvertResult>::type -FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); - -template <typename T> -StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v, - FormatConversionSpecImpl conv, - FormatSinkImpl* out) { - std::ostringstream oss; - oss << v.v_; - if (!oss) return {false}; - return str_format_internal::FormatConvertImpl(oss.str(), conv, out); -} - -// Use templates and dependent types to delay evaluation of the function -// until after FormatCountCapture is fully defined. -struct FormatCountCaptureHelper { - template <class T = int> - static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper( - const FormatCountCapture& v, FormatConversionSpecImpl conv, - FormatSinkImpl* sink) { - const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v; - - if (conv.conversion_char() != - str_format_internal::FormatConversionCharInternal::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) { - return FormatCountCaptureHelper::ConvertHelper(v, conv, sink); -} - -// Helper friend struct to hide implementation details from the public API of -// FormatArgImpl. -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. - return arg.dispatcher_(arg.data_, {}, out); - } - - template <typename Arg> - static bool Convert(Arg arg, FormatConversionSpecImpl conv, - FormatSinkImpl* out) { - return arg.dispatcher_(arg.data_, conv, out); - } - - template <typename Arg> - static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) { - return arg.dispatcher_; - } -}; - -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: - enum { kInlinedSpace = 8 }; - - using VoidPtr = str_format_internal::VoidPtr; - - union Data { - const void* ptr; - const volatile void* volatile_ptr; - char buf[kInlinedSpace]; - }; - - using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out); - - template <typename T> - struct store_by_value - : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) && - (std::is_integral<T>::value || - std::is_floating_point<T>::value || - std::is_pointer<T>::value || - std::is_same<VoidPtr, T>::value)> {}; - - enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue }; - template <typename T> - struct storage_policy - : std::integral_constant<StoragePolicy, - (std::is_volatile<T>::value - ? ByVolatilePointer - : (store_by_value<T>::value ? ByValue - : ByPointer))> { - }; - - // To reduce the number of vtables we will decay values before hand. - // Anything with a user-defined Convert will get its own vtable. - // For everything else: - // - Decay char* and char arrays into `const char*` - // - Decay any other pointer to `const void*` - // - Decay all enums to their underlying type. - // - Decay function pointers to void*. - template <typename T, typename = void> - struct DecayType { - static constexpr bool kHasUserDefined = - str_format_internal::HasUserDefinedConvert<T>::value; - using type = typename std::conditional< - !kHasUserDefined && std::is_convertible<T, const char*>::value, - const char*, - typename std::conditional<!kHasUserDefined && - std::is_convertible<T, VoidPtr>::value, - VoidPtr, const T&>::type>::type; - }; - template <typename T> - struct DecayType<T, - typename std::enable_if< - !str_format_internal::HasUserDefinedConvert<T>::value && - std::is_enum<T>::value>::type> { - using type = typename std::underlying_type<T>::type; - }; - - public: - template <typename T> - explicit FormatArgImpl(const T& value) { - using D = typename DecayType<T>::type; - static_assert( - std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue, - "Decayed types must be stored by value"); - Init(static_cast<D>(value)); - } - - private: - friend struct str_format_internal::FormatArgImplFriend; - template <typename T, StoragePolicy = storage_policy<T>::value> - struct Manager; - - template <typename T> - struct Manager<T, ByPointer> { - static Data SetValue(const T& value) { - Data data; - data.ptr = std::addressof(value); - return data; - } - - static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); } - }; - - template <typename T> - struct Manager<T, ByVolatilePointer> { - static Data SetValue(const T& value) { - Data data; - data.volatile_ptr = &value; - return data; - } - - static const T& Value(Data arg) { - return *static_cast<const T*>(arg.volatile_ptr); - } - }; - - template <typename T> - struct Manager<T, ByValue> { - static Data SetValue(const T& value) { - Data data; - memcpy(data.buf, &value, sizeof(value)); - return data; - } - - static T Value(Data arg) { - T value; - memcpy(&value, arg.buf, sizeof(T)); - return value; - } - }; - - template <typename T> - void Init(const T& value) { - data_ = Manager<T>::SetValue(value); - dispatcher_ = &Dispatch<T>; - } - - template <typename T> - static int ToIntVal(const T& val) { - using CommonType = typename std::conditional<std::is_signed<T>::value, - int64_t, uint64_t>::type; - if (static_cast<CommonType>(val) > - static_cast<CommonType>((std::numeric_limits<int>::max)())) { - return (std::numeric_limits<int>::max)(); - } else if (std::is_signed<T>::value && - static_cast<CommonType>(val) < - static_cast<CommonType>((std::numeric_limits<int>::min)())) { - return (std::numeric_limits<int>::min)(); - } - return static_cast<int>(val); - } - - template <typename T> - static bool ToInt(Data arg, int* out, std::true_type /* is_integral */, - std::false_type) { - *out = ToIntVal(Manager<T>::Value(arg)); - return true; - } - - template <typename T> - static bool ToInt(Data arg, int* out, std::false_type, - std::true_type /* is_enum */) { - *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>( - Manager<T>::Value(arg))); - return true; - } - - template <typename T> - static bool ToInt(Data, int*, std::false_type, std::false_type) { - return false; - } - - template <typename T> - static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) { - // A `none` conv indicates that we want the `int` conversion. - if (ABSL_PREDICT_FALSE(spec.conversion_char() == - FormatConversionCharInternal::kNone)) { - return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(), - std::is_enum<T>()); - } - if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(), - spec.conversion_char()))) { - return false; - } - return str_format_internal::FormatConvertImpl( - Manager<T>::Value(arg), spec, - static_cast<FormatSinkImpl*>(out)) - .value; - } - - Data data_; - Dispatcher dispatcher_; -}; - -#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \ - E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \ - void*) - -#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \ - __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \ - __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \ - __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \ - __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \ - __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__) - -ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); - - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_ diff --git a/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 deleted file mode 100644 index 1261937c3097..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg_test.cc +++ /dev/null @@ -1,130 +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/strings/internal/str_format/arg.h" - -#include <ostream> -#include <string> -#include "gtest/gtest.h" -#include "absl/strings/str_format.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { -namespace { - -class FormatArgImplTest : public ::testing::Test { - public: - 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)); - EXPECT_EQ(1, out); - EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(-1), &out)); - EXPECT_EQ(-1, out); - EXPECT_TRUE( - FormatArgImplFriend::ToInt(FormatArgImpl(static_cast<char>(64)), &out)); - EXPECT_EQ(64, out); - EXPECT_TRUE(FormatArgImplFriend::ToInt( - FormatArgImpl(static_cast<unsigned long long>(123456)), &out)); // NOLINT - EXPECT_EQ(123456, out); - EXPECT_TRUE(FormatArgImplFriend::ToInt( - FormatArgImpl(static_cast<unsigned long long>( // NOLINT - std::numeric_limits<int>::max()) + - 1), - &out)); - EXPECT_EQ(std::numeric_limits<int>::max(), out); - EXPECT_TRUE(FormatArgImplFriend::ToInt( - FormatArgImpl(static_cast<long long>( // NOLINT - std::numeric_limits<int>::min()) - - 10), - &out)); - EXPECT_EQ(std::numeric_limits<int>::min(), out); - EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(false), &out)); - EXPECT_EQ(0, out); - EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(true), &out)); - EXPECT_EQ(1, out); - EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(2.2), &out)); - EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(3.2f), &out)); - EXPECT_FALSE(FormatArgImplFriend::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); -} - -extern const char kMyArray[]; - -TEST_F(FormatArgImplTest, CharArraysDecayToCharPtr) { - const char* a = ""; - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)), - FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(""))); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)), - FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl("A"))); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)), - FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl("ABC"))); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)), - FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(kMyArray))); -} - -TEST_F(FormatArgImplTest, OtherPtrDecayToVoidPtr) { - auto expected = FormatArgImplFriend::GetVTablePtrForTest( - FormatArgImpl(static_cast<void *>(nullptr))); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest( - FormatArgImpl(static_cast<int *>(nullptr))), - expected); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest( - FormatArgImpl(static_cast<volatile int *>(nullptr))), - expected); - - auto p = static_cast<void (*)()>([] {}); - EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(p)), - expected); -} - -TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) { - std::string s; - FormatSinkImpl sink(&s); - FormatConversionSpecImpl conv; - FormatConversionSpecImplFriend::SetConversionChar( - FormatConversionCharInternal::s, &conv); - FormatConversionSpecImplFriend::SetFlags(Flags(), &conv); - FormatConversionSpecImplFriend::SetWidth(-1, &conv); - FormatConversionSpecImplFriend::SetPrecision(-1, &conv); - EXPECT_TRUE( - FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink)); - sink.Flush(); - EXPECT_EQ("ABCDE", s); -} -const char kMyArray[] = "ABCDE"; - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 4e68b90b5ce8..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.cc +++ /dev/null @@ -1,259 +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/str_format/bind.h" - -#include <cerrno> -#include <limits> -#include <sstream> -#include <string> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -namespace { - -inline bool BindFromPosition(int position, int* value, - absl::Span<const FormatArgImpl> pack) { - assert(position > 0); - if (static_cast<size_t>(position) > pack.size()) { - return false; - } - // -1 because positions are 1-based - return FormatArgImplFriend::ToInt(pack[position - 1], value); -} - -class ArgContext { - public: - explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {} - - // Fill 'bound' with the results of applying the context's argument pack - // to the specified 'unbound'. We synthesize a BoundConversion by - // lining up a UnboundConversion with a user argument. We also - // resolve any '*' specifiers for width and precision, so after - // this call, 'bound' has all the information it needs to be formatted. - // Returns false on failure. - bool Bind(const UnboundConversion* unbound, BoundConversion* bound); - - private: - absl::Span<const FormatArgImpl> pack_; -}; - -inline bool ArgContext::Bind(const UnboundConversion* unbound, - BoundConversion* bound) { - const FormatArgImpl* arg = nullptr; - int arg_position = unbound->arg_position; - if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false; - arg = &pack_[arg_position - 1]; // 1-based - - if (!unbound->flags.basic) { - int width = unbound->width.value(); - bool force_left = false; - if (unbound->width.is_from_arg()) { - if (!BindFromPosition(unbound->width.get_from_arg(), &width, pack_)) - return false; - if (width < 0) { - // "A negative field width is taken as a '-' flag followed by a - // positive field width." - force_left = true; - // Make sure we don't overflow the width when negating it. - width = -std::max(width, -std::numeric_limits<int>::max()); - } - } - - int precision = unbound->precision.value(); - if (unbound->precision.is_from_arg()) { - if (!BindFromPosition(unbound->precision.get_from_arg(), &precision, - pack_)) - return false; - } - - FormatConversionSpecImplFriend::SetWidth(width, bound); - FormatConversionSpecImplFriend::SetPrecision(precision, bound); - - if (force_left) { - Flags flags = unbound->flags; - flags.left = true; - FormatConversionSpecImplFriend::SetFlags(flags, bound); - } else { - FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound); - } - } else { - FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound); - FormatConversionSpecImplFriend::SetWidth(-1, bound); - FormatConversionSpecImplFriend::SetPrecision(-1, bound); - } - FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound); - bound->set_arg(arg); - return true; -} - -template <typename Converter> -class ConverterConsumer { - public: - ConverterConsumer(Converter converter, absl::Span<const FormatArgImpl> pack) - : converter_(converter), arg_context_(pack) {} - - bool Append(string_view s) { - converter_.Append(s); - return true; - } - bool ConvertOne(const UnboundConversion& conv, string_view conv_string) { - BoundConversion bound; - if (!arg_context_.Bind(&conv, &bound)) return false; - return converter_.ConvertOne(bound, conv_string); - } - - private: - Converter converter_; - ArgContext arg_context_; -}; - -template <typename Converter> -bool ConvertAll(const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args, Converter converter) { - if (format.has_parsed_conversion()) { - return format.parsed_conversion()->ProcessFormat( - ConverterConsumer<Converter>(converter, args)); - } else { - return ParseFormatString(format.str(), - ConverterConsumer<Converter>(converter, args)); - } -} - -class DefaultConverter { - public: - explicit DefaultConverter(FormatSinkImpl* sink) : sink_(sink) {} - - void Append(string_view s) const { sink_->Append(s); } - - bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const { - return FormatArgImplFriend::Convert(*bound.arg(), bound, sink_); - } - - private: - FormatSinkImpl* sink_; -}; - -class SummarizingConverter { - public: - explicit SummarizingConverter(FormatSinkImpl* sink) : sink_(sink) {} - - void Append(string_view s) const { sink_->Append(s); } - - bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const { - UntypedFormatSpecImpl spec("%d"); - - std::ostringstream ss; - ss << "{" << Streamable(spec, {*bound.arg()}) << ":" - << FormatConversionSpecImplFriend::FlagsToString(bound); - if (bound.width() >= 0) ss << bound.width(); - if (bound.precision() >= 0) ss << "." << bound.precision(); - ss << bound.conversion_char() << "}"; - Append(ss.str()); - return true; - } - - private: - FormatSinkImpl* sink_; -}; - -} // namespace - -bool BindWithPack(const UnboundConversion* props, - absl::Span<const FormatArgImpl> pack, - BoundConversion* bound) { - return ArgContext(pack).Bind(props, bound); -} - -std::string Summarize(const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - typedef SummarizingConverter Converter; - std::string out; - { - // inner block to destroy sink before returning out. It ensures a last - // flush. - FormatSinkImpl sink(&out); - if (!ConvertAll(format, args, Converter(&sink))) { - return ""; - } - } - return out; -} - -bool FormatUntyped(FormatRawSinkImpl raw_sink, - const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - FormatSinkImpl sink(raw_sink); - using Converter = DefaultConverter; - return ConvertAll(format, args, Converter(&sink)); -} - -std::ostream& Streamable::Print(std::ostream& os) const { - if (!FormatUntyped(&os, format_, args_)) os.setstate(std::ios::failbit); - return os; -} - -std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - size_t orig = out->size(); - if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) { - out->erase(orig); - } - return *out; -} - -std::string FormatPack(const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - std::string out; - if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) { - out.clear(); - } - return out; -} - -int FprintF(std::FILE* output, const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - FILERawSink sink(output); - if (!FormatUntyped(&sink, format, args)) { - errno = EINVAL; - return -1; - } - if (sink.error()) { - errno = sink.error(); - return -1; - } - if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) { - errno = EFBIG; - return -1; - } - return static_cast<int>(sink.count()); -} - -int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args) { - BufferRawSink sink(output, size ? size - 1 : 0); - if (!FormatUntyped(&sink, format, args)) { - errno = EINVAL; - return -1; - } - size_t total = sink.total_written(); - if (size) output[std::min(total, size - 1)] = 0; - return static_cast<int>(total); -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 267cc0ef6928..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.h +++ /dev/null @@ -1,217 +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_STR_FORMAT_BIND_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ - -#include <array> -#include <cstdio> -#include <sstream> -#include <string> - -#include "absl/base/port.h" -#include "absl/strings/internal/str_format/arg.h" -#include "absl/strings/internal/str_format/checker.h" -#include "absl/strings/internal/str_format/parser.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class UntypedFormatSpec; - -namespace str_format_internal { - -class BoundConversion : public FormatConversionSpecImpl { - public: - const FormatArgImpl* arg() const { return arg_; } - void set_arg(const FormatArgImpl* a) { arg_ = a; } - - private: - const FormatArgImpl* arg_; -}; - -// This is the type-erased class that the implementation uses. -class UntypedFormatSpecImpl { - public: - UntypedFormatSpecImpl() = delete; - - explicit UntypedFormatSpecImpl(string_view s) - : data_(s.data()), size_(s.size()) {} - explicit UntypedFormatSpecImpl( - const str_format_internal::ParsedFormatBase* pc) - : data_(pc), size_(~size_t{}) {} - - bool has_parsed_conversion() const { return size_ == ~size_t{}; } - - string_view str() const { - assert(!has_parsed_conversion()); - return string_view(static_cast<const char*>(data_), size_); - } - const str_format_internal::ParsedFormatBase* parsed_conversion() const { - assert(has_parsed_conversion()); - return static_cast<const str_format_internal::ParsedFormatBase*>(data_); - } - - template <typename T> - static const UntypedFormatSpecImpl& Extract(const T& s) { - return s.spec_; - } - - private: - const void* data_; - size_t size_; -}; - -template <typename T, FormatConversionCharSet...> -struct MakeDependent { - using type = T; -}; - -// 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> -class FormatSpecTemplate - : public MakeDependent<UntypedFormatSpec, Args...>::type { - using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type; - - public: -#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - - // Honeypot overload for when the string is not constexpr. - // We use the 'unavailable' attribute to give a better compiler error than - // just 'method is deleted'. - FormatSpecTemplate(...) // NOLINT - __attribute__((unavailable("Format 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 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 - __attribute__(( - enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"), - unavailable( - "Format specified does not match the arguments passed."))); - - template <typename T = void> - FormatSpecTemplate(string_view s) // NOLINT - __attribute__((enable_if(str_format_internal::EnsureConstexpr(s), - "constexpr trap"))) { - static_assert(sizeof(T*) == 0, - "Format specified does not match the arguments passed."); - } - - // Good format overload. - FormatSpecTemplate(const char* s) // NOLINT - __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap"))) - : Base(s) {} - - FormatSpecTemplate(string_view s) // NOLINT - __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap"))) - : Base(s) {} - -#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - - FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT - FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT - -#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> - FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT - : Base(&pc) {} -}; - -class Streamable { - public: - Streamable(const UntypedFormatSpecImpl& format, - absl::Span<const FormatArgImpl> args) - : format_(format) { - if (args.size() <= ABSL_ARRAYSIZE(few_args_)) { - for (size_t i = 0; i < args.size(); ++i) { - few_args_[i] = args[i]; - } - args_ = absl::MakeSpan(few_args_, args.size()); - } else { - many_args_.assign(args.begin(), args.end()); - args_ = many_args_; - } - } - - std::ostream& Print(std::ostream& os) const; - - friend std::ostream& operator<<(std::ostream& os, const Streamable& l) { - return l.Print(os); - } - - private: - const UntypedFormatSpecImpl& format_; - absl::Span<const FormatArgImpl> args_; - // if args_.size() is 4 or less: - FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0), - FormatArgImpl(0), FormatArgImpl(0)}; - // if args_.size() is more than 4: - std::vector<FormatArgImpl> many_args_; -}; - -// for testing -std::string Summarize(UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); -bool BindWithPack(const UnboundConversion* props, - absl::Span<const FormatArgImpl> pack, BoundConversion* bound); - -bool FormatUntyped(FormatRawSinkImpl raw_sink, - UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); - -std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); - -std::string FormatPack(const UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); - -int FprintF(std::FILE* output, UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); -int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format, - absl::Span<const FormatArgImpl> args); - -// Returned by Streamed(v). Converts via '%s' to the std::string created -// by std::ostream << v. -template <typename T> -class StreamedWrapper { - public: - explicit StreamedWrapper(const T& v) : v_(v) { } - - private: - template <typename S> - friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl( - const StreamedWrapper<S>& v, FormatConversionSpecImpl conv, - FormatSinkImpl* out); - const T& v_; -}; - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ diff --git a/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 deleted file mode 100644 index 1eef9c4326e2..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind_test.cc +++ /dev/null @@ -1,157 +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/str_format/bind.h" - -#include <string.h> -#include <limits> - -#include "gtest/gtest.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { -namespace { - -class FormatBindTest : public ::testing::Test { - public: - bool Extract(const char *s, UnboundConversion *props, int *next) const { - return ConsumeUnboundConversion(s, s + strlen(s), props, next) == - s + strlen(s); - } -}; - -TEST_F(FormatBindTest, BindSingle) { - struct Expectation { - int line; - const char *fmt; - int ok_phases; - const FormatArgImpl *arg; - int width; - int precision; - int next_arg; - }; - const int no = -1; - const int ia[] = { 10, 20, 30, 40}; - const FormatArgImpl args[] = {FormatArgImpl(ia[0]), FormatArgImpl(ia[1]), - FormatArgImpl(ia[2]), FormatArgImpl(ia[3])}; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" - const Expectation kExpect[] = { - {__LINE__, "d", 2, &args[0], no, no, 2}, - {__LINE__, "4d", 2, &args[0], 4, no, 2}, - {__LINE__, ".5d", 2, &args[0], no, 5, 2}, - {__LINE__, "4.5d", 2, &args[0], 4, 5, 2}, - {__LINE__, "*d", 2, &args[1], 10, no, 3}, - {__LINE__, ".*d", 2, &args[1], no, 10, 3}, - {__LINE__, "*.*d", 2, &args[2], 10, 20, 4}, - {__LINE__, "1$d", 2, &args[0], no, no, 0}, - {__LINE__, "2$d", 2, &args[1], no, no, 0}, - {__LINE__, "3$d", 2, &args[2], no, no, 0}, - {__LINE__, "4$d", 2, &args[3], no, no, 0}, - {__LINE__, "2$*1$d", 2, &args[1], 10, no, 0}, - {__LINE__, "2$*2$d", 2, &args[1], 20, no, 0}, - {__LINE__, "2$*3$d", 2, &args[1], 30, no, 0}, - {__LINE__, "2$.*1$d", 2, &args[1], no, 10, 0}, - {__LINE__, "2$.*2$d", 2, &args[1], no, 20, 0}, - {__LINE__, "2$.*3$d", 2, &args[1], no, 30, 0}, - {__LINE__, "2$*3$.*1$d", 2, &args[1], 30, 10, 0}, - {__LINE__, "2$*2$.*2$d", 2, &args[1], 20, 20, 0}, - {__LINE__, "2$*1$.*3$d", 2, &args[1], 10, 30, 0}, - {__LINE__, "2$*3$.*1$d", 2, &args[1], 30, 10, 0}, - {__LINE__, "1$*d", 0}, // indexed, then positional - {__LINE__, "*2$d", 0}, // positional, then indexed - {__LINE__, "6$d", 1}, // arg position out of bounds - {__LINE__, "1$6$d", 0}, // width position incorrectly specified - {__LINE__, "1$.6$d", 0}, // precision position incorrectly specified - {__LINE__, "1$*6$d", 1}, // width position out of bounds - {__LINE__, "1$.*6$d", 1}, // precision position out of bounds - }; -#pragma GCC diagnostic pop - for (const Expectation &e : kExpect) { - SCOPED_TRACE(e.line); - SCOPED_TRACE(e.fmt); - UnboundConversion props; - BoundConversion bound; - int ok_phases = 0; - int next = 0; - if (Extract(e.fmt, &props, &next)) { - ++ok_phases; - if (BindWithPack(&props, args, &bound)) { - ++ok_phases; - } - } - EXPECT_EQ(e.ok_phases, ok_phases); - if (e.ok_phases < 2) continue; - if (e.arg != nullptr) { - EXPECT_EQ(e.arg, bound.arg()); - } - EXPECT_EQ(e.width, bound.width()); - EXPECT_EQ(e.precision, bound.precision()); - } -} - -TEST_F(FormatBindTest, WidthUnderflowRegression) { - UnboundConversion props; - BoundConversion bound; - int next = 0; - const int args_i[] = {std::numeric_limits<int>::min(), 17}; - const FormatArgImpl args[] = {FormatArgImpl(args_i[0]), - FormatArgImpl(args_i[1])}; - ASSERT_TRUE(Extract("*d", &props, &next)); - ASSERT_TRUE(BindWithPack(&props, args, &bound)); - - EXPECT_EQ(bound.width(), std::numeric_limits<int>::max()); - EXPECT_EQ(bound.arg(), args + 1); -} - -TEST_F(FormatBindTest, FormatPack) { - struct Expectation { - int line; - const char *fmt; - const char *summary; - }; - const int ia[] = { 10, 20, 30, 40, -10 }; - const FormatArgImpl args[] = {FormatArgImpl(ia[0]), FormatArgImpl(ia[1]), - FormatArgImpl(ia[2]), FormatArgImpl(ia[3]), - FormatArgImpl(ia[4])}; - const Expectation kExpect[] = { - {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"}, - {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"}, - {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"}, - {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"}, - {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"}, - {__LINE__, "a%.*fb", "a{20:.10f}b"}, - {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"}, - {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"}, - {__LINE__, "a%04ldb", "a{10:04d}b"}, - {__LINE__, "a%-#04lldb", "a{10:-#04d}b"}, - {__LINE__, "a%1$*5$db", "a{10:-10d}b"}, - {__LINE__, "a%1$.*5$db", "a{10:d}b"}, - }; - for (const Expectation &e : kExpect) { - absl::string_view fmt = e.fmt; - SCOPED_TRACE(e.line); - SCOPED_TRACE(e.fmt); - UntypedFormatSpecImpl format(fmt); - EXPECT_EQ(e.summary, - str_format_internal::Summarize(format, absl::MakeSpan(args))) - << "line:" << e.line; - } -} - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 2a2601eccfd8..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/checker.h +++ /dev/null @@ -1,333 +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_STR_FORMAT_CHECKER_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ - -#include "absl/base/attributes.h" -#include "absl/strings/internal/str_format/arg.h" -#include "absl/strings/internal/str_format/extension.h" - -// Compile time check support for entry points. - -#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER -#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) -#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1 -#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) -#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -constexpr bool AllOf() { return true; } - -template <typename... T> -constexpr bool AllOf(bool b, T... t) { - return b && AllOf(t...); -} - -#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - -constexpr bool ContainsChar(const char* chars, char c) { - return *chars == c || (*chars && ContainsChar(chars + 1, c)); -} - -// A constexpr compatible list of Convs. -struct ConvList { - const FormatConversionCharSet* array; - int count; - - // We do the bound check here to avoid having to do it on the callers. - // Returning an empty FormatConversionCharSet has the same effect as - // short circuiting because it will never match any conversion. - constexpr FormatConversionCharSet operator[](int i) const { - return i < count ? array[i] : FormatConversionCharSet{}; - } - - constexpr ConvList without_front() const { - return count != 0 ? ConvList{array + 1, count - 1} : *this; - } -}; - -template <size_t count> -struct ConvListT { - // Make sure the array has size > 0. - FormatConversionCharSet list[count ? count : 1]; -}; - -constexpr char GetChar(string_view str, size_t index) { - return index < str.size() ? str[index] : char{}; -} - -constexpr string_view ConsumeFront(string_view str, size_t len = 1) { - return len <= str.size() ? string_view(str.data() + len, str.size() - len) - : string_view(); -} - -constexpr string_view ConsumeAnyOf(string_view format, const char* chars) { - return ContainsChar(chars, GetChar(format, 0)) - ? ConsumeAnyOf(ConsumeFront(format), chars) - : format; -} - -constexpr bool IsDigit(char c) { return c >= '0' && c <= '9'; } - -// Helper class for the ParseDigits function. -// It encapsulates the two return values we need there. -struct Integer { - string_view format; - int value; - - // If the next character is a '$', consume it. - // Otherwise, make `this` an invalid positional argument. - constexpr Integer ConsumePositionalDollar() const { - return GetChar(format, 0) == '$' ? Integer{ConsumeFront(format), value} - : Integer{format, 0}; - } -}; - -constexpr Integer ParseDigits(string_view format, int value = 0) { - return IsDigit(GetChar(format, 0)) - ? ParseDigits(ConsumeFront(format), - 10 * value + GetChar(format, 0) - '0') - : Integer{format, value}; -} - -// Parse digits for a positional argument. -// The parsing also consumes the '$'. -constexpr Integer ParsePositional(string_view format) { - return ParseDigits(format).ConsumePositionalDollar(); -} - -// Parses a single conversion specifier. -// See ConvParser::Run() for post conditions. -class ConvParser { - constexpr ConvParser SetFormat(string_view format) const { - return ConvParser(format, args_, error_, arg_position_, is_positional_); - } - - constexpr ConvParser SetArgs(ConvList args) const { - return ConvParser(format_, args, error_, arg_position_, is_positional_); - } - - constexpr ConvParser SetError(bool error) const { - return ConvParser(format_, args_, error_ || error, arg_position_, - is_positional_); - } - - constexpr ConvParser SetArgPosition(int arg_position) const { - return ConvParser(format_, args_, error_, arg_position, is_positional_); - } - - // Consumes the next arg and verifies that it matches `conv`. - // `error_` is set if there is no next arg or if it doesn't match `conv`. - constexpr ConvParser ConsumeNextArg(char conv) const { - return SetArgs(args_.without_front()).SetError(!Contains(args_[0], conv)); - } - - // Verify that positional argument `i.value` matches `conv`. - // `error_` is set if `i.value` is not a valid argument or if it doesn't - // match. - constexpr ConvParser VerifyPositional(Integer i, char conv) const { - return SetFormat(i.format).SetError(!Contains(args_[i.value - 1], conv)); - } - - // Parse the position of the arg and store it in `arg_position_`. - constexpr ConvParser ParseArgPosition(Integer arg) const { - return SetFormat(arg.format).SetArgPosition(arg.value); - } - - // Consume the flags. - constexpr ConvParser ParseFlags() const { - return SetFormat(ConsumeAnyOf(format_, "-+ #0")); - } - - // Consume the width. - // If it is '*', we verify that it matches `args_`. `error_` is set if it - // doesn't match. - constexpr ConvParser ParseWidth() const { - return IsDigit(GetChar(format_, 0)) - ? SetFormat(ParseDigits(format_).format) - : GetChar(format_, 0) == '*' - ? is_positional_ - ? VerifyPositional( - ParsePositional(ConsumeFront(format_)), '*') - : SetFormat(ConsumeFront(format_)) - .ConsumeNextArg('*') - : *this; - } - - // Consume the precision. - // If it is '*', we verify that it matches `args_`. `error_` is set if it - // doesn't match. - constexpr ConvParser ParsePrecision() const { - return GetChar(format_, 0) != '.' - ? *this - : GetChar(format_, 1) == '*' - ? is_positional_ - ? VerifyPositional( - ParsePositional(ConsumeFront(format_, 2)), '*') - : SetFormat(ConsumeFront(format_, 2)) - .ConsumeNextArg('*') - : SetFormat(ParseDigits(ConsumeFront(format_)).format); - } - - // Consume the length characters. - constexpr ConvParser ParseLength() const { - return SetFormat(ConsumeAnyOf(format_, "lLhjztq")); - } - - // Consume the conversion character and verify that it matches `args_`. - // `error_` is set if it doesn't match. - constexpr ConvParser ParseConversion() const { - return is_positional_ - ? VerifyPositional({ConsumeFront(format_), arg_position_}, - GetChar(format_, 0)) - : ConsumeNextArg(GetChar(format_, 0)) - .SetFormat(ConsumeFront(format_)); - } - - constexpr ConvParser(string_view format, ConvList args, bool error, - int arg_position, bool is_positional) - : format_(format), - args_(args), - error_(error), - arg_position_(arg_position), - is_positional_(is_positional) {} - - public: - constexpr ConvParser(string_view format, ConvList args, bool is_positional) - : format_(format), - args_(args), - error_(false), - arg_position_(0), - is_positional_(is_positional) {} - - // Consume the whole conversion specifier. - // `format()` will be set to the character after the conversion character. - // `error()` will be set if any of the arguments do not match. - constexpr ConvParser Run() const { - return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *this) - .ParseFlags() - .ParseWidth() - .ParsePrecision() - .ParseLength() - .ParseConversion(); - } - - constexpr string_view format() const { return format_; } - constexpr ConvList args() const { return args_; } - constexpr bool error() const { return error_; } - constexpr bool is_positional() const { return is_positional_; } - - private: - string_view format_; - // Current list of arguments. If we are not in positional mode we will consume - // from the front. - ConvList args_; - bool error_; - // Holds the argument position of the conversion character, if we are in - // positional mode. Otherwise, it is unspecified. - int arg_position_; - // Whether we are in positional mode. - // It changes the behavior of '*' and where to find the converted argument. - bool is_positional_; -}; - -// Parses a whole format expression. -// See FormatParser::Run(). -class FormatParser { - static constexpr bool FoundPercent(string_view format) { - return format.empty() || - (GetChar(format, 0) == '%' && GetChar(format, 1) != '%'); - } - - // We use an inner function to increase the recursion limit. - // The inner function consumes up to `limit` characters on every run. - // This increases the limit from 512 to ~512*limit. - static constexpr string_view ConsumeNonPercentInner(string_view format, - int limit = 20) { - return FoundPercent(format) || !limit - ? format - : ConsumeNonPercentInner( - ConsumeFront(format, GetChar(format, 0) == '%' && - GetChar(format, 1) == '%' - ? 2 - : 1), - limit - 1); - } - - // Consume characters until the next conversion spec %. - // It skips %%. - static constexpr string_view ConsumeNonPercent(string_view format) { - return FoundPercent(format) - ? format - : ConsumeNonPercent(ConsumeNonPercentInner(format)); - } - - static constexpr bool IsPositional(string_view format) { - return IsDigit(GetChar(format, 0)) ? IsPositional(ConsumeFront(format)) - : GetChar(format, 0) == '$'; - } - - constexpr bool RunImpl(bool is_positional) const { - // In non-positional mode we require all arguments to be consumed. - // In positional mode just reaching the end of the format without errors is - // enough. - return (format_.empty() && (is_positional || args_.count == 0)) || - (!format_.empty() && - ValidateArg( - ConvParser(ConsumeFront(format_), args_, is_positional).Run())); - } - - constexpr bool ValidateArg(ConvParser conv) const { - return !conv.error() && FormatParser(conv.format(), conv.args()) - .RunImpl(conv.is_positional()); - } - - public: - constexpr FormatParser(string_view format, ConvList args) - : format_(ConsumeNonPercent(format)), args_(args) {} - - // Runs the parser for `format` and `args`. - // It verifies that the format is valid and that all conversion specifiers - // match the arguments passed. - // In non-positional mode it also verfies that all arguments are consumed. - constexpr bool Run() const { - return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_))); - } - - private: - string_view format_; - // Current list of arguments. - // If we are not in positional mode we will consume from the front and will - // have to be empty in the end. - ConvList args_; -}; - -template <FormatConversionCharSet... C> -constexpr bool ValidFormatImpl(string_view format) { - return FormatParser(format, - {ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)}) - .Run(); -} - -#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ diff --git a/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 deleted file mode 100644 index 7c70f47d682a..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/checker_test.cc +++ /dev/null @@ -1,170 +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 <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/str_format.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { -namespace { - -std::string ConvToString(FormatConversionCharSet conv) { - std::string out; -#define CONV_SET_CASE(c) \ - if (Contains(conv, FormatConversionCharSetInternal::c)) { \ - out += #c; \ - } - ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, ) -#undef CONV_SET_CASE - if (Contains(conv, FormatConversionCharSetInternal::kStar)) { - out += "*"; - } - return out; -} - -TEST(StrFormatChecker, ArgumentToConv) { - FormatConversionCharSet conv = ArgumentToConv<std::string>(); - EXPECT_EQ(ConvToString(conv), "s"); - - conv = ArgumentToConv<const char*>(); - EXPECT_EQ(ConvToString(conv), "sp"); - - conv = ArgumentToConv<double>(); - EXPECT_EQ(ConvToString(conv), "fFeEgGaA"); - - conv = ArgumentToConv<int>(); - EXPECT_EQ(ConvToString(conv), "cdiouxXfFeEgGaA*"); - - conv = ArgumentToConv<std::string*>(); - EXPECT_EQ(ConvToString(conv), "p"); -} - -#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - -struct Case { - bool result; - const char* format; -}; - -template <typename... Args> -constexpr Case ValidFormat(const char* format) { - return {ValidFormatImpl<ArgumentToConv<Args>()...>(format), format}; -} - -TEST(StrFormatChecker, ValidFormat) { - // We want to make sure these expressions are constexpr and they have the - // expected value. - // If they are not constexpr the attribute will just ignore them and not give - // a compile time error. - enum e {}; - enum class e2 {}; - constexpr Case trues[] = { - ValidFormat<>("abc"), // - - ValidFormat<e>("%d"), // - ValidFormat<e2>("%d"), // - ValidFormat<int>("%% %d"), // - ValidFormat<int>("%ld"), // - ValidFormat<int>("%lld"), // - ValidFormat<std::string>("%s"), // - ValidFormat<std::string>("%10s"), // - ValidFormat<int>("%.10x"), // - ValidFormat<int, int>("%*.3x"), // - ValidFormat<int>("%1.d"), // - ValidFormat<int>("%.d"), // - ValidFormat<int, double>("%d %g"), // - ValidFormat<int, std::string>("%*s"), // - ValidFormat<int, double>("%.*f"), // - ValidFormat<void (*)(), volatile int*>("%p %p"), // - ValidFormat<string_view, const char*, double, void*>( - "string_view=%s const char*=%s double=%f void*=%p)"), - - ValidFormat<int>("%% %1$d"), // - ValidFormat<int>("%1$ld"), // - ValidFormat<int>("%1$lld"), // - ValidFormat<std::string>("%1$s"), // - ValidFormat<std::string>("%1$10s"), // - ValidFormat<int>("%1$.10x"), // - ValidFormat<int>("%1$*1$.*1$d"), // - ValidFormat<int, int>("%1$*2$.3x"), // - ValidFormat<int>("%1$1.d"), // - ValidFormat<int>("%1$.d"), // - ValidFormat<double, int>("%2$d %1$g"), // - ValidFormat<int, std::string>("%2$*1$s"), // - ValidFormat<int, double>("%2$.*1$f"), // - ValidFormat<void*, string_view, const char*, double>( - "string_view=%2$s const char*=%3$s double=%4$f void*=%1$p " - "repeat=%3$s)")}; - - for (Case c : trues) { - EXPECT_TRUE(c.result) << c.format; - } - - constexpr Case falses[] = { - ValidFormat<int>(""), // - - ValidFormat<e>("%s"), // - ValidFormat<e2>("%s"), // - ValidFormat<>("%s"), // - ValidFormat<>("%r"), // - ValidFormat<int>("%s"), // - ValidFormat<int>("%.1.d"), // - ValidFormat<int>("%*1d"), // - ValidFormat<int>("%1-d"), // - ValidFormat<std::string, int>("%*s"), // - ValidFormat<int>("%*d"), // - ValidFormat<std::string>("%p"), // - ValidFormat<int (*)(int)>("%d"), // - - ValidFormat<>("%3$d"), // - ValidFormat<>("%1$r"), // - ValidFormat<int>("%1$s"), // - ValidFormat<int>("%1$.1.d"), // - ValidFormat<int>("%1$*2$1d"), // - ValidFormat<int>("%1$1-d"), // - ValidFormat<std::string, int>("%2$*1$s"), // - ValidFormat<std::string>("%1$p"), - - ValidFormat<int, int>("%d %2$d"), // - }; - - for (Case c : falses) { - EXPECT_FALSE(c.result) << c.format; - } -} - -TEST(StrFormatChecker, LongFormat) { -#define CHARS_X_40 "1234567890123456789012345678901234567890" -#define CHARS_X_400 \ - CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 \ - CHARS_X_40 CHARS_X_40 CHARS_X_40 -#define CHARS_X_4000 \ - CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 \ - CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 - constexpr char long_format[] = - CHARS_X_4000 "%d" CHARS_X_4000 "%s" CHARS_X_4000; - constexpr bool is_valid = ValidFormat<int, std::string>(long_format).result; - EXPECT_TRUE(is_valid); -} - -#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 375db0a0592c..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/convert_test.cc +++ /dev/null @@ -1,1242 +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 <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; -} - -std::string LengthModFor(float) { return ""; } -std::string LengthModFor(double) { return ""; } -std::string LengthModFor(long double) { return "L"; } -std::string LengthModFor(char) { return "hh"; } -std::string LengthModFor(signed char) { return "hh"; } -std::string LengthModFor(unsigned char) { return "hh"; } -std::string LengthModFor(short) { return "h"; } // NOLINT -std::string LengthModFor(unsigned short) { return "h"; } // NOLINT -std::string LengthModFor(int) { return ""; } -std::string LengthModFor(unsigned) { return ""; } -std::string LengthModFor(long) { return "l"; } // NOLINT -std::string LengthModFor(unsigned long) { return "l"; } // NOLINT -std::string LengthModFor(long long) { return "ll"; } // NOLINT -std::string LengthModFor(unsigned long long) { return "ll"; } // NOLINT - -std::string EscCharImpl(int v) { - if (std::isprint(static_cast<unsigned char>(v))) { - return std::string(1, static_cast<char>(v)); - } - char buf[64]; - int n = snprintf(buf, sizeof(buf), "\\%#.2x", - static_cast<unsigned>(v & 0xff)); - assert(n > 0 && n < sizeof(buf)); - return std::string(buf, n); -} - -std::string Esc(char v) { return EscCharImpl(v); } -std::string Esc(signed char v) { return EscCharImpl(v); } -std::string Esc(unsigned char v) { return EscCharImpl(v); } - -template <typename T> -std::string Esc(const T &v) { - std::ostringstream oss; - oss << v; - return oss.str(); -} - -void StrAppendV(std::string *dst, const char *format, va_list ap) { - // First try with a small fixed size buffer - static const int kSpaceLength = 1024; - char space[kSpaceLength]; - - // It's possible for methods that use a va_list to invalidate - // the data in it upon use. The fix is to make a copy - // of the structure before using it and use that copy instead. - va_list backup_ap; - va_copy(backup_ap, ap); - int result = vsnprintf(space, kSpaceLength, format, backup_ap); - va_end(backup_ap); - if (result < kSpaceLength) { - if (result >= 0) { - // Normal case -- everything fit. - dst->append(space, result); - return; - } - if (result < 0) { - // Just an error. - return; - } - } - - // Increase the buffer size to the size requested by vsnprintf, - // plus one for the closing \0. - int length = result + 1; - char *buf = new char[length]; - - // Restore the va_list before we use it again - va_copy(backup_ap, ap); - result = vsnprintf(buf, length, format, backup_ap); - va_end(backup_ap); - - if (result >= 0 && result < length) { - // It fit - dst->append(buf, result); - } - 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); - 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> -void TestStringConvert(const T& str) { - const FormatArgImpl args[] = {FormatArgImpl(str)}; - struct Expectation { - const char *out; - const char *fmt; - }; - const Expectation kExpect[] = { - {"hello", "%1$s" }, - {"", "%1$.s" }, - {"", "%1$.0s" }, - {"h", "%1$.1s" }, - {"he", "%1$.2s" }, - {"hello", "%1$.10s" }, - {" hello", "%1$6s" }, - {" he", "%1$5.2s" }, - {"he ", "%1$-5.2s" }, - {"hello ", "%1$-6.10s" }, - }; - for (const Expectation &e : kExpect) { - UntypedFormatSpecImpl format(e.fmt); - EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); - } -} - -TEST_F(FormatConvertTest, BasicString) { - TestStringConvert("hello"); // As char array. - TestStringConvert(static_cast<const char*>("hello")); - TestStringConvert(std::string("hello")); - TestStringConvert(string_view("hello")); -} - -TEST_F(FormatConvertTest, NullString) { - const char* p = nullptr; - UntypedFormatSpecImpl format("%s"); - EXPECT_EQ("", FormatPack(format, {FormatArgImpl(p)})); -} - -TEST_F(FormatConvertTest, StringPrecision) { - // We cap at the precision. - char c = 'a'; - const char* p = &c; - UntypedFormatSpecImpl format("%.1s"); - EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)})); - - // We cap at the NUL-terminator. - p = "ABC"; - UntypedFormatSpecImpl format2("%.10s"); - EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)})); -} - -// Pointer formatting is implementation defined. This checks that the argument -// can be matched to `ptr`. -MATCHER_P(MatchesPointerString, ptr, "") { - if (ptr == nullptr && arg == "(nil)") { - return true; - } - void* parsed = nullptr; - if (sscanf(arg.c_str(), "%p", &parsed) != 1) { - ABSL_RAW_LOG(FATAL, "Could not parse %s", arg.c_str()); - } - return ptr == parsed; -} - -TEST_F(FormatConvertTest, Pointer) { - static int x = 0; - const int *xp = &x; - char c = 'h'; - char *mcp = &c; - const char *cp = "hi"; - const char *cnil = nullptr; - const int *inil = nullptr; - using VoidF = void (*)(); - VoidF fp = [] {}, fnil = nullptr; - volatile char vc; - volatile char *vcp = &vc; - volatile char *vcnil = nullptr; - const FormatArgImpl args_array[] = { - FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil), - FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp), - FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil), - }; - auto args = absl::MakeConstSpan(args_array); - - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args), - MatchesPointerString(&x)); - - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), - MatchesPointerString(&x)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args), - MatchesPointerString(&x)); - - // const char* - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args), - MatchesPointerString(cp)); - // null const int* - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args), - MatchesPointerString(nullptr)); - // null const char* - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args), - MatchesPointerString(nullptr)); - // nonconst char* - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args), - MatchesPointerString(mcp)); - - // function pointers - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args), - MatchesPointerString(reinterpret_cast<const void*>(fp))); - EXPECT_THAT( - FormatPack(UntypedFormatSpecImpl("%8$p"), args), - MatchesPointerString(reinterpret_cast<volatile const void *>(vcp))); - - // null function pointers - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args), - MatchesPointerString(nullptr)); - EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args), - MatchesPointerString(nullptr)); -} - -struct Cardinal { - enum Pos { k1 = 1, k2 = 2, k3 = 3 }; - enum Neg { kM1 = -1, kM2 = -2, kM3 = -3 }; -}; - -TEST_F(FormatConvertTest, Enum) { - const Cardinal::Pos k3 = Cardinal::k3; - const Cardinal::Neg km3 = Cardinal::kM3; - const FormatArgImpl args[] = {FormatArgImpl(k3), FormatArgImpl(km3)}; - UntypedFormatSpecImpl format("%1$d"); - UntypedFormatSpecImpl format2("%2$d"); - EXPECT_EQ("3", FormatPack(format, absl::MakeSpan(args))); - EXPECT_EQ("-3", FormatPack(format2, absl::MakeSpan(args))); -} - -template <typename T> -class TypedFormatConvertTest : public FormatConvertTest { }; - -TYPED_TEST_SUITE_P(TypedFormatConvertTest); - -std::vector<std::string> AllFlagCombinations() { - const char kFlags[] = {'-', '#', '0', '+', ' '}; - std::vector<std::string> result; - for (size_t fsi = 0; fsi < (1ull << ArraySize(kFlags)); ++fsi) { - std::string flag_set; - for (size_t fi = 0; fi < ArraySize(kFlags); ++fi) - if (fsi & (1ull << fi)) - flag_set += kFlags[fi]; - result.push_back(flag_set); - } - return result; -} - -TYPED_TEST_P(TypedFormatConvertTest, AllIntsWithFlags) { - typedef TypeParam T; - typedef typename std::make_unsigned<T>::type UnsignedT; - using remove_volatile_t = typename std::remove_volatile<T>::type; - const T kMin = std::numeric_limits<remove_volatile_t>::min(); - const T kMax = std::numeric_limits<remove_volatile_t>::max(); - const T kVals[] = { - remove_volatile_t(1), - remove_volatile_t(2), - remove_volatile_t(3), - remove_volatile_t(123), - remove_volatile_t(-1), - remove_volatile_t(-2), - remove_volatile_t(-3), - remove_volatile_t(-123), - remove_volatile_t(0), - kMax - remove_volatile_t(1), - kMax, - kMin + remove_volatile_t(1), - kMin, - }; - const char kConvChars[] = {'d', 'i', 'u', 'o', 'x', 'X'}; - const std::string kWid[] = {"", "4", "10"}; - const std::string kPrec[] = {"", ".", ".0", ".4", ".10"}; - - const std::vector<std::string> flag_sets = AllFlagCombinations(); - - for (size_t vi = 0; vi < ArraySize(kVals); ++vi) { - const T val = kVals[vi]; - SCOPED_TRACE(Esc(val)); - const FormatArgImpl args[] = {FormatArgImpl(val)}; - for (size_t ci = 0; ci < ArraySize(kConvChars); ++ci) { - const char conv_char = kConvChars[ci]; - for (size_t fsi = 0; fsi < flag_sets.size(); ++fsi) { - const std::string &flag_set = flag_sets[fsi]; - for (size_t wi = 0; wi < ArraySize(kWid); ++wi) { - const std::string &wid = kWid[wi]; - for (size_t pi = 0; pi < ArraySize(kPrec); ++pi) { - const std::string &prec = kPrec[pi]; - - const bool is_signed_conv = (conv_char == 'd' || conv_char == 'i'); - const bool is_unsigned_to_signed = - !std::is_signed<T>::value && is_signed_conv; - // Don't consider sign-related flags '+' and ' ' when doing - // unsigned to signed conversions. - if (is_unsigned_to_signed && - flag_set.find_first_of("+ ") != std::string::npos) { - continue; - } - - std::string new_fmt("%"); - new_fmt += flag_set; - new_fmt += wid; - new_fmt += prec; - // old and new always agree up to here. - std::string old_fmt = new_fmt; - new_fmt += conv_char; - std::string old_result; - if (is_unsigned_to_signed) { - // don't expect agreement on unsigned formatted as signed, - // as printf can't do that conversion properly. For those - // cases, we do expect agreement with printf with a "%u" - // and the unsigned equivalent of 'val'. - UnsignedT uval = val; - old_fmt += LengthModFor(uval); - old_fmt += "u"; - old_result = StrPrint(old_fmt.c_str(), uval); - } else { - old_fmt += LengthModFor(val); - old_fmt += conv_char; - old_result = StrPrint(old_fmt.c_str(), val); - } - - SCOPED_TRACE(std::string() + " old_fmt: \"" + old_fmt + - "\"'" - " new_fmt: \"" + - new_fmt + "\""); - UntypedFormatSpecImpl format(new_fmt); - EXPECT_EQ(old_result, FormatPack(format, absl::MakeSpan(args))); - } - } - } - } - } -} - -TYPED_TEST_P(TypedFormatConvertTest, Char) { - typedef TypeParam T; - using remove_volatile_t = typename std::remove_volatile<T>::type; - static const T kMin = std::numeric_limits<remove_volatile_t>::min(); - static const T kMax = std::numeric_limits<remove_volatile_t>::max(); - T kVals[] = { - remove_volatile_t(1), remove_volatile_t(2), remove_volatile_t(10), - remove_volatile_t(-1), remove_volatile_t(-2), remove_volatile_t(-10), - remove_volatile_t(0), - kMin + remove_volatile_t(1), kMin, - kMax - remove_volatile_t(1), kMax - }; - for (const T &c : kVals) { - const FormatArgImpl args[] = {FormatArgImpl(c)}; - UntypedFormatSpecImpl format("%c"); - EXPECT_EQ(StrPrint("%c", c), FormatPack(format, absl::MakeSpan(args))); - } -} - -REGISTER_TYPED_TEST_CASE_P(TypedFormatConvertTest, AllIntsWithFlags, Char); - -typedef ::testing::Types< - int, unsigned, volatile int, - short, unsigned short, - long, unsigned long, - long long, unsigned long long, - signed char, unsigned char, char> - AllIntTypes; -INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, - TypedFormatConvertTest, AllIntTypes); -TEST_F(FormatConvertTest, VectorBool) { - // Make sure vector<bool>'s values behave as bools. - std::vector<bool> v = {true, false}; - const std::vector<bool> cv = {true, false}; - EXPECT_EQ("1,0,1,0", - FormatPack(UntypedFormatSpecImpl("%d,%d,%d,%d"), - absl::Span<const FormatArgImpl>( - {FormatArgImpl(v[0]), FormatArgImpl(v[1]), - FormatArgImpl(cv[0]), FormatArgImpl(cv[1])}))); -} - - -TEST_F(FormatConvertTest, Int128) { - absl::int128 positive = static_cast<absl::int128>(0x1234567890abcdef) * 1979; - absl::int128 negative = -positive; - absl::int128 max = absl::Int128Max(), min = absl::Int128Min(); - const FormatArgImpl args[] = {FormatArgImpl(positive), - FormatArgImpl(negative), FormatArgImpl(max), - FormatArgImpl(min)}; - - struct Case { - const char* format; - const char* expected; - } cases[] = { - {"%1$d", "2595989796776606496405"}, - {"%1$30d", " 2595989796776606496405"}, - {"%1$-30d", "2595989796776606496405 "}, - {"%1$u", "2595989796776606496405"}, - {"%1$x", "8cba9876066020f695"}, - {"%2$d", "-2595989796776606496405"}, - {"%2$30d", " -2595989796776606496405"}, - {"%2$-30d", "-2595989796776606496405 "}, - {"%2$u", "340282366920938460867384810655161715051"}, - {"%2$x", "ffffffffffffff73456789f99fdf096b"}, - {"%3$d", "170141183460469231731687303715884105727"}, - {"%3$u", "170141183460469231731687303715884105727"}, - {"%3$x", "7fffffffffffffffffffffffffffffff"}, - {"%4$d", "-170141183460469231731687303715884105728"}, - {"%4$x", "80000000000000000000000000000000"}, - }; - - for (auto c : cases) { - UntypedFormatSpecImpl format(c.format); - EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); - } -} - -TEST_F(FormatConvertTest, Uint128) { - absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979; - absl::uint128 max = absl::Uint128Max(); - const FormatArgImpl args[] = {FormatArgImpl(v), FormatArgImpl(max)}; - - struct Case { - const char* format; - const char* expected; - } cases[] = { - {"%1$d", "2595989796776606496405"}, - {"%1$30d", " 2595989796776606496405"}, - {"%1$-30d", "2595989796776606496405 "}, - {"%1$u", "2595989796776606496405"}, - {"%1$x", "8cba9876066020f695"}, - {"%2$d", "340282366920938463463374607431768211455"}, - {"%2$u", "340282366920938463463374607431768211455"}, - {"%2$x", "ffffffffffffffffffffffffffffffff"}, - }; - - for (auto c : cases) { - UntypedFormatSpecImpl format(c.format); - EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); - } -} - -template <typename Floating> -void TestWithMultipleFormatsHelper(const std::vector<Floating> &floats) { - 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)); - } - - if (string_printf_result != str_format_result) { - // 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) { -#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 - - 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()}; - - // 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()); - -#ifndef __APPLE__ - // Apple formats NaN differently (+nan) vs. (nan) - floats.push_back(std::nan("")); -#endif - - TestWithMultipleFormatsHelper(floats); -} - -TEST_F(FormatConvertTest, Double) { -#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 - - std::vector<double> doubles = {0.0, - -0.0, - .99999999999999, - 99999999999999., - std::numeric_limits<double>::max(), - -std::numeric_limits<double>::max(), - std::numeric_limits<double>::min(), - -std::numeric_limits<double>::min(), - std::numeric_limits<double>::lowest(), - -std::numeric_limits<double>::lowest(), - std::numeric_limits<double>::epsilon(), - std::numeric_limits<double>::epsilon() + 1, - std::numeric_limits<double>::infinity(), - -std::numeric_limits<double>::infinity()}; - - // Some regression tests. - doubles.push_back(0.99999999999999989); - - if (std::numeric_limits<double>::has_denorm != std::denorm_absent) { - doubles.push_back(std::numeric_limits<double>::denorm_min()); - doubles.push_back(-std::numeric_limits<double>::denorm_min()); - } - - for (double base : - {1., 12., 123., 1234., 12345., 123456., 1234567., 12345678., 123456789., - 1234567890., 12345678901., 123456789012., 1234567890123.}) { - for (int exp = -123; exp <= 123; ++exp) { - for (int sign : {1, -1}) { - doubles.push_back(sign * std::ldexp(base, exp)); - } - } - } - - // 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"; - - if (!gcc_bug_22142) { - 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) { - for (auto &d : doubles) { - using L = std::numeric_limits<double>; - double d2 = std::abs(d); - if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) { - d = 0; - } - } - } - - // Remove duplicates to speed up the logic below. - std::sort(doubles.begin(), doubles.end()); - doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end()); - -#ifndef __APPLE__ - // Apple formats NaN differently (+nan) vs. (nan) - doubles.push_back(std::nan("")); -#endif - - TestWithMultipleFormatsHelper(doubles); -} - -TEST_F(FormatConvertTest, DoubleRound) { - std::string s; - const auto format = [&](const char *fmt, double d) -> std::string & { - s.clear(); - FormatArgImpl args[1] = {FormatArgImpl(d)}; - AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); -#if !defined(_MSC_VER) - // MSVC has a different rounding policy than us so we can't test our - // implementation against the native one there. - EXPECT_EQ(StrPrint(fmt, d), s); -#endif // _MSC_VER - - return s; - }; - // All of these values have to be exactly represented. - // Otherwise we might not be testing what we think we are testing. - - // These values can fit in a 64bit "fast" representation. - const double exact_value = 0.00000000000005684341886080801486968994140625; - assert(exact_value == std::pow(2, -44)); - // Round up at a 5xx. - EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001"); - // Round up at a >5 - EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006"); - // Round down at a <5 - EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568"); - // Nine handling - EXPECT_EQ(format("%.35f", exact_value), - "0.00000000000005684341886080801486969"); - EXPECT_EQ(format("%.36f", exact_value), - "0.000000000000056843418860808014869690"); - // Round down the last nine. - EXPECT_EQ(format("%.37f", exact_value), - "0.0000000000000568434188608080148696899"); - EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147"); - // Round up the last nine - EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470"); - EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697"); - - // Round to even (down) - EXPECT_EQ(format("%.43f", exact_value), - "0.0000000000000568434188608080148696899414062"); - // Exact - EXPECT_EQ(format("%.44f", exact_value), - "0.00000000000005684341886080801486968994140625"); - // Round to even (up), let make the last digits 75 instead of 25 - EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)), - "0.0000000000001705302565824240446090698242188"); - // Exact, just to check. - EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)), - "0.00000000000017053025658242404460906982421875"); - - // This value has to be small enough that it won't fit in the uint128 - // representation for printing. - const double small_exact_value = - 0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625; // NOLINT - assert(small_exact_value == std::pow(2, -120)); - // Round up at a 5xx. - EXPECT_EQ(format("%.37f", small_exact_value), - "0.0000000000000000000000000000000000008"); - // Round down at a <5 - EXPECT_EQ(format("%.38f", small_exact_value), - "0.00000000000000000000000000000000000075"); - // Round up at a >5 - EXPECT_EQ(format("%.41f", small_exact_value), - "0.00000000000000000000000000000000000075232"); - // Nine handling - EXPECT_EQ(format("%.55f", small_exact_value), - "0.0000000000000000000000000000000000007523163845262640051"); - EXPECT_EQ(format("%.56f", small_exact_value), - "0.00000000000000000000000000000000000075231638452626400510"); - EXPECT_EQ(format("%.57f", small_exact_value), - "0.000000000000000000000000000000000000752316384526264005100"); - EXPECT_EQ(format("%.58f", small_exact_value), - "0.0000000000000000000000000000000000007523163845262640051000"); - // Round down the last nine - EXPECT_EQ(format("%.59f", small_exact_value), - "0.00000000000000000000000000000000000075231638452626400509999"); - // Round up the last nine - EXPECT_EQ(format("%.79f", small_exact_value), - "0.000000000000000000000000000000000000" - "7523163845262640050999913838222372338039460"); - - // Round to even (down) - EXPECT_EQ(format("%.119f", small_exact_value), - "0.000000000000000000000000000000000000" - "75231638452626400509999138382223723380" - "394595633413601376560109201818704605102539062"); - // Exact - EXPECT_EQ(format("%.120f", small_exact_value), - "0.000000000000000000000000000000000000" - "75231638452626400509999138382223723380" - "3945956334136013765601092018187046051025390625"); - // Round to even (up), let make the last digits 75 instead of 25 - EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)), - "0.000000000000000000000000000000000002" - "25694915357879201529997415146671170141" - "183786900240804129680327605456113815307617188"); - // Exact, just to check. - EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)), - "0.000000000000000000000000000000000002" - "25694915357879201529997415146671170141" - "1837869002408041296803276054561138153076171875"); -} - -TEST_F(FormatConvertTest, DoubleRoundA) { - const NativePrintfTraits &native_traits = VerifyNativeImplementation(); - std::string s; - const auto format = [&](const char *fmt, double d) -> std::string & { - s.clear(); - FormatArgImpl args[1] = {FormatArgImpl(d)}; - AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); - if (native_traits.hex_float_has_glibc_rounding) { - EXPECT_EQ(StrPrint(fmt, d), s); - } - return s; - }; - - // 0x1.00018000p+100 - const double on_boundary_odd = 1267679614447900152596896153600.0; - EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100"); - EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100"); - EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100"); - EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100"); - EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100"); // round - EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100"); - EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100"); - - // 0x1.00028000p-2 - const double on_boundary_even = 0.250009536743164062500; - EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2"); - EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2"); - EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2"); - EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2"); - EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2"); // no round - EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2"); - EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2"); - - // 0x1.00018001p+1 - const double slightly_over = 2.00004577683284878730773925781250; - EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1"); - EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1"); - EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1"); - EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1"); - EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1"); - EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1"); - EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1"); - - // 0x1.00017fffp+0 - const double slightly_under = 1.000022887950763106346130371093750; - EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0"); - EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0"); - EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0"); - EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0"); - EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0"); - EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0"); - EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0"); - EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0"); - - // 0x1.1b3829ac28058p+3 - const double hex_value = 8.85060580848964661981881363317370414733886718750; - EXPECT_EQ(format("%.0a", hex_value), "0x1p+3"); - EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3"); - EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3"); - EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3"); - EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3"); - EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3"); - EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3"); - EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3"); - EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3"); - EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3"); - EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3"); - EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3"); - EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3"); - EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3"); - EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3"); - EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3"); - EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3"); - EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3"); - EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3"); - EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3"); - EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3"); - EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3"); - - // 0x1.0818283848586p+3 - const double hex_value2 = 8.2529488658208371987257123691961169242858886718750; - EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3"); - EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3"); - EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3"); - EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3"); - EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3"); - EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3"); - EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3"); - EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3"); - EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3"); - EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3"); - EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3"); - EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3"); - EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3"); - EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3"); - EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3"); - EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3"); - EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3"); - EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3"); - EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3"); - EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3"); - EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3"); - EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3"); -} - -TEST_F(FormatConvertTest, LongDoubleRoundA) { - if (std::numeric_limits<long double>::digits % 4 != 0) { - // This test doesn't really make sense to run on platforms where a long - // double has a different mantissa size (mod 4) than Prod, since then the - // leading digit will be formatted differently. - return; - } - const NativePrintfTraits &native_traits = VerifyNativeImplementation(); - std::string s; - const auto format = [&](const char *fmt, long double d) -> std::string & { - s.clear(); - FormatArgImpl args[1] = {FormatArgImpl(d)}; - AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); - if (native_traits.hex_float_has_glibc_rounding && - native_traits.hex_float_optimizes_leading_digit_bit_count) { - EXPECT_EQ(StrPrint(fmt, d), s); - } - return s; - }; - - // 0x8.8p+4 - const long double on_boundary_even = 136.0; - EXPECT_EQ(format("%.0La", on_boundary_even), "0x8p+4"); - EXPECT_EQ(format("%.1La", on_boundary_even), "0x8.8p+4"); - EXPECT_EQ(format("%.2La", on_boundary_even), "0x8.80p+4"); - EXPECT_EQ(format("%.3La", on_boundary_even), "0x8.800p+4"); - EXPECT_EQ(format("%.4La", on_boundary_even), "0x8.8000p+4"); - EXPECT_EQ(format("%.5La", on_boundary_even), "0x8.80000p+4"); - EXPECT_EQ(format("%.6La", on_boundary_even), "0x8.800000p+4"); - - // 0x9.8p+4 - const long double on_boundary_odd = 152.0; - EXPECT_EQ(format("%.0La", on_boundary_odd), "0xap+4"); - EXPECT_EQ(format("%.1La", on_boundary_odd), "0x9.8p+4"); - EXPECT_EQ(format("%.2La", on_boundary_odd), "0x9.80p+4"); - EXPECT_EQ(format("%.3La", on_boundary_odd), "0x9.800p+4"); - EXPECT_EQ(format("%.4La", on_boundary_odd), "0x9.8000p+4"); - EXPECT_EQ(format("%.5La", on_boundary_odd), "0x9.80000p+4"); - EXPECT_EQ(format("%.6La", on_boundary_odd), "0x9.800000p+4"); - - // 0x8.80001p+24 - const long double slightly_over = 142606352.0; - EXPECT_EQ(format("%.0La", slightly_over), "0x9p+24"); - EXPECT_EQ(format("%.1La", slightly_over), "0x8.8p+24"); - EXPECT_EQ(format("%.2La", slightly_over), "0x8.80p+24"); - EXPECT_EQ(format("%.3La", slightly_over), "0x8.800p+24"); - EXPECT_EQ(format("%.4La", slightly_over), "0x8.8000p+24"); - EXPECT_EQ(format("%.5La", slightly_over), "0x8.80001p+24"); - EXPECT_EQ(format("%.6La", slightly_over), "0x8.800010p+24"); - - // 0x8.7ffffp+24 - const long double slightly_under = 142606320.0; - EXPECT_EQ(format("%.0La", slightly_under), "0x8p+24"); - EXPECT_EQ(format("%.1La", slightly_under), "0x8.8p+24"); - EXPECT_EQ(format("%.2La", slightly_under), "0x8.80p+24"); - EXPECT_EQ(format("%.3La", slightly_under), "0x8.800p+24"); - EXPECT_EQ(format("%.4La", slightly_under), "0x8.8000p+24"); - EXPECT_EQ(format("%.5La", slightly_under), "0x8.7ffffp+24"); - EXPECT_EQ(format("%.6La", slightly_under), "0x8.7ffff0p+24"); - EXPECT_EQ(format("%.7La", slightly_under), "0x8.7ffff00p+24"); - - // 0xc.0828384858688000p+128 - const long double eights = 4094231060438608800781871108094404067328.0; - EXPECT_EQ(format("%.0La", eights), "0xcp+128"); - EXPECT_EQ(format("%.1La", eights), "0xc.1p+128"); - EXPECT_EQ(format("%.2La", eights), "0xc.08p+128"); - EXPECT_EQ(format("%.3La", eights), "0xc.083p+128"); - EXPECT_EQ(format("%.4La", eights), "0xc.0828p+128"); - EXPECT_EQ(format("%.5La", eights), "0xc.08284p+128"); - EXPECT_EQ(format("%.6La", eights), "0xc.082838p+128"); - EXPECT_EQ(format("%.7La", eights), "0xc.0828385p+128"); - EXPECT_EQ(format("%.8La", eights), "0xc.08283848p+128"); - EXPECT_EQ(format("%.9La", eights), "0xc.082838486p+128"); - EXPECT_EQ(format("%.10La", eights), "0xc.0828384858p+128"); - EXPECT_EQ(format("%.11La", eights), "0xc.08283848587p+128"); - EXPECT_EQ(format("%.12La", eights), "0xc.082838485868p+128"); - EXPECT_EQ(format("%.13La", eights), "0xc.0828384858688p+128"); - EXPECT_EQ(format("%.14La", eights), "0xc.08283848586880p+128"); - EXPECT_EQ(format("%.15La", eights), "0xc.082838485868800p+128"); - EXPECT_EQ(format("%.16La", eights), "0xc.0828384858688000p+128"); -} - -// We don't actually store the results. This is just to exercise the rest of the -// machinery. -struct NullSink { - friend void AbslFormatFlush(NullSink *sink, string_view str) {} -}; - -template <typename... T> -bool FormatWithNullSink(absl::string_view fmt, const T &... a) { - NullSink sink; - FormatArgImpl args[] = {FormatArgImpl(a)...}; - return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); -} - -TEST_F(FormatConvertTest, ExtremeWidthPrecision) { - for (const char *fmt : {"f"}) { - for (double d : {1e-100, 1.0, 1e100}) { - constexpr int max = std::numeric_limits<int>::max(); - EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d)); - EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d)); - EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d)); - EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d)); - } - } -} - -TEST_F(FormatConvertTest, LongDouble) { -#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 - const NativePrintfTraits &native_traits = VerifyNativeImplementation(); - const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", - "%.60", "%+", "% ", "%-10"}; - - std::vector<long double> doubles = { - 0.0, - -0.0, - std::numeric_limits<long double>::max(), - -std::numeric_limits<long double>::max(), - std::numeric_limits<long double>::min(), - -std::numeric_limits<long double>::min(), - 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); - // We use ASSERT_EQ here because failures are usually correlated and a - // bug would print way too many failed expectations causing the test to - // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) - << fmt_str << " " << StrPrint("%.18Lg", d) << " " - << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); - } - } - } -} - -TEST_F(FormatConvertTest, IntAsDouble) { - const NativePrintfTraits &native_traits = VerifyNativeImplementation(); - const int kMin = std::numeric_limits<int>::min(); - const int kMax = std::numeric_limits<int>::max(); - const int ia[] = { - 1, 2, 3, 123, - -1, -2, -3, -123, - 0, kMax - 1, kMax, kMin + 1, kMin }; - for (const int fx : ia) { - SCOPED_TRACE(fx); - const FormatArgImpl args[] = {FormatArgImpl(fx)}; - struct Expectation { - int line; - std::string out; - 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"}, - }; - if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { - Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"}; - expect.push_back(ex); - } - for (const Expectation &e : expect) { - SCOPED_TRACE(e.line); - SCOPED_TRACE(e.fmt); - UntypedFormatSpecImpl format(e.fmt); - EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); - } - } -} - -template <typename T> -bool FormatFails(const char* test_format, T value) { - std::string format_string = std::string("<<") + test_format + ">>"; - UntypedFormatSpecImpl format(format_string); - - int one = 1; - const FormatArgImpl args[] = {FormatArgImpl(value), FormatArgImpl(one)}; - EXPECT_EQ(FormatPack(format, absl::MakeSpan(args)), "") - << "format=" << test_format << " value=" << value; - return FormatPack(format, absl::MakeSpan(args)).empty(); -} - -TEST_F(FormatConvertTest, ExpectedFailures) { - // Int input - EXPECT_TRUE(FormatFails("%p", 1)); - EXPECT_TRUE(FormatFails("%s", 1)); - EXPECT_TRUE(FormatFails("%n", 1)); - - // Double input - EXPECT_TRUE(FormatFails("%p", 1.)); - EXPECT_TRUE(FormatFails("%s", 1.)); - EXPECT_TRUE(FormatFails("%n", 1.)); - EXPECT_TRUE(FormatFails("%c", 1.)); - EXPECT_TRUE(FormatFails("%d", 1.)); - EXPECT_TRUE(FormatFails("%x", 1.)); - EXPECT_TRUE(FormatFails("%*d", 1.)); - - // String input - EXPECT_TRUE(FormatFails("%n", "")); - EXPECT_TRUE(FormatFails("%c", "")); - EXPECT_TRUE(FormatFails("%d", "")); - EXPECT_TRUE(FormatFails("%x", "")); - EXPECT_TRUE(FormatFails("%f", "")); - EXPECT_TRUE(FormatFails("%*d", "")); -} - -// Sanity check to make sure that we are testing what we think we're testing on -// e.g. the x86_64+glibc platform. -TEST_F(FormatConvertTest, GlibcHasCorrectTraits) { -#if !defined(__GLIBC__) || !defined(__x86_64__) - return; -#endif - const NativePrintfTraits &native_traits = VerifyNativeImplementation(); - // If one of the following tests break then it is either because the above PP - // macro guards failed to exclude a new platform (likely) or because something - // has changed in the implemention of glibc sprintf float formatting behavior. - // If the latter, then the code that computes these flags needs to be - // revisited and/or possibly the StrFormat implementation. - EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding); - EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr); - EXPECT_TRUE( - native_traits.hex_float_uses_minimal_precision_when_not_specified); - EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count); -} - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc deleted file mode 100644 index bb0d96cf3216..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc +++ /dev/null @@ -1,75 +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/strings/internal/str_format/extension.h" - -#include <errno.h> -#include <algorithm> -#include <string> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -std::string Flags::ToString() const { - std::string s; - 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) { - 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); - space_remaining = Excess(shown.size(), space_remaining); - if (!left) Append(space_remaining, ' '); - Append(shown); - if (left) Append(space_remaining, ' '); - return true; -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index a9b9e137deb2..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.h +++ /dev/null @@ -1,427 +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. -// -#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ - -#include <limits.h> - -#include <cstddef> -#include <cstring> -#include <ostream> - -#include "absl/base/config.h" -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/internal/str_format/output.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -enum class FormatConversionChar : uint8_t; -enum class FormatConversionCharSet : uint64_t; - -namespace str_format_internal { - -class FormatRawSinkImpl { - public: - // Implicitly convert from any type that provides the hook function as - // described above. - template <typename T, decltype(str_format_internal::InvokeFlush( - std::declval<T*>(), string_view()))* = nullptr> - FormatRawSinkImpl(T* raw) // NOLINT - : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {} - - void Write(string_view s) { write_(sink_, s); } - - template <typename T> - static FormatRawSinkImpl Extract(T s) { - return s.sink_; - } - - private: - template <typename T> - static void Flush(void* r, string_view s) { - str_format_internal::InvokeFlush(static_cast<T*>(r), s); - } - - void* sink_; - void (*write_)(void*, string_view); -}; - -// An abstraction to which conversions write their string data. -class FormatSinkImpl { - public: - explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {} - - ~FormatSinkImpl() { Flush(); } - - void Flush() { - raw_.Write(string_view(buf_, pos_ - buf_)); - pos_ = buf_; - } - - void Append(size_t n, char c) { - if (n == 0) return; - size_ += n; - auto raw_append = [&](size_t count) { - memset(pos_, c, count); - pos_ += count; - }; - while (n > Avail()) { - n -= Avail(); - if (Avail() > 0) { - raw_append(Avail()); - } - Flush(); - } - raw_append(n); - } - - void Append(string_view v) { - size_t n = v.size(); - if (n == 0) return; - size_ += n; - if (n >= Avail()) { - Flush(); - raw_.Write(v); - return; - } - memcpy(pos_, v.data(), n); - pos_ += n; - } - - 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); - - template <typename T> - T Wrap() { - return T(this); - } - - template <typename T> - static FormatSinkImpl* Extract(T* s) { - return s->sink_; - } - - private: - size_t Avail() const { return buf_ + sizeof(buf_) - pos_; } - - FormatRawSinkImpl raw_; - size_t size_ = 0; - char* pos_ = buf_; - char buf_[1024]; -}; - -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(); - } -}; - -// clang-format off -#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \ - /* text */ \ - X_VAL(c) X_SEP X_VAL(s) X_SEP \ - /* ints */ \ - X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \ - X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \ - /* floats */ \ - X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \ - X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \ - /* misc */ \ - X_VAL(n) X_SEP X_VAL(p) -// 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 - 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); -}; -// clang-format on - -inline FormatConversionChar FormatConversionCharFromChar(char c) { - switch (c) { -#define ABSL_INTERNAL_X_VAL(id) \ - case #id[0]: \ - return FormatConversionCharInternal::id; - ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, ) -#undef ABSL_INTERNAL_X_VAL - } - return FormatConversionCharInternal::kNone; -} - -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; - } -} - -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; - } -} - -inline char FormatConversionCharToChar(FormatConversionChar c) { - if (c == FormatConversionCharInternal::kNone) { - return '\0'; - -#define ABSL_INTERNAL_X_VAL(e) \ - } else if (c == FormatConversionCharInternal::e) { \ - return #e[0]; -#define ABSL_INTERNAL_X_SEP - ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, - ABSL_INTERNAL_X_SEP) - } else { - return '\0'; - } - -#undef ABSL_INTERNAL_X_VAL -#undef ABSL_INTERNAL_X_SEP -} - -// The associated char. -inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) { - char c = FormatConversionCharToChar(v); - if (!c) c = '?'; - return os << c; -} - -struct FormatConversionSpecImplFriend; - -class FormatConversionSpecImpl { - public: - // Width and precison are not specified, no flags are set. - bool is_basic() const { return flags_.basic; } - bool has_left_flag() const { return flags_.left; } - bool has_show_pos_flag() const { return flags_.show_pos; } - bool has_sign_col_flag() const { return flags_.sign_col; } - bool has_alt_flag() const { return flags_.alt; } - bool has_zero_flag() const { return flags_.zero; } - - FormatConversionChar conversion_char() const { - // Keep this field first in the struct . It generates better code when - // accessing it when ConversionSpec is passed by value in registers. - static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, ""); - return conv_; - } - - // Returns the specified width. If width is unspecfied, it returns a negative - // value. - int width() const { return width_; } - // Returns the specified precision. If precision is unspecfied, it returns a - // negative value. - int precision() const { return precision_; } - - template <typename T> - T Wrap() { - return T(*this); - } - - private: - friend struct str_format_internal::FormatConversionSpecImplFriend; - FormatConversionChar conv_ = FormatConversionCharInternal::kNone; - Flags flags_; - int width_; - int precision_; -}; - -struct FormatConversionSpecImplFriend final { - static void SetFlags(Flags f, FormatConversionSpecImpl* conv) { - conv->flags_ = f; - } - static void SetConversionChar(FormatConversionChar c, - FormatConversionSpecImpl* conv) { - conv->conv_ = c; - } - static void SetWidth(int w, FormatConversionSpecImpl* conv) { - conv->width_ = w; - } - static void SetPrecision(int p, FormatConversionSpecImpl* conv) { - conv->precision_ = p; - } - static std::string FlagsToString(const FormatConversionSpecImpl& spec) { - return spec.flags_.ToString(); - } -}; - -// Type safe OR operator. -// We need this for two reasons: -// 1. operator| on enums makes them decay to integers and the result is an -// integer. We need the result to stay as an enum. -// 2. We use "enum class" which would not work even if we accepted the decay. -constexpr FormatConversionCharSet FormatConversionCharSetUnion( - FormatConversionCharSet a) { - return a; -} - -template <typename... CharSet> -constexpr FormatConversionCharSet FormatConversionCharSetUnion( - FormatConversionCharSet a, CharSet... rest) { - return static_cast<FormatConversionCharSet>( - static_cast<uint64_t>(a) | - static_cast<uint64_t>(FormatConversionCharSetUnion(rest...))); -} - -constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) { - return uint64_t{1} << (1 + static_cast<uint8_t>(c)); -} - -constexpr uint64_t FormatConversionCharToConvInt(char conv) { - return -#define ABSL_INTERNAL_CHAR_SET_CASE(c) \ - conv == #c[0] \ - ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \ - : - ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) -#undef ABSL_INTERNAL_CHAR_SET_CASE - conv == '*' - ? 1 - : 0; -} - -constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) { - return static_cast<FormatConversionCharSet>( - FormatConversionCharToConvInt(conv)); -} - -struct FormatConversionCharSetInternal { -#define ABSL_INTERNAL_CHAR_SET_CASE(c) \ - static constexpr FormatConversionCharSet c = \ - FormatConversionCharToConvValue(#c[0]); - ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) -#undef ABSL_INTERNAL_CHAR_SET_CASE - - // Used for width/precision '*' specification. - static constexpr FormatConversionCharSet kStar = - FormatConversionCharToConvValue('*'); - - static constexpr FormatConversionCharSet kIntegral = - FormatConversionCharSetUnion(d, i, u, o, x, X); - static constexpr FormatConversionCharSet kFloating = - FormatConversionCharSetUnion(a, e, f, g, A, E, F, G); - static constexpr FormatConversionCharSet kNumeric = - FormatConversionCharSetUnion(kIntegral, kFloating); - static constexpr FormatConversionCharSet kPointer = p; -}; - -// Type safe OR operator. -// 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 operator|(FormatConversionCharSet a, - FormatConversionCharSet b) { - return FormatConversionCharSetUnion(a, b); -} - -// Overloaded conversion functions to support absl::ParsedFormat. -// Get a conversion with a single character in it. -constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) { - return static_cast<FormatConversionCharSet>( - FormatConversionCharToConvValue(c)); -} - -// Get a conversion with a single character in it. -constexpr 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; -} - -// Checks whether all the characters in `c` are contained in `set` -constexpr bool Contains(FormatConversionCharSet set, - FormatConversionCharSet c) { - return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) == - 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 capacity - used, clipped to a minimum of 0. -inline size_t Excess(size_t used, size_t capacity) { - return used < capacity ? capacity - used : 0; -} - -} // namespace str_format_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ 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 deleted file mode 100644 index 1c93fdb1c75b..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc +++ /dev/null @@ -1,98 +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/strings/internal/str_format/extension.h" - -#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 - -namespace { - -std::string MakeRandomString(size_t len) { - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis('a', 'z'); - std::string s(len, '0'); - for (char& c : s) { - c = dis(gen); - } - return s; -} - -TEST(FormatExtensionTest, SinkAppendSubstring) { - for (size_t chunk_size : {1, 10, 100, 1000, 10000}) { - std::string expected, actual; - absl::str_format_internal::FormatSinkImpl sink(&actual); - for (size_t chunks = 0; chunks < 10; ++chunks) { - std::string rand = MakeRandomString(chunk_size); - expected += rand; - sink.Append(rand); - } - sink.Flush(); - EXPECT_EQ(actual, expected); - } -} - -TEST(FormatExtensionTest, SinkAppendChars) { - for (size_t chunk_size : {1, 10, 100, 1000, 10000}) { - std::string expected, actual; - absl::str_format_internal::FormatSinkImpl sink(&actual); - for (size_t chunks = 0; chunks < 10; ++chunks) { - std::string rand = MakeRandomString(1); - expected.append(chunk_size, rand[0]); - sink.Append(chunk_size, rand[0]); - } - sink.Flush(); - 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 deleted file mode 100644 index 0ded0a66afa9..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.cc +++ /dev/null @@ -1,1419 +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/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/internal/bits.h" -#include "absl/base/optimization.h" -#include "absl/functional/function_ref.h" -#include "absl/meta/type_traits.h" -#include "absl/numeric/int128.h" -#include "absl/strings/numbers.h" -#include "absl/types/optional.h" -#include "absl/types/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -namespace { - -// 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; -} - -// 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<long double>::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<long double>::max_exponent); - static_assert( - static_cast<int>(StackArray::kMaxCapacity) >= - ChunksNeeded(std::numeric_limits<long double>::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<long double>::min_exponent - limits<long double>::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<long double>; - 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 base_internal::CountLeadingZeros64(v); } -int LeadingZeros(uint128 v) { - auto high = static_cast<uint64_t>(v >> 64); - auto low = static_cast<uint64_t>(v); - return high != 0 ? base_internal::CountLeadingZeros64(high) - : 64 + base_internal::CountLeadingZeros64(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<long double>::digits / 4 // number of hex digits - + 1 // round up - + 1; // "." (dot) - char digits_buffer[kBufSizeForHexFloatRepr]; - char *digits_iter = digits_buffer; - const char *const digits = - static_cast<const char *>("0123456789ABCDEF0123456789abcdef") + - (uppercase ? 0 : 16); - - // =============== Hex Prefix ================ - *digits_iter++ = '0'; - *digits_iter++ = uppercase ? 'X' : 'x'; - - // ========== Non-Fractional Digit =========== - *digits_iter++ = digits[leading]; - - // ================== Dot ==================== - // There are three reasons we might need a dot. Keep in mind that, at this - // point, the mantissa holds only the fractional part. - if ((precision_specified && state.precision > 0) || - (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) { - *digits_iter++ = '.'; - } - - // ============ Fractional Digits ============ - int digits_emitted = 0; - while (mantissa > 0) { - *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)]; - mantissa <<= 4; - ++digits_emitted; - } - int trailing_zeros = - precision_specified ? state.precision - digits_emitted : 0; - assert(trailing_zeros >= 0); - auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer); - - // =============== Exponent ================== - constexpr size_t kBufSizeForExpDecRepr = - numbers_internal::kFastToBufferSize // requred for FastIntToBuffer - + 1 // 'p' or 'P' - + 1; // '+' or '-' - char exp_buffer[kBufSizeForExpDecRepr]; - exp_buffer[0] = uppercase ? 'P' : 'p'; - exp_buffer[1] = exp >= 0 ? '+' : '-'; - numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2); - - // ============ Assemble Result ============== - FinalPrint(state, // - digits_result, // 0xN.NNN... - 2, // offset in `data` to start padding if needed. - trailing_zeros, // num remaining mantissa padding zeros - exp_buffer); // exponent -} - -char *CopyStringTo(absl::string_view v, char *out) { - std::memcpy(out, v.data(), v.size()); - return out + v.size(); -} - -template <typename Float> -bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - int w = conv.width() >= 0 ? conv.width() : 0; - int p = conv.precision() >= 0 ? conv.precision() : -1; - char fmt[32]; - { - char *fp = fmt; - *fp++ = '%'; - fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp); - fp = CopyStringTo("*.*", fp); - if (std::is_same<long double, Float>()) { - *fp++ = 'L'; - } - *fp++ = FormatConversionCharToChar(conv.conversion_char()); - *fp = 0; - assert(fp < fmt + sizeof(fmt)); - } - std::string space(512, '\0'); - absl::string_view result; - while (true) { - int n = snprintf(&space[0], space.size(), fmt, w, p, v); - if (n < 0) return false; - if (static_cast<size_t>(n) < space.size()) { - result = absl::string_view(space.data(), n); - break; - } - space.resize(n + 1); - } - sink->Append(result); - return true; -} - -// 128-bits in decimal: ceil(128*log(2)/log(10)) -// or std::numeric_limits<__uint128_t>::digits10 -constexpr int kMaxFixedPrecision = 39; - -constexpr int kBufferLength = /*sign*/ 1 + - /*integer*/ kMaxFixedPrecision + - /*point*/ 1 + - /*fraction*/ kMaxFixedPrecision + - /*exponent e+123*/ 5; - -struct Buffer { - void push_front(char c) { - assert(begin > data); - *--begin = c; - } - void push_back(char c) { - assert(end < data + sizeof(data)); - *end++ = c; - } - void pop_back() { - assert(begin < end); - --end; - } - - char &back() { - assert(begin < end); - return end[-1]; - } - - char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; } - - int size() const { return static_cast<int>(end - begin); } - - char data[kBufferLength]; - char *begin; - char *end; -}; - -enum class FormatStyle { Fixed, Precision }; - -// If the value is Inf or Nan, print it and return true. -// Otherwise, return false. -template <typename Float> -bool ConvertNonNumericFloats(char sign_char, Float v, - const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - char text[4], *ptr = text; - if (sign_char != '\0') *ptr++ = sign_char; - if (std::isnan(v)) { - ptr = std::copy_n( - FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3, - ptr); - } else if (std::isinf(v)) { - ptr = std::copy_n( - FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3, - ptr); - } else { - return false; - } - - return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1, - conv.has_left_flag()); -} - -// Round up the last digit of the value. -// It will carry over and potentially overflow. 'exp' will be adjusted in that -// case. -template <FormatStyle mode> -void RoundUp(Buffer *buffer, int *exp) { - char *p = &buffer->back(); - while (p >= buffer->begin && (*p == '9' || *p == '.')) { - if (*p == '9') *p = '0'; - --p; - } - - if (p < buffer->begin) { - *p = '1'; - buffer->begin = p; - if (mode == FormatStyle::Precision) { - std::swap(p[1], p[2]); // move the . - ++*exp; - buffer->pop_back(); - } - } else { - ++*p; - } -} - -void PrintExponent(int exp, char e, Buffer *out) { - out->push_back(e); - if (exp < 0) { - out->push_back('-'); - exp = -exp; - } else { - out->push_back('+'); - } - // Exponent digits. - if (exp > 99) { - out->push_back(exp / 100 + '0'); - out->push_back(exp / 10 % 10 + '0'); - out->push_back(exp % 10 + '0'); - } else { - out->push_back(exp / 10 + '0'); - out->push_back(exp % 10 + '0'); - } -} - -template <typename Float, typename Int> -constexpr bool CanFitMantissa() { - return -#if defined(__clang__) && !defined(__SSE3__) - // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 - // Casting from long double to uint64_t is miscompiled and drops bits. - (!std::is_same<Float, long double>::value || - !std::is_same<Int, uint64_t>::value) && -#endif - std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits; -} - -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; - int exponent; -}; - -// Decompose the double into an integer mantissa and an exponent. -template <typename Float> -Decomposed<Float> Decompose(Float v) { - int exp; - 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}; -} - -// Print 'digits' as decimal. -// In Fixed mode, we add a '.' at the end. -// In Precision mode, we add a '.' after the first digit. -template <FormatStyle mode, typename Int> -int PrintIntegralDigits(Int digits, Buffer *out) { - int printed = 0; - if (digits) { - for (; digits; digits /= 10) out->push_front(digits % 10 + '0'); - printed = out->size(); - if (mode == FormatStyle::Precision) { - out->push_front(*out->begin); - out->begin[1] = '.'; - } else { - out->push_back('.'); - } - } else if (mode == FormatStyle::Fixed) { - out->push_front('0'); - out->push_back('.'); - printed = 1; - } - return printed; -} - -// Back out 'extra_digits' digits and round up if necessary. -bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value, - Buffer *out, int *exp_out) { - if (extra_digits <= 0) return false; - - // Back out the extra digits - out->end -= extra_digits; - - bool needs_to_round_up = [&] { - // We look at the digit just past the end. - // There must be 'extra_digits' extra valid digits after end. - if (*out->end > '5') return true; - if (*out->end < '5') return false; - if (has_leftover_value || std::any_of(out->end + 1, out->end + extra_digits, - [](char c) { return c != '0'; })) - return true; - - // Ends in ...50*, round to even. - return out->last_digit() % 2 == 1; - }(); - - if (needs_to_round_up) { - RoundUp<FormatStyle::Precision>(out, exp_out); - } - return true; -} - -// Print the value into the buffer. -// This will not include the exponent, which will be returned in 'exp_out' for -// Precision mode. -template <typename Int, typename Float, FormatStyle mode> -bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out, - int *exp_out) { - assert((CanFitMantissa<Float, Int>())); - - const int int_bits = std::numeric_limits<Int>::digits; - - // In precision mode, we start printing one char to the right because it will - // also include the '.' - // In fixed mode we put the dot afterwards on the right. - out->begin = out->end = - out->data + 1 + kMaxFixedPrecision + (mode == FormatStyle::Precision); - - if (exp >= 0) { - if (std::numeric_limits<Float>::digits + exp > int_bits) { - // The value will overflow the Int - return false; - } - int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out); - int digits_to_zero_pad = precision; - if (mode == FormatStyle::Precision) { - *exp_out = digits_printed - 1; - digits_to_zero_pad -= digits_printed - 1; - if (RemoveExtraPrecision(-digits_to_zero_pad, false, out, exp_out)) { - return true; - } - } - for (; digits_to_zero_pad-- > 0;) out->push_back('0'); - return true; - } - - exp = -exp; - // We need at least 4 empty bits for the next decimal digit. - // We will multiply by 10. - if (exp > int_bits - 4) return false; - - const Int mask = (Int{1} << exp) - 1; - - // Print the integral part first. - int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out); - int_mantissa &= mask; - - int fractional_count = precision; - if (mode == FormatStyle::Precision) { - if (digits_printed == 0) { - // Find the first non-zero digit, when in Precision mode. - *exp_out = 0; - if (int_mantissa) { - while (int_mantissa <= mask) { - int_mantissa *= 10; - --*exp_out; - } - } - out->push_front(static_cast<char>(int_mantissa >> exp) + '0'); - out->push_back('.'); - int_mantissa &= mask; - } else { - // We already have a digit, and a '.' - *exp_out = digits_printed - 1; - fractional_count -= *exp_out; - if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out, - exp_out)) { - // If we had enough digits, return right away. - // The code below will try to round again otherwise. - return true; - } - } - } - - auto get_next_digit = [&] { - int_mantissa *= 10; - int digit = static_cast<int>(int_mantissa >> exp); - int_mantissa &= mask; - return digit; - }; - - // Print fractional_count more digits, if available. - for (; fractional_count > 0; --fractional_count) { - out->push_back(get_next_digit() + '0'); - } - - int next_digit = get_next_digit(); - if (next_digit > 5 || - (next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) { - RoundUp<mode>(out, exp_out); - } - - return true; -} - -template <FormatStyle mode, typename Float> -bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out, - int *exp) { - if (precision > kMaxFixedPrecision) return false; - - // Try with uint64_t. - if (CanFitMantissa<Float, std::uint64_t>() && - FloatToBufferImpl<std::uint64_t, Float, mode>( - static_cast<std::uint64_t>(decomposed.mantissa), - static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp)) - return true; - -#if defined(ABSL_HAVE_INTRINSIC_INT128) - // If that is not enough, try with __uint128_t. - return CanFitMantissa<Float, __uint128_t>() && - FloatToBufferImpl<__uint128_t, Float, mode>( - static_cast<__uint128_t>(decomposed.mantissa), - static_cast<__uint128_t>(decomposed.exponent), precision, out, - exp); -#endif - return false; -} - -void WriteBufferToSink(char sign_char, absl::string_view str, - const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - int left_spaces = 0, zeros = 0, right_spaces = 0; - int missing_chars = - conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) - - static_cast<int>(sign_char != 0), - 0) - : 0; - if (conv.has_left_flag()) { - right_spaces = missing_chars; - } else if (conv.has_zero_flag()) { - zeros = missing_chars; - } else { - left_spaces = missing_chars; - } - - sink->Append(left_spaces, ' '); - if (sign_char != '\0') sink->Append(1, sign_char); - sink->Append(zeros, '0'); - sink->Append(str); - sink->Append(right_spaces, ' '); -} - -template <typename Float> -bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - // Print the sign or the sign column. - Float abs_v = v; - char sign_char = 0; - if (std::signbit(abs_v)) { - sign_char = '-'; - abs_v = -abs_v; - } else if (conv.has_show_pos_flag()) { - sign_char = '+'; - } else if (conv.has_sign_col_flag()) { - sign_char = ' '; - } - - // Print nan/inf. - if (ConvertNonNumericFloats(sign_char, abs_v, conv, sink)) { - return true; - } - - int precision = conv.precision() < 0 ? 6 : conv.precision(); - - int exp = 0; - - auto decomposed = Decompose(abs_v); - - Buffer buffer; - - FormatConversionChar c = conv.conversion_char(); - - 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); - } - exp = 0; - } - if (!conv.has_alt_flag()) { - while (buffer.back() == '0') buffer.pop_back(); - if (buffer.back() == '.') buffer.pop_back(); - } - if (exp) { - PrintExponent( - exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e', - &buffer); - } - } else if (c == FormatConversionCharInternal::a || - c == FormatConversionCharInternal::A) { - bool uppercase = (c == FormatConversionCharInternal::A); - FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa, - decomposed.exponent, uppercase, {sign_char, precision, conv, sink}); - return true; - } else { - return false; - } - - WriteBufferToSink(sign_char, - absl::string_view(buffer.begin, buffer.end - buffer.begin), - conv, sink); - - return true; -} - -} // namespace - -bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - if (std::numeric_limits<long double>::digits == - 2 * std::numeric_limits<double>::digits) { - // 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, - FormatSinkImpl *sink) { - return FloatToSink(static_cast<double>(v), conv, sink); -} - -bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink) { - return FloatToSink(v, conv, sink); -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/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 deleted file mode 100644 index 71100e714257..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.h +++ /dev/null @@ -1,37 +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_STR_FORMAT_FLOAT_CONVERSION_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_ - -#include "absl/strings/internal/str_format/extension.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink); - -bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink); - -bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, - FormatSinkImpl *sink); - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/output.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/output.cc deleted file mode 100644 index c4b24706132c..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/output.cc +++ /dev/null @@ -1,72 +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/strings/internal/str_format/output.h" - -#include <errno.h> -#include <cstring> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -namespace { -struct ClearErrnoGuard { - ClearErrnoGuard() : old_value(errno) { errno = 0; } - ~ClearErrnoGuard() { - if (!errno) errno = old_value; - } - int old_value; -}; -} // namespace - -void BufferRawSink::Write(string_view v) { - size_t to_write = std::min(v.size(), size_); - std::memcpy(buffer_, v.data(), to_write); - buffer_ += to_write; - size_ -= to_write; - total_written_ += v.size(); -} - -void FILERawSink::Write(string_view v) { - while (!v.empty() && !error_) { - // Reset errno to zero in case the libc implementation doesn't set errno - // when a failure occurs. - ClearErrnoGuard guard; - - if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) { - // Some progress was made. - count_ += result; - v.remove_prefix(result); - } else { - if (errno == EINTR) { - continue; - } else if (errno) { - error_ = errno; - } else if (std::ferror(output_)) { - // Non-POSIX compliant libc implementations may not set errno, so we - // have check the streams error indicator. - error_ = EBADF; - } else { - // We're likely on a non-POSIX system that encountered EINTR but had no - // way of reporting it. - continue; - } - } - } -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 8030dae00f4f..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/output.h +++ /dev/null @@ -1,96 +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. -// -// Output extension hooks for the Format library. -// `internal::InvokeFlush` calls the appropriate flush function for the -// specified output argument. -// `BufferRawSink` is a simple output sink for a char buffer. Used by SnprintF. -// `FILERawSink` is a std::FILE* based sink. Used by PrintF and FprintF. - -#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_ - -#include <cstdio> -#include <ostream> -#include <string> - -#include "absl/base/port.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -// RawSink implementation that writes into a char* buffer. -// It will not overflow the buffer, but will keep the total count of chars -// that would have been written. -class BufferRawSink { - public: - BufferRawSink(char* buffer, size_t size) : buffer_(buffer), size_(size) {} - - size_t total_written() const { return total_written_; } - void Write(string_view v); - - private: - char* buffer_; - size_t size_; - size_t total_written_ = 0; -}; - -// RawSink implementation that writes into a FILE*. -// It keeps track of the total number of bytes written and any error encountered -// during the writes. -class FILERawSink { - public: - explicit FILERawSink(std::FILE* output) : output_(output) {} - - void Write(string_view v); - - size_t count() const { return count_; } - int error() const { return error_; } - - private: - std::FILE* output_; - int error_ = 0; - size_t count_ = 0; -}; - -// Provide RawSink integration with common types from the STL. -inline void AbslFormatFlush(std::string* out, string_view s) { - out->append(s.data(), s.size()); -} -inline void AbslFormatFlush(std::ostream* out, string_view s) { - out->write(s.data(), s.size()); -} - -inline void AbslFormatFlush(FILERawSink* sink, string_view v) { - sink->Write(v); -} - -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); -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_ 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 deleted file mode 100644 index ce2e91a0bbe8..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/output_test.cc +++ /dev/null @@ -1,79 +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/strings/internal/str_format/output.h" - -#include <sstream> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/cord.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -TEST(InvokeFlush, String) { - std::string str = "ABC"; - str_format_internal::InvokeFlush(&str, "DEF"); - EXPECT_EQ(str, "ABCDEF"); -} - -TEST(InvokeFlush, Stream) { - std::stringstream str; - str << "ABC"; - str_format_internal::InvokeFlush(&str, "DEF"); - 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]; - { - std::fill(std::begin(buf), std::end(buf), 'x'); - str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1); - str_format_internal::InvokeFlush(&bufsink, "Hello World237"); - EXPECT_EQ(std::string(buf, sizeof(buf)), "Hello World237xx"); - } - { - std::fill(std::begin(buf), std::end(buf), 'x'); - str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1); - str_format_internal::InvokeFlush(&bufsink, "Hello World237237"); - EXPECT_EQ(std::string(buf, sizeof(buf)), "Hello World2372x"); - } - { - std::fill(std::begin(buf), std::end(buf), 'x'); - str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1); - str_format_internal::InvokeFlush(&bufsink, "Hello World"); - str_format_internal::InvokeFlush(&bufsink, "237"); - EXPECT_EQ(std::string(buf, sizeof(buf)), "Hello World237xx"); - } - { - std::fill(std::begin(buf), std::end(buf), 'x'); - str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1); - str_format_internal::InvokeFlush(&bufsink, "Hello World"); - str_format_internal::InvokeFlush(&bufsink, "237237"); - EXPECT_EQ(std::string(buf, sizeof(buf)), "Hello World2372x"); - } -} - -} // 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 deleted file mode 100644 index f308d0235120..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.cc +++ /dev/null @@ -1,350 +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/str_format/parser.h" - -#include <assert.h> -#include <string.h> -#include <wchar.h> -#include <cctype> -#include <cstdint> - -#include <algorithm> -#include <initializer_list> -#include <limits> -#include <ostream> -#include <string> -#include <unordered_set> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -using CC = FormatConversionCharInternal; -using LM = LengthMod; - -ABSL_CONST_INIT const ConvTag kTags[256] = { - {}, {}, {}, {}, {}, {}, {}, {}, // 00-07 - {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f - {}, {}, {}, {}, {}, {}, {}, {}, // 10-17 - {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f - {}, {}, {}, {}, {}, {}, {}, {}, // 20-27 - {}, {}, {}, {}, {}, {}, {}, {}, // 28-2f - {}, {}, {}, {}, {}, {}, {}, {}, // 30-37 - {}, {}, {}, {}, {}, {}, {}, {}, // 38-3f - {}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG - {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO - {}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW - CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_ - {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg - LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno - CC::p, LM::q, {}, CC::s, LM::t, CC::u, {}, {}, // pqrstuvw - CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}! - {}, {}, {}, {}, {}, {}, {}, {}, // 80-87 - {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f - {}, {}, {}, {}, {}, {}, {}, {}, // 90-97 - {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f - {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7 - {}, {}, {}, {}, {}, {}, {}, {}, // a8-af - {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7 - {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf - {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7 - {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf - {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7 - {}, {}, {}, {}, {}, {}, {}, {}, // d8-df - {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7 - {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef - {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7 - {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff -}; - -namespace { - -bool CheckFastPathSetting(const UnboundConversion& conv) { - 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.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 should_be_basic == conv.flags.basic; -} - -template <bool is_positional> -const char *ConsumeConversion(const char *pos, const char *const end, - UnboundConversion *conv, int *next_arg) { - const char* const original_pos = pos; - char c; - // Read the next char into `c` and update `pos`. Returns false if there are - // no more chars to read. -#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \ - do { \ - if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \ - c = *pos++; \ - } while (0) - - const auto parse_digits = [&] { - int digits = c - '0'; - // We do not want to overflow `digits` so we consume at most digits10 - // digits. If there are more digits the parsing will fail later on when the - // digit doesn't match the expected characters. - int num_digits = std::numeric_limits<int>::digits10; - for (;;) { - if (ABSL_PREDICT_FALSE(pos == end)) break; - c = *pos++; - if (!std::isdigit(c)) break; - --num_digits; - if (ABSL_PREDICT_FALSE(!num_digits)) break; - digits = 10 * digits + c - '0'; - } - return digits; - }; - - if (is_positional) { - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr; - conv->arg_position = parse_digits(); - assert(conv->arg_position > 0); - if (ABSL_PREDICT_FALSE(c != '$')) return nullptr; - } - - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - - // We should start with the basic flag on. - assert(conv->flags.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') { - 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') { - int maybe_width = parse_digits(); - if (!is_positional && c == '$') { - 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->width.set_value(maybe_width); - } else if (c == '*') { - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (is_positional) { - if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr; - conv->width.set_from_arg(parse_digits()); - if (ABSL_PREDICT_FALSE(c != '$')) return nullptr; - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - } else { - conv->width.set_from_arg(++*next_arg); - } - } - } - - if (c == '.') { - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (std::isdigit(c)) { - conv->precision.set_value(parse_digits()); - } else if (c == '*') { - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (is_positional) { - if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr; - conv->precision.set_from_arg(parse_digits()); - if (c != '$') return nullptr; - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - } else { - conv->precision.set_from_arg(++*next_arg); - } - } else { - conv->precision.set_value(0); - } - } - } - - auto tag = GetTagForChar(c); - - if (ABSL_PREDICT_FALSE(!tag.is_conv())) { - if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr; - - // It is a length modifier. - using str_format_internal::LengthMod; - LengthMod length_mod = tag.as_length(); - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (c == 'h' && length_mod == LengthMod::h) { - conv->length_mod = LengthMod::hh; - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - } else if (c == 'l' && length_mod == LengthMod::l) { - conv->length_mod = LengthMod::ll; - ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - } else { - conv->length_mod = length_mod; - } - tag = GetTagForChar(c); - if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr; - } - - assert(CheckFastPathSetting(*conv)); - (void)(&CheckFastPathSetting); - - conv->conv = tag.as_conv(); - if (!is_positional) conv->arg_position = ++*next_arg; - return pos; -} - -} // namespace - -std::string LengthModToString(LengthMod v) { - switch (v) { - case LengthMod::h: - return "h"; - case LengthMod::hh: - return "hh"; - case LengthMod::l: - return "l"; - case LengthMod::ll: - return "ll"; - case LengthMod::L: - return "L"; - case LengthMod::j: - return "j"; - case LengthMod::z: - return "z"; - case LengthMod::t: - return "t"; - case LengthMod::q: - return "q"; - case LengthMod::none: - return ""; - } - return ""; -} - -const char *ConsumeUnboundConversion(const char *p, const char *end, - UnboundConversion *conv, int *next_arg) { - if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg); - return ConsumeConversion<false>(p, end, conv, next_arg); -} - -struct ParsedFormatBase::ParsedFormatConsumer { - explicit ParsedFormatConsumer(ParsedFormatBase *parsedformat) - : parsed(parsedformat), data_pos(parsedformat->data_.get()) {} - - bool Append(string_view s) { - if (s.empty()) return true; - - size_t text_end = AppendText(s); - - if (!parsed->items_.empty() && !parsed->items_.back().is_conversion) { - // Let's extend the existing text run. - parsed->items_.back().text_end = text_end; - } else { - // Let's make a new text run. - parsed->items_.push_back({false, text_end, {}}); - } - return true; - } - - bool ConvertOne(const UnboundConversion &conv, string_view s) { - size_t text_end = AppendText(s); - parsed->items_.push_back({true, text_end, conv}); - return true; - } - - size_t AppendText(string_view s) { - memcpy(data_pos, s.data(), s.size()); - data_pos += s.size(); - return static_cast<size_t>(data_pos - parsed->data_.get()); - } - - ParsedFormatBase *parsed; - char* data_pos; -}; - -ParsedFormatBase::ParsedFormatBase( - string_view format, bool allow_ignored, - std::initializer_list<FormatConversionCharSet> convs) - : data_(format.empty() ? nullptr : new char[format.size()]) { - has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) || - !MatchesConversions(allow_ignored, convs); -} - -bool ParsedFormatBase::MatchesConversions( - bool allow_ignored, - std::initializer_list<FormatConversionCharSet> convs) const { - std::unordered_set<int> used; - auto add_if_valid_conv = [&](int pos, char c) { - if (static_cast<size_t>(pos) > convs.size() || - !Contains(convs.begin()[pos - 1], c)) - return false; - used.insert(pos); - return true; - }; - for (const ConversionItem &item : items_) { - if (!item.is_conversion) continue; - auto &conv = item.conv; - if (conv.precision.is_from_arg() && - !add_if_valid_conv(conv.precision.get_from_arg(), '*')) - return false; - if (conv.width.is_from_arg() && - !add_if_valid_conv(conv.width.get_from_arg(), '*')) - return false; - if (!add_if_valid_conv(conv.arg_position, - FormatConversionCharToChar(conv.conv))) - return false; - } - return used.size() == convs.size() || allow_ignored; -} - -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 6504dd3ddc20..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.h +++ /dev/null @@ -1,349 +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_STR_FORMAT_PARSER_H_ -#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ - -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> - -#include <cassert> -#include <cstdint> -#include <initializer_list> -#include <iosfwd> -#include <iterator> -#include <memory> -#include <string> -#include <vector> - -#include "absl/strings/internal/str_format/checker.h" -#include "absl/strings/internal/str_format/extension.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none }; - -std::string LengthModToString(LengthMod v); - -// The analyzed properties of a single specified conversion. -struct UnboundConversion { - UnboundConversion() - : flags() /* This is required to zero all the fields of flags. */ { - flags.basic = true; - } - - class InputValue { - public: - void set_value(int value) { - assert(value >= 0); - value_ = value; - } - int value() const { return value_; } - - // Marks the value as "from arg". aka the '*' format. - // Requires `value >= 1`. - // When set, is_from_arg() return true and get_from_arg() returns the - // original value. - // `value()`'s return value is unspecfied in this state. - void set_from_arg(int value) { - assert(value > 0); - value_ = -value - 1; - } - bool is_from_arg() const { return value_ < -1; } - int get_from_arg() const { - assert(is_from_arg()); - return -value_ - 1; - } - - private: - int value_ = -1; - }; - - // No need to initialize. It will always be set in the parser. - int arg_position; - - InputValue width; - InputValue precision; - - Flags flags; - LengthMod length_mod = LengthMod::none; - FormatConversionChar conv = FormatConversionCharInternal::kNone; -}; - -// Consume conversion spec prefix (not including '%') of [p, end) if valid. -// Examples of valid specs would be e.g.: "s", "d", "-12.6f". -// If valid, it returns the first character following the conversion spec, -// and the spec part is broken down and returned in 'conv'. -// If invalid, returns nullptr. -const char* ConsumeUnboundConversion(const char* p, const char* end, - UnboundConversion* conv, int* next_arg); - -// Helper tag class for the table below. -// It allows fast `char -> ConversionChar/LengthMod` checking and -// conversions. -class ConvTag { - public: - constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT - : tag_(static_cast<int8_t>(conversion_char)) {} - // We invert the length modifiers to make them negative so that we can easily - // test for them. - constexpr ConvTag(LengthMod length_mod) // NOLINT - : tag_(~static_cast<std::int8_t>(length_mod)) {} - // Everything else is -128, which is negative to make is_conv() simpler. - constexpr ConvTag() : tag_(-128) {} - - bool is_conv() const { return tag_ >= 0; } - bool is_length() const { return tag_ < 0 && tag_ != -128; } - FormatConversionChar as_conv() const { - assert(is_conv()); - return static_cast<FormatConversionChar>(tag_); - } - LengthMod as_length() const { - assert(is_length()); - return static_cast<LengthMod>(~tag_); - } - - private: - std::int8_t tag_; -}; - -extern const ConvTag kTags[256]; -// Keep a single table for all the conversion chars and length modifiers. -inline ConvTag GetTagForChar(char c) { - return kTags[static_cast<unsigned char>(c)]; -} - -// Parse the format string provided in 'src' and pass the identified items into -// 'consumer'. -// Text runs will be passed by calling -// Consumer::Append(string_view); -// ConversionItems will be passed by calling -// Consumer::ConvertOne(UnboundConversion, string_view); -// In the case of ConvertOne, the string_view that is passed is the -// portion of the format string corresponding to the conversion, not including -// the leading %. On success, it returns true. On failure, it stops and returns -// false. -template <typename Consumer> -bool ParseFormatString(string_view src, Consumer consumer) { - int next_arg = 0; - const char* p = src.data(); - const char* const end = p + src.size(); - while (p != end) { - const char* percent = static_cast<const char*>(memchr(p, '%', end - p)); - if (!percent) { - // We found the last substring. - return consumer.Append(string_view(p, end - p)); - } - // We found a percent, so push the text run then process the percent. - if (ABSL_PREDICT_FALSE(!consumer.Append(string_view(p, percent - p)))) { - return false; - } - if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false; - - auto tag = GetTagForChar(percent[1]); - if (tag.is_conv()) { - if (ABSL_PREDICT_FALSE(next_arg < 0)) { - // This indicates an error in the format string. - // The only way to get `next_arg < 0` here is to have a positional - // argument first which sets next_arg to -1 and then a non-positional - // argument. - return false; - } - p = percent + 2; - - // Keep this case separate from the one below. - // ConvertOne is more efficient when the compiler can see that the `basic` - // flag is set. - UnboundConversion conv; - conv.conv = tag.as_conv(); - conv.arg_position = ++next_arg; - if (ABSL_PREDICT_FALSE( - !consumer.ConvertOne(conv, string_view(percent + 1, 1)))) { - return false; - } - } else if (percent[1] != '%') { - UnboundConversion conv; - p = ConsumeUnboundConversion(percent + 1, end, &conv, &next_arg); - if (ABSL_PREDICT_FALSE(p == nullptr)) return false; - if (ABSL_PREDICT_FALSE(!consumer.ConvertOne( - conv, string_view(percent + 1, p - (percent + 1))))) { - return false; - } - } else { - if (ABSL_PREDICT_FALSE(!consumer.Append("%"))) return false; - p = percent + 2; - continue; - } - } - return true; -} - -// Always returns true, or fails to compile in a constexpr context if s does not -// point to a constexpr char array. -constexpr bool EnsureConstexpr(string_view s) { - return s.empty() || s[0] == s[0]; -} - -class ParsedFormatBase { - public: - explicit ParsedFormatBase( - string_view format, bool allow_ignored, - std::initializer_list<FormatConversionCharSet> convs); - - ParsedFormatBase(const ParsedFormatBase& other) { *this = other; } - - ParsedFormatBase(ParsedFormatBase&& other) { *this = std::move(other); } - - ParsedFormatBase& operator=(const ParsedFormatBase& other) { - if (this == &other) return *this; - has_error_ = other.has_error_; - items_ = other.items_; - size_t text_size = items_.empty() ? 0 : items_.back().text_end; - data_.reset(new char[text_size]); - memcpy(data_.get(), other.data_.get(), text_size); - return *this; - } - - ParsedFormatBase& operator=(ParsedFormatBase&& other) { - if (this == &other) return *this; - has_error_ = other.has_error_; - data_ = std::move(other.data_); - items_ = std::move(other.items_); - // Reset the vector to make sure the invariants hold. - other.items_.clear(); - return *this; - } - - template <typename Consumer> - bool ProcessFormat(Consumer consumer) const { - const char* const base = data_.get(); - string_view text(base, 0); - for (const auto& item : items_) { - const char* const end = text.data() + text.size(); - text = string_view(end, (base + item.text_end) - end); - if (item.is_conversion) { - if (!consumer.ConvertOne(item.conv, text)) return false; - } else { - if (!consumer.Append(text)) return false; - } - } - return !has_error_; - } - - bool has_error() const { return has_error_; } - - 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; - - struct ParsedFormatConsumer; - - struct ConversionItem { - bool is_conversion; - // Points to the past-the-end location of this element in the data_ array. - size_t text_end; - UnboundConversion conv; - }; - - bool has_error_; - std::unique_ptr<char[]> data_; - std::vector<ConversionItem> items_; -}; - - -// A value type representing a preparsed format. These can be created, copied -// around, and reused to speed up formatting loops. -// The user must specify through the template arguments the conversion -// characters used in the format. This will be checked at compile time. -// -// This class uses Conv enum values to specify each argument. -// This allows for more flexibility as you can specify multiple possible -// conversion characters for each argument. -// ParsedFormat<char...> is a simplified alias for when the user only -// needs to specify a single conversion character for each argument. -// -// Example: -// // Extended format supports multiple characters per argument: -// using MyFormat = ExtendedParsedFormat<Conv::d | Conv::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); -// -// This class also supports runtime format checking with the ::New() and -// ::NewAllowIgnored() factory functions. -// 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> -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."), - enable_if(str_format_internal::ValidFormatImpl<C...>(format), - "Format specified does not match the template arguments."))) -#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - : ExtendedParsedFormat(format, false) { - } - - // ExtendedParsedFormat factory function. - // The user still has to specify the conversion characters, but they will not - // be checked at compile time. Instead, it will be checked at runtime. - // This delays the checking to runtime, but allows the user to pass - // dynamically sourced formats. - // It returns NULL if the format does not match the conversion characters. - // The user is responsible for checking the return value before using it. - // - // The 'New' variant will check that all the specified arguments are being - // consumed by the format and return NULL if any argument is being ignored. - // The 'NewAllowIgnored' variant will not verify this and will allow formats - // that ignore arguments. - static std::unique_ptr<ExtendedParsedFormat> New(string_view format) { - return New(format, false); - } - static std::unique_ptr<ExtendedParsedFormat> NewAllowIgnored( - string_view format) { - return New(format, true); - } - - private: - static std::unique_ptr<ExtendedParsedFormat> New(string_view format, - bool allow_ignored) { - std::unique_ptr<ExtendedParsedFormat> conv( - new ExtendedParsedFormat(format, allow_ignored)); - if (conv->has_error()) return nullptr; - return conv; - } - - ExtendedParsedFormat(string_view s, bool allow_ignored) - : ParsedFormatBase(s, allow_ignored, {C...}) {} -}; -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ diff --git a/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 deleted file mode 100644 index a5fa1c79aaf4..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc +++ /dev/null @@ -1,427 +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/str_format/parser.h" - -#include <string.h> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -namespace { - -using testing::Pair; - -TEST(LengthModTest, Names) { - struct Expectation { - int line; - LengthMod mod; - const char *name; - }; - const Expectation kExpect[] = { - {__LINE__, LengthMod::none, "" }, - {__LINE__, LengthMod::h, "h" }, - {__LINE__, LengthMod::hh, "hh"}, - {__LINE__, LengthMod::l, "l" }, - {__LINE__, LengthMod::ll, "ll"}, - {__LINE__, LengthMod::L, "L" }, - {__LINE__, LengthMod::j, "j" }, - {__LINE__, LengthMod::z, "z" }, - {__LINE__, LengthMod::t, "t" }, - {__LINE__, LengthMod::q, "q" }, - }; - EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10); - for (auto e : kExpect) { - SCOPED_TRACE(e.line); - EXPECT_EQ(e.name, LengthModToString(e.mod)); - } -} - -TEST(ConversionCharTest, Names) { - struct Expectation { - FormatConversionChar id; - char name; - }; - // clang-format off - const Expectation kExpect[] = { -#define X(c) {FormatConversionCharInternal::c, #c[0]} - X(c), X(s), // text - X(d), X(i), X(o), X(u), X(x), X(X), // int - X(f), X(F), X(e), X(E), X(g), X(G), X(a), X(A), // float - X(n), X(p), // misc -#undef X - {FormatConversionCharInternal::kNone, '\0'}, - }; - // clang-format on - for (auto e : kExpect) { - SCOPED_TRACE(e.name); - FormatConversionChar v = e.id; - EXPECT_EQ(e.name, FormatConversionCharToChar(v)); - } -} - -class ConsumeUnboundConversionTest : public ::testing::Test { - public: - std::pair<string_view, string_view> Consume(string_view src) { - int next = 0; - o = UnboundConversion(); // refresh - const char* p = ConsumeUnboundConversion( - src.data(), src.data() + src.size(), &o, &next); - if (!p) return {{}, src}; - return {string_view(src.data(), p - src.data()), - string_view(p, src.data() + src.size() - p)}; - } - - bool Run(const char *fmt, bool force_positional = false) { - int next = force_positional ? -1 : 0; - o = UnboundConversion(); // refresh - return ConsumeUnboundConversion(fmt, fmt + strlen(fmt), &o, &next) == - fmt + strlen(fmt); - } - UnboundConversion o; -}; - -TEST_F(ConsumeUnboundConversionTest, ConsumeSpecification) { - struct Expectation { - int line; - string_view src; - string_view out; - string_view src_post; - }; - const Expectation kExpect[] = { - {__LINE__, "", "", "" }, - {__LINE__, "b", "", "b" }, // 'b' is invalid - {__LINE__, "ba", "", "ba"}, // 'b' is invalid - {__LINE__, "l", "", "l" }, // just length mod isn't okay - {__LINE__, "d", "d", "" }, // basic - {__LINE__, "d ", "d", " " }, // leave suffix - {__LINE__, "dd", "d", "d" }, // don't be greedy - {__LINE__, "d9", "d", "9" }, // leave non-space suffix - {__LINE__, "dzz", "d", "zz"}, // length mod as suffix - {__LINE__, "1$*2$d", "1$*2$d", "" }, // arg indexing and * allowed. - {__LINE__, "0-14.3hhd", "0-14.3hhd", ""}, // precision, width - {__LINE__, " 0-+#14.3hhd", " 0-+#14.3hhd", ""}, // flags - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.line); - EXPECT_THAT(Consume(e.src), Pair(e.out, e.src_post)); - } -} - -TEST_F(ConsumeUnboundConversionTest, BasicConversion) { - EXPECT_FALSE(Run("")); - EXPECT_FALSE(Run("z")); - - EXPECT_FALSE(Run("dd")); // no excess allowed - - EXPECT_TRUE(Run("d")); - EXPECT_EQ('d', FormatConversionCharToChar(o.conv)); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - EXPECT_EQ(1, o.arg_position); -} - -TEST_F(ConsumeUnboundConversionTest, ArgPosition) { - EXPECT_TRUE(Run("d")); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("3$d")); - EXPECT_EQ(3, o.arg_position); - EXPECT_TRUE(Run("1$d")); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("1$d", true)); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("123$d")); - EXPECT_EQ(123, o.arg_position); - EXPECT_TRUE(Run("123$d", true)); - EXPECT_EQ(123, o.arg_position); - EXPECT_TRUE(Run("10$d")); - EXPECT_EQ(10, o.arg_position); - EXPECT_TRUE(Run("10$d", true)); - EXPECT_EQ(10, o.arg_position); - - // Position can't be zero. - EXPECT_FALSE(Run("0$d")); - EXPECT_FALSE(Run("0$d", true)); - EXPECT_FALSE(Run("1$*0$d")); - EXPECT_FALSE(Run("1$.*0$d")); - - // Position can't start with a zero digit at all. That is not a 'decimal'. - EXPECT_FALSE(Run("01$p")); - EXPECT_FALSE(Run("01$p", true)); - EXPECT_FALSE(Run("1$*01$p")); - EXPECT_FALSE(Run("1$.*01$p")); -} - -TEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) { - EXPECT_TRUE(Run("14d")); - EXPECT_EQ('d', FormatConversionCharToChar(o.conv)); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - - EXPECT_TRUE(Run("14.d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run(".d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run(".5d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(5, o.precision.value()); - - EXPECT_TRUE(Run(".0d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run("14.5d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_EQ(5, o.precision.value()); - - EXPECT_TRUE(Run("*.*d")); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(1, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(2, o.precision.get_from_arg()); - EXPECT_EQ(3, o.arg_position); - - EXPECT_TRUE(Run("*d")); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(1, o.width.get_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - EXPECT_EQ(2, o.arg_position); - - EXPECT_TRUE(Run(".*d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(1, o.precision.get_from_arg()); - EXPECT_EQ(2, o.arg_position); - - // mixed implicit and explicit: didn't specify arg position. - EXPECT_FALSE(Run("*23$.*34$d")); - - EXPECT_TRUE(Run("12$*23$.*34$d")); - EXPECT_EQ(12, o.arg_position); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(23, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(34, o.precision.get_from_arg()); - - EXPECT_TRUE(Run("2$*5$.*9$d")); - EXPECT_EQ(2, o.arg_position); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(5, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(9, o.precision.get_from_arg()); - - EXPECT_FALSE(Run(".*0$d")) << "no arg 0"; - - // Large values - EXPECT_TRUE(Run("999999999.999999999d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_EQ(999999999, o.width.value()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(999999999, o.precision.value()); - - EXPECT_FALSE(Run("1000000000.999999999d")); - EXPECT_FALSE(Run("999999999.1000000000d")); - EXPECT_FALSE(Run("9999999999d")); - EXPECT_FALSE(Run(".9999999999d")); -} - -TEST_F(ConsumeUnboundConversionTest, Flags) { - static const char kAllFlags[] = "-+ #0"; - static const int kNumFlags = ABSL_ARRAYSIZE(kAllFlags) - 1; - for (int rev = 0; rev < 2; ++rev) { - for (int i = 0; i < 1 << kNumFlags; ++i) { - std::string fmt; - 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()); } - fmt += 'd'; - SCOPED_TRACE(fmt); - EXPECT_TRUE(Run(fmt.c_str())); - 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); - } - } -} - -TEST_F(ConsumeUnboundConversionTest, BasicFlag) { - // Flag is on - for (const char* fmt : {"d", "llx", "G", "1$X"}) { - SCOPED_TRACE(fmt); - EXPECT_TRUE(Run(fmt)); - 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_FALSE(o.flags.basic); - } -} - -TEST_F(ConsumeUnboundConversionTest, LengthMod) { - EXPECT_TRUE(Run("d")); - EXPECT_EQ(LengthMod::none, o.length_mod); - EXPECT_TRUE(Run("hd")); - EXPECT_EQ(LengthMod::h, o.length_mod); - EXPECT_TRUE(Run("hhd")); - EXPECT_EQ(LengthMod::hh, o.length_mod); - EXPECT_TRUE(Run("ld")); - EXPECT_EQ(LengthMod::l, o.length_mod); - EXPECT_TRUE(Run("lld")); - EXPECT_EQ(LengthMod::ll, o.length_mod); - EXPECT_TRUE(Run("Lf")); - EXPECT_EQ(LengthMod::L, o.length_mod); - EXPECT_TRUE(Run("qf")); - EXPECT_EQ(LengthMod::q, o.length_mod); - EXPECT_TRUE(Run("jd")); - EXPECT_EQ(LengthMod::j, o.length_mod); - EXPECT_TRUE(Run("zd")); - EXPECT_EQ(LengthMod::z, o.length_mod); - EXPECT_TRUE(Run("td")); - EXPECT_EQ(LengthMod::t, o.length_mod); -} - -struct SummarizeConsumer { - std::string* out; - explicit SummarizeConsumer(std::string* out) : out(out) {} - - bool Append(string_view s) { - *out += "[" + std::string(s) + "]"; - return true; - } - - bool ConvertOne(const UnboundConversion& conv, string_view s) { - *out += "{"; - *out += std::string(s); - *out += ":"; - *out += std::to_string(conv.arg_position) + "$"; - if (conv.width.is_from_arg()) { - *out += std::to_string(conv.width.get_from_arg()) + "$*"; - } - if (conv.precision.is_from_arg()) { - *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*"; - } - *out += FormatConversionCharToChar(conv.conv); - *out += "}"; - return true; - } -}; - -std::string SummarizeParsedFormat(const ParsedFormatBase& pc) { - std::string out; - if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!"; - return out; -} - -class ParsedFormatTest : public testing::Test {}; - -TEST_F(ParsedFormatTest, ValueSemantics) { - ParsedFormatBase p1({}, true, {}); // empty format - EXPECT_EQ("", SummarizeParsedFormat(p1)); - - ParsedFormatBase p2 = p1; // copy construct (empty) - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2)); - - p1 = ParsedFormatBase("hello%s", true, - {FormatConversionCharSetInternal::s}); // move assign - EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p1)); - - ParsedFormatBase p3 = p1; // copy construct (nonempty) - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p3)); - - using std::swap; - swap(p1, p2); - EXPECT_EQ("", SummarizeParsedFormat(p1)); - EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p2)); - swap(p1, p2); // undo - - p2 = p1; // copy assign - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2)); -} - -struct ExpectParse { - const char* in; - std::initializer_list<FormatConversionCharSet> conv_set; - const char* out; -}; - -TEST_F(ParsedFormatTest, Parsing) { - // Parse should be equivalent to that obtained by ConversionParseIterator. - // No need to retest the parsing edge cases here. - 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%b %d", {}, "[a]!"}, // stop after error - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.in); - EXPECT_EQ(e.out, - SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set))); - } -} - -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}"}, - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.in); - EXPECT_EQ(e.out, - SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set))); - } -} - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/str_join_internal.h b/third_party/abseil_cpp/absl/strings/internal/str_join_internal.h deleted file mode 100644 index 31dbf672f0b6..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_join_internal.h +++ /dev/null @@ -1,314 +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 declares INTERNAL parts of the Join API that are inlined/templated -// or otherwise need to be available at compile time. The main abstractions -// defined in this file are: -// -// - A handful of default Formatters -// - JoinAlgorithm() overloads -// - JoinRange() overloads -// - JoinTuple() -// -// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including -// absl/strings/str_join.h -// -// IWYU pragma: private, include "absl/strings/str_join.h" - -#ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ -#define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ - -#include <cstring> -#include <iterator> -#include <memory> -#include <string> -#include <type_traits> -#include <utility> - -#include "absl/strings/internal/ostringstream.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// -// Formatter objects -// -// The following are implementation classes for standard Formatter objects. The -// factory functions that users will call to create and use these formatters are -// defined and documented in strings/join.h. -// - -// The default formatter. Converts alpha-numeric types to strings. -struct AlphaNumFormatterImpl { - // This template is needed in order to support passing in a dereferenced - // vector<bool>::iterator - template <typename T> - void operator()(std::string* out, const T& t) const { - StrAppend(out, AlphaNum(t)); - } - - void operator()(std::string* out, const AlphaNum& t) const { - StrAppend(out, t); - } -}; - -// A type that's used to overload the JoinAlgorithm() function (defined below) -// for ranges that do not require additional formatting (e.g., a range of -// strings). - -struct NoFormatter : public AlphaNumFormatterImpl {}; - -// Formats types to strings using the << operator. -class StreamFormatterImpl { - public: - // The method isn't const because it mutates state. Making it const will - // render StreamFormatterImpl thread-hostile. - template <typename T> - void operator()(std::string* out, const T& t) { - // The stream is created lazily to avoid paying the relatively high cost - // of its construction when joining an empty range. - if (strm_) { - strm_->clear(); // clear the bad, fail and eof bits in case they were set - strm_->str(out); - } else { - strm_.reset(new strings_internal::OStringStream(out)); - } - *strm_ << t; - } - - private: - std::unique_ptr<strings_internal::OStringStream> strm_; -}; - -// Formats a std::pair<>. The 'first' member is formatted using f1_ and the -// 'second' member is formatted using f2_. sep_ is the separator. -template <typename F1, typename F2> -class PairFormatterImpl { - public: - PairFormatterImpl(F1 f1, absl::string_view sep, F2 f2) - : f1_(std::move(f1)), sep_(sep), f2_(std::move(f2)) {} - - template <typename T> - void operator()(std::string* out, const T& p) { - f1_(out, p.first); - out->append(sep_); - f2_(out, p.second); - } - - template <typename T> - void operator()(std::string* out, const T& p) const { - f1_(out, p.first); - out->append(sep_); - f2_(out, p.second); - } - - private: - F1 f1_; - std::string sep_; - F2 f2_; -}; - -// Wraps another formatter and dereferences the argument to operator() then -// passes the dereferenced argument to the wrapped formatter. This can be -// useful, for example, to join a std::vector<int*>. -template <typename Formatter> -class DereferenceFormatterImpl { - public: - DereferenceFormatterImpl() : f_() {} - explicit DereferenceFormatterImpl(Formatter&& f) - : f_(std::forward<Formatter>(f)) {} - - template <typename T> - void operator()(std::string* out, const T& t) { - f_(out, *t); - } - - template <typename T> - void operator()(std::string* out, const T& t) const { - f_(out, *t); - } - - private: - Formatter f_; -}; - -// DefaultFormatter<T> is a traits class that selects a default Formatter to use -// for the given type T. The ::Type member names the Formatter to use. This is -// used by the strings::Join() functions that do NOT take a Formatter argument, -// in which case a default Formatter must be chosen. -// -// AlphaNumFormatterImpl is the default in the base template, followed by -// specializations for other types. -template <typename ValueType> -struct DefaultFormatter { - typedef AlphaNumFormatterImpl Type; -}; -template <> -struct DefaultFormatter<const char*> { - typedef AlphaNumFormatterImpl Type; -}; -template <> -struct DefaultFormatter<char*> { - typedef AlphaNumFormatterImpl Type; -}; -template <> -struct DefaultFormatter<std::string> { - typedef NoFormatter Type; -}; -template <> -struct DefaultFormatter<absl::string_view> { - typedef NoFormatter Type; -}; -template <typename ValueType> -struct DefaultFormatter<ValueType*> { - typedef DereferenceFormatterImpl<typename DefaultFormatter<ValueType>::Type> - Type; -}; - -template <typename ValueType> -struct DefaultFormatter<std::unique_ptr<ValueType>> - : public DefaultFormatter<ValueType*> {}; - -// -// JoinAlgorithm() functions -// - -// The main joining algorithm. This simply joins the elements in the given -// iterator range, each separated by the given separator, into an output string, -// and formats each element using the provided Formatter object. -template <typename Iterator, typename Formatter> -std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s, - Formatter&& f) { - std::string result; - absl::string_view sep(""); - for (Iterator it = start; it != end; ++it) { - result.append(sep.data(), sep.size()); - f(&result, *it); - sep = s; - } - return result; -} - -// A joining algorithm that's optimized for a forward iterator range of -// string-like objects that do not need any additional formatting. This is to -// optimize the common case of joining, say, a std::vector<string> or a -// std::vector<absl::string_view>. -// -// This is an overload of the previous JoinAlgorithm() function. Here the -// Formatter argument is of type NoFormatter. Since NoFormatter is an internal -// type, this overload is only invoked when strings::Join() is called with a -// range of string-like objects (e.g., std::string, absl::string_view), and an -// explicit Formatter argument was NOT specified. -// -// The optimization is that the needed space will be reserved in the output -// string to avoid the need to resize while appending. To do this, the iterator -// range will be traversed twice: once to calculate the total needed size, and -// then again to copy the elements and delimiters to the output string. -template <typename Iterator, - typename = typename std::enable_if<std::is_convertible< - typename std::iterator_traits<Iterator>::iterator_category, - std::forward_iterator_tag>::value>::type> -std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s, - NoFormatter) { - std::string result; - if (start != end) { - // Sums size - size_t result_size = start->size(); - for (Iterator it = start; ++it != end;) { - result_size += s.size(); - result_size += it->size(); - } - - if (result_size > 0) { - STLStringResizeUninitialized(&result, result_size); - - // Joins strings - char* result_buf = &*result.begin(); - memcpy(result_buf, start->data(), start->size()); - result_buf += start->size(); - for (Iterator it = start; ++it != end;) { - memcpy(result_buf, s.data(), s.size()); - result_buf += s.size(); - memcpy(result_buf, it->data(), it->size()); - result_buf += it->size(); - } - } - } - - return result; -} - -// JoinTupleLoop implements a loop over the elements of a std::tuple, which -// are heterogeneous. The primary template matches the tuple interior case. It -// continues the iteration after appending a separator (for nonzero indices) -// and formatting an element of the tuple. The specialization for the I=N case -// matches the end-of-tuple, and terminates the iteration. -template <size_t I, size_t N> -struct JoinTupleLoop { - template <typename Tup, typename Formatter> - void operator()(std::string* out, const Tup& tup, absl::string_view sep, - Formatter&& fmt) { - if (I > 0) out->append(sep.data(), sep.size()); - fmt(out, std::get<I>(tup)); - JoinTupleLoop<I + 1, N>()(out, tup, sep, fmt); - } -}; -template <size_t N> -struct JoinTupleLoop<N, N> { - template <typename Tup, typename Formatter> - void operator()(std::string*, const Tup&, absl::string_view, Formatter&&) {} -}; - -template <typename... T, typename Formatter> -std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep, - Formatter&& fmt) { - std::string result; - JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt); - return result; -} - -template <typename Iterator> -std::string JoinRange(Iterator first, Iterator last, - absl::string_view separator) { - // No formatter was explicitly given, so a default must be chosen. - typedef typename std::iterator_traits<Iterator>::value_type ValueType; - typedef typename DefaultFormatter<ValueType>::Type Formatter; - return JoinAlgorithm(first, last, separator, Formatter()); -} - -template <typename Range, typename Formatter> -std::string JoinRange(const Range& range, absl::string_view separator, - Formatter&& fmt) { - using std::begin; - using std::end; - return JoinAlgorithm(begin(range), end(range), separator, fmt); -} - -template <typename Range> -std::string JoinRange(const Range& range, absl::string_view separator) { - using std::begin; - using std::end; - return JoinRange(begin(range), end(range), separator); -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ 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 deleted file mode 100644 index a2f41c153131..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_split_internal.h +++ /dev/null @@ -1,430 +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 declares INTERNAL parts of the Split API that are inline/templated -// or otherwise need to be available at compile time. The main abstractions -// defined in here are -// -// - ConvertibleToStringView -// - SplitIterator<> -// - Splitter<> -// -// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including -// absl/strings/str_split.h. -// -// IWYU pragma: private, include "absl/strings/str_split.h" - -#ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ -#define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ - -#include <array> -#include <initializer_list> -#include <iterator> -#include <map> -#include <type_traits> -#include <utility> -#include <vector> - -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -#ifdef _GLIBCXX_DEBUG -#include "absl/strings/internal/stl_type_traits.h" -#endif // _GLIBCXX_DEBUG - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// This class is implicitly constructible from everything that absl::string_view -// is implicitly constructible from, except for rvalue strings. This means it -// can be used as a function parameter in places where passing a temporary -// string might cause memory lifetime issues. -class ConvertibleToStringView { - public: - ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit) - : value_(s) {} - ConvertibleToStringView(char* s) : value_(s) {} // NOLINT(runtime/explicit) - ConvertibleToStringView(absl::string_view s) // NOLINT(runtime/explicit) - : value_(s) {} - ConvertibleToStringView(const std::string& s) // NOLINT(runtime/explicit) - : value_(s) {} - - // Matches rvalue strings and moves their data to a member. - ConvertibleToStringView(std::string&& s) = delete; - ConvertibleToStringView(const std::string&& s) = delete; - - absl::string_view value() const { return value_; } - - private: - absl::string_view value_; -}; - -// An iterator that enumerates the parts of a string from a Splitter. The text -// to be split, the Delimiter, and the Predicate are all taken from the given -// Splitter object. Iterators may only be compared if they refer to the same -// Splitter instance. -// -// This class is NOT part of the public splitting API. -template <typename Splitter> -class SplitIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = absl::string_view; - using difference_type = ptrdiff_t; - using pointer = const value_type*; - using reference = const value_type&; - - enum State { kInitState, kLastState, kEndState }; - SplitIterator(State state, const Splitter* splitter) - : pos_(0), - state_(state), - splitter_(splitter), - delimiter_(splitter->delimiter()), - predicate_(splitter->predicate()) { - // Hack to maintain backward compatibility. This one block makes it so an - // empty absl::string_view whose .data() happens to be nullptr behaves - // *differently* from an otherwise empty absl::string_view whose .data() is - // not nullptr. This is an undesirable difference in general, but this - // behavior is maintained to avoid breaking existing code that happens to - // depend on this old behavior/bug. Perhaps it will be fixed one day. The - // difference in behavior is as follows: - // Split(absl::string_view(""), '-'); // {""} - // Split(absl::string_view(), '-'); // {} - if (splitter_->text().data() == nullptr) { - state_ = kEndState; - pos_ = splitter_->text().size(); - return; - } - - if (state_ == kEndState) { - pos_ = splitter_->text().size(); - } else { - ++(*this); - } - } - - bool at_end() const { return state_ == kEndState; } - - reference operator*() const { return curr_; } - pointer operator->() const { return &curr_; } - - SplitIterator& operator++() { - do { - if (state_ == kLastState) { - state_ = kEndState; - return *this; - } - const absl::string_view text = splitter_->text(); - const absl::string_view d = delimiter_.Find(text, pos_); - if (d.data() == text.data() + text.size()) state_ = kLastState; - curr_ = text.substr(pos_, d.data() - (text.data() + pos_)); - pos_ += curr_.size() + d.size(); - } while (!predicate_(curr_)); - return *this; - } - - SplitIterator operator++(int) { - SplitIterator old(*this); - ++(*this); - return old; - } - - friend bool operator==(const SplitIterator& a, const SplitIterator& b) { - return a.state_ == b.state_ && a.pos_ == b.pos_; - } - - friend bool operator!=(const SplitIterator& a, const SplitIterator& b) { - return !(a == b); - } - - private: - size_t pos_; - State state_; - absl::string_view curr_; - const Splitter* splitter_; - typename Splitter::DelimiterType delimiter_; - typename Splitter::PredicateType predicate_; -}; - -// HasMappedType<T>::value is true iff there exists a type T::mapped_type. -template <typename T, typename = void> -struct HasMappedType : std::false_type {}; -template <typename T> -struct HasMappedType<T, absl::void_t<typename T::mapped_type>> - : std::true_type {}; - -// HasValueType<T>::value is true iff there exists a type T::value_type. -template <typename T, typename = void> -struct HasValueType : std::false_type {}; -template <typename T> -struct HasValueType<T, absl::void_t<typename T::value_type>> : std::true_type { -}; - -// HasConstIterator<T>::value is true iff there exists a type T::const_iterator. -template <typename T, typename = void> -struct HasConstIterator : std::false_type {}; -template <typename T> -struct HasConstIterator<T, absl::void_t<typename T::const_iterator>> - : 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 -template <typename T> -std::true_type IsInitializerListDispatch(std::initializer_list<T>*); -template <typename T> -struct IsInitializerList - : decltype(IsInitializerListDispatch(static_cast<T*>(nullptr))) {}; - -// A SplitterIsConvertibleTo<C>::type alias exists iff the specified condition -// is true for type 'C'. -// -// Restricts conversion to container-like types (by testing for the presence of -// a const_iterator member type) and also to disable conversion to an -// std::initializer_list (which also has a const_iterator). Otherwise, code -// compiled in C++11 will get an error due to ambiguous conversion paths (in -// C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T> -// or an std::initializer_list<T>). - -template <typename C, bool has_value_type, bool has_mapped_type> -struct SplitterIsConvertibleToImpl : std::false_type {}; - -template <typename C> -struct SplitterIsConvertibleToImpl<C, true, false> - : std::is_constructible<typename C::value_type, absl::string_view> {}; - -template <typename C> -struct SplitterIsConvertibleToImpl<C, true, true> - : absl::conjunction< - std::is_constructible<typename C::key_type, absl::string_view>, - std::is_constructible<typename C::mapped_type, absl::string_view>> {}; - -template <typename C> -struct SplitterIsConvertibleTo - : SplitterIsConvertibleToImpl< - C, -#ifdef _GLIBCXX_DEBUG - !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value && -#endif // _GLIBCXX_DEBUG - !IsInitializerList< - typename std::remove_reference<C>::type>::value && - HasValueType<C>::value && HasConstIterator<C>::value, - HasMappedType<C>::value> { -}; - -// This class implements the range that is returned by absl::StrSplit(). This -// class has templated conversion operators that allow it to be implicitly -// converted to a variety of types that the caller may have specified on the -// left-hand side of an assignment. -// -// The main interface for interacting with this class is through its implicit -// conversion operators. However, this class may also be used like a container -// in that it has .begin() and .end() member functions. It may also be used -// within a range-for loop. -// -// Output containers can be collections of any type that is constructible from -// an absl::string_view. -// -// An Predicate functor may be supplied. This predicate will be used to filter -// 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> -class Splitter { - public: - using DelimiterType = Delimiter; - using PredicateType = Predicate; - 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) - : text_(std::move(input_text)), - delimiter_(std::move(d)), - predicate_(std::move(p)) {} - - absl::string_view text() const { return text_; } - const Delimiter& delimiter() const { return delimiter_; } - const Predicate& predicate() const { return predicate_; } - - // Range functions that iterate the split substrings as absl::string_view - // objects. These methods enable a Splitter to be used in a range-based for - // loop. - const_iterator begin() const { return {const_iterator::kInitState, this}; } - const_iterator end() const { return {const_iterator::kEndState, this}; } - - // An implicit conversion operator that is restricted to only those containers - // that the splitter is convertible to. - template <typename Container, - typename = typename std::enable_if< - SplitterIsConvertibleTo<Container>::value>::type> - operator Container() const { // NOLINT(runtime/explicit) - return ConvertToContainer<Container, typename Container::value_type, - HasMappedType<Container>::value>()(*this); - } - - // Returns a pair with its .first and .second members set to the first two - // strings returned by the begin() iterator. Either/both of .first and .second - // will be constructed with empty strings if the iterator doesn't have a - // corresponding value. - template <typename First, typename Second> - operator std::pair<First, Second>() const { // NOLINT(runtime/explicit) - absl::string_view first, second; - auto it = begin(); - if (it != end()) { - first = *it; - if (++it != end()) { - second = *it; - } - } - return {First(first), Second(second)}; - } - - private: - // ConvertToContainer is a functor converting a Splitter to the requested - // Container of ValueType. It is specialized below to optimize splitting to - // certain combinations of Container and ValueType. - // - // This base template handles the generic case of storing the split results in - // the requested non-map-like container and converting the split substrings to - // the requested type. - template <typename Container, typename ValueType, bool is_map = false> - struct ConvertToContainer { - Container operator()(const Splitter& splitter) const { - Container c; - auto it = std::inserter(c, c.end()); - for (const auto& sp : splitter) { - *it++ = ValueType(sp); - } - return c; - } - }; - - // Partial specialization for a std::vector<absl::string_view>. - // - // Optimized for the common case of splitting to a - // std::vector<absl::string_view>. In this case we first split the results to - // a small array of absl::string_view on the stack, to reduce reallocations. - template <typename A> - struct ConvertToContainer<std::vector<absl::string_view, A>, - absl::string_view, false> { - std::vector<absl::string_view, A> operator()( - const Splitter& splitter) const { - struct raw_view { - const char* data; - size_t size; - operator absl::string_view() const { // NOLINT(runtime/explicit) - return {data, size}; - } - }; - std::vector<absl::string_view, A> v; - std::array<raw_view, 16> ar; - for (auto it = splitter.begin(); !it.at_end();) { - size_t index = 0; - do { - ar[index].data = it->data(); - ar[index].size = it->size(); - ++it; - } while (++index != ar.size() && !it.at_end()); - v.insert(v.end(), ar.begin(), ar.begin() + index); - } - return v; - } - }; - - // Partial specialization for a std::vector<std::string>. - // - // Optimized for the common case of splitting to a std::vector<std::string>. - // In this case we first split the results to a std::vector<absl::string_view> - // so the returned std::vector<std::string> can have space reserved to avoid - // std::string moves. - template <typename A> - struct ConvertToContainer<std::vector<std::string, A>, std::string, false> { - std::vector<std::string, A> operator()(const Splitter& splitter) const { - const std::vector<absl::string_view> v = splitter; - return std::vector<std::string, A>(v.begin(), v.end()); - } - }; - - // Partial specialization for containers of pairs (e.g., maps). - // - // The algorithm is to insert a new pair into the map for each even-numbered - // item, with the even-numbered item as the key with a default-constructed - // value. Each odd-numbered item will then be assigned to the last pair's - // value. - template <typename Container, typename First, typename Second> - struct ConvertToContainer<Container, std::pair<const First, Second>, true> { - Container operator()(const Splitter& splitter) const { - Container m; - typename Container::iterator it; - bool insert = true; - for (const auto& sp : splitter) { - if (insert) { - it = Inserter<Container>::Insert(&m, First(sp), Second()); - } else { - it->second = Second(sp); - } - insert = !insert; - } - return m; - } - - // 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_; - Delimiter delimiter_; - Predicate predicate_; -}; - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ 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 b15f1d9bcfac..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/string_constant.h +++ /dev/null @@ -1,70 +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 { - private: - // Returns true if `view` points to constant data. - // Otherwise, it can't be constant evaluated. - static constexpr bool ValidateConstant(absl::string_view view) { - return view.empty() || 2 * view[0] != 1; - } - - public: - static constexpr absl::string_view value = T{}(); - constexpr absl::string_view operator()() const { return value; } - - static_assert(ValidateConstant(value), - "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 392833cf1592..000000000000 --- 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/internal/utf8.cc b/third_party/abseil_cpp/absl/strings/internal/utf8.cc deleted file mode 100644 index 8fd8edc1ec6f..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/utf8.cc +++ /dev/null @@ -1,53 +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. - -// UTF8 utilities, implemented to reduce dependencies. - -#include "absl/strings/internal/utf8.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) { - if (utf8_char <= 0x7F) { - *buffer = static_cast<char>(utf8_char); - return 1; - } else if (utf8_char <= 0x7FF) { - buffer[1] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[0] = 0xC0 | utf8_char; - return 2; - } else if (utf8_char <= 0xFFFF) { - buffer[2] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[1] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[0] = 0xE0 | utf8_char; - return 3; - } else { - buffer[3] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[2] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[1] = 0x80 | (utf8_char & 0x3F); - utf8_char >>= 6; - buffer[0] = 0xF0 | utf8_char; - return 4; - } -} - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/internal/utf8.h b/third_party/abseil_cpp/absl/strings/internal/utf8.h deleted file mode 100644 index 32fb1093bea3..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/utf8.h +++ /dev/null @@ -1,50 +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. -// -// UTF8 utilities, implemented to reduce dependencies. - -#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_ -#define ABSL_STRINGS_INTERNAL_UTF8_H_ - -#include <cstddef> -#include <cstdint> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes -// out the UTF-8 encoding into buffer, and returns the number of chars -// it wrote. -// -// As described in https://tools.ietf.org/html/rfc3629#section-3 , the encodings -// are: -// 00 - 7F : 0xxxxxxx -// 80 - 7FF : 110xxxxx 10xxxxxx -// 800 - FFFF : 1110xxxx 10xxxxxx 10xxxxxx -// 10000 - 10FFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -// -// Values greater than 0x10FFFF are not supported and may or may not write -// characters into buffer, however never will more than kMaxEncodedUTF8Size -// bytes be written, regardless of the value of utf8_char. -enum { kMaxEncodedUTF8Size = 4 }; -size_t EncodeUTF8Char(char *buffer, char32_t utf8_char); - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_UTF8_H_ diff --git a/third_party/abseil_cpp/absl/strings/internal/utf8_test.cc b/third_party/abseil_cpp/absl/strings/internal/utf8_test.cc deleted file mode 100644 index 88dd5036e3da..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/utf8_test.cc +++ /dev/null @@ -1,66 +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/strings/internal/utf8.h" - -#include <cstdint> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/base/port.h" - -namespace { - -#if !defined(__cpp_char8_t) -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++2a-compat" -#endif -TEST(EncodeUTF8Char, BasicFunction) { - std::pair<char32_t, std::string> tests[] = {{0x0030, u8"\u0030"}, - {0x00A3, u8"\u00A3"}, - {0x00010000, u8"\U00010000"}, - {0x0000FFFF, u8"\U0000FFFF"}, - {0x0010FFFD, u8"\U0010FFFD"}}; - for (auto &test : tests) { - char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'}; - char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'}; - char *buf0_written = - &buf0[absl::strings_internal::EncodeUTF8Char(buf0, test.first)]; - char *buf1_written = - &buf1[absl::strings_internal::EncodeUTF8Char(buf1, test.first)]; - int apparent_length = 7; - while (buf0[apparent_length - 1] == '\x00' && - buf1[apparent_length - 1] == '\xFF') { - if (--apparent_length == 0) break; - } - EXPECT_EQ(apparent_length, buf0_written - buf0); - EXPECT_EQ(apparent_length, buf1_written - buf1); - EXPECT_EQ(apparent_length, test.second.length()); - EXPECT_EQ(std::string(buf0, apparent_length), test.second); - EXPECT_EQ(std::string(buf1, apparent_length), test.second); - } - char buf[32] = "Don't Tread On Me"; - EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf, 0x00110000), - absl::strings_internal::kMaxEncodedUTF8Size); - char buf2[32] = "Negative is invalid but sane"; - EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf2, -1), - absl::strings_internal::kMaxEncodedUTF8Size); -} -#if defined(__clang__) -#pragma clang diagnostic pop -#endif -#endif // !defined(__cpp_char8_t) - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/match.cc b/third_party/abseil_cpp/absl/strings/match.cc deleted file mode 100644 index 8127cb0c5e77..000000000000 --- a/third_party/abseil_cpp/absl/strings/match.cc +++ /dev/null @@ -1,40 +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/strings/match.h" - -#include "absl/strings/internal/memutil.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -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) { - return (text.size() >= prefix.size()) && - EqualsIgnoreCase(text.substr(0, prefix.size()), prefix); -} - -bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) { - return (text.size() >= suffix.size()) && - EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/match.h b/third_party/abseil_cpp/absl/strings/match.h deleted file mode 100644 index 90fca98ad2cf..000000000000 --- a/third_party/abseil_cpp/absl/strings/match.h +++ /dev/null @@ -1,90 +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. -// -// ----------------------------------------------------------------------------- -// File: match.h -// ----------------------------------------------------------------------------- -// -// This file contains simple utilities for performing string matching checks. -// All of these function parameters are specified as `absl::string_view`, -// meaning that these functions can accept `std::string`, `absl::string_view` or -// NUL-terminated C-style strings. -// -// Examples: -// std::string s = "foo"; -// absl::string_view sv = "f"; -// assert(absl::StrContains(s, sv)); -// -// Note: The order of parameters in these functions is designed to mimic the -// order an equivalent member function would exhibit; -// e.g. `s.Contains(x)` ==> `absl::StrContains(s, x). -#ifndef ABSL_STRINGS_MATCH_H_ -#define ABSL_STRINGS_MATCH_H_ - -#include <cstring> - -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// StrContains() -// -// Returns whether a given string `haystack` contains the substring `needle`. -inline bool StrContains(absl::string_view haystack, absl::string_view needle) { - return haystack.find(needle, 0) != haystack.npos; -} - -// StartsWith() -// -// Returns whether a given string `text` begins with `prefix`. -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); -} - -// EndsWith() -// -// Returns whether a given string `text` ends with `suffix`. -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(), - suffix.size()) == 0); -} - -// EqualsIgnoreCase() -// -// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring -// case in the comparison. -bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2); - -// 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); - -// 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); - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_MATCH_H_ diff --git a/third_party/abseil_cpp/absl/strings/match_test.cc b/third_party/abseil_cpp/absl/strings/match_test.cc deleted file mode 100644 index 4c313dda14e3..000000000000 --- a/third_party/abseil_cpp/absl/strings/match_test.cc +++ /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. - -#include "absl/strings/match.h" - -#include "gtest/gtest.h" - -namespace { - -TEST(MatchTest, StartsWith) { - const std::string s1("123\0abc", 7); - const absl::string_view a("foobar"); - const absl::string_view b(s1); - const absl::string_view e; - EXPECT_TRUE(absl::StartsWith(a, a)); - EXPECT_TRUE(absl::StartsWith(a, "foo")); - EXPECT_TRUE(absl::StartsWith(a, e)); - EXPECT_TRUE(absl::StartsWith(b, s1)); - EXPECT_TRUE(absl::StartsWith(b, b)); - EXPECT_TRUE(absl::StartsWith(b, e)); - EXPECT_TRUE(absl::StartsWith(e, "")); - EXPECT_FALSE(absl::StartsWith(a, b)); - EXPECT_FALSE(absl::StartsWith(b, a)); - EXPECT_FALSE(absl::StartsWith(e, a)); -} - -TEST(MatchTest, EndsWith) { - const std::string s1("123\0abc", 7); - const absl::string_view a("foobar"); - const absl::string_view b(s1); - const absl::string_view e; - EXPECT_TRUE(absl::EndsWith(a, a)); - EXPECT_TRUE(absl::EndsWith(a, "bar")); - EXPECT_TRUE(absl::EndsWith(a, e)); - EXPECT_TRUE(absl::EndsWith(b, s1)); - EXPECT_TRUE(absl::EndsWith(b, b)); - EXPECT_TRUE(absl::EndsWith(b, e)); - EXPECT_TRUE(absl::EndsWith(e, "")); - EXPECT_FALSE(absl::EndsWith(a, b)); - EXPECT_FALSE(absl::EndsWith(b, a)); - EXPECT_FALSE(absl::EndsWith(e, a)); -} - -TEST(MatchTest, Contains) { - absl::string_view a("abcdefg"); - absl::string_view b("abcd"); - absl::string_view c("efg"); - absl::string_view d("gh"); - EXPECT_TRUE(absl::StrContains(a, a)); - EXPECT_TRUE(absl::StrContains(a, b)); - EXPECT_TRUE(absl::StrContains(a, c)); - EXPECT_FALSE(absl::StrContains(a, d)); - EXPECT_TRUE(absl::StrContains("", "")); - EXPECT_TRUE(absl::StrContains("abc", "")); - EXPECT_FALSE(absl::StrContains("", "a")); -} - -TEST(MatchTest, ContainsNull) { - const std::string s = "foo"; - const char* cs = "foo"; - const absl::string_view sv("foo"); - const absl::string_view sv2("foo\0bar", 4); - EXPECT_EQ(s, "foo"); - EXPECT_EQ(sv, "foo"); - EXPECT_NE(sv2, "foo"); - EXPECT_TRUE(absl::EndsWith(s, sv)); - EXPECT_TRUE(absl::StartsWith(cs, sv)); - EXPECT_TRUE(absl::StrContains(cs, sv)); - EXPECT_FALSE(absl::StrContains(cs, sv2)); -} - -TEST(MatchTest, EqualsIgnoreCase) { - std::string text = "the"; - absl::string_view data(text); - - EXPECT_TRUE(absl::EqualsIgnoreCase(data, "The")); - EXPECT_TRUE(absl::EqualsIgnoreCase(data, "THE")); - EXPECT_TRUE(absl::EqualsIgnoreCase(data, "the")); - EXPECT_FALSE(absl::EqualsIgnoreCase(data, "Quick")); - EXPECT_FALSE(absl::EqualsIgnoreCase(data, "then")); -} - -TEST(MatchTest, StartsWithIgnoreCase) { - EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "foo")); - EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "Fo")); - EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "")); - EXPECT_FALSE(absl::StartsWithIgnoreCase("foo", "fooo")); - EXPECT_FALSE(absl::StartsWithIgnoreCase("", "fo")); -} - -TEST(MatchTest, EndsWithIgnoreCase) { - EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", "foo")); - EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", "Oo")); - EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", "")); - EXPECT_FALSE(absl::EndsWithIgnoreCase("foo", "fooo")); - EXPECT_FALSE(absl::EndsWithIgnoreCase("", "fo")); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/numbers.cc b/third_party/abseil_cpp/absl/strings/numbers.cc deleted file mode 100644 index 3da1059c908d..000000000000 --- a/third_party/abseil_cpp/absl/strings/numbers.cc +++ /dev/null @@ -1,1083 +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 contains string processing functions related to -// numeric values. - -#include "absl/strings/numbers.h" - -#include <algorithm> -#include <cassert> -#include <cfloat> // for DBL_DIG and FLT_DIG -#include <cmath> // for HUGE_VAL -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <iterator> -#include <limits> -#include <memory> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/base/internal/bits.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/ascii.h" -#include "absl/strings/charconv.h" -#include "absl/strings/escaping.h" -#include "absl/strings/internal/memutil.h" -#include "absl/strings/match.h" -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -bool SimpleAtof(absl::string_view str, float* out) { - *out = 0.0; - str = StripAsciiWhitespace(str); - if (!str.empty() && str[0] == '+') { - str.remove_prefix(1); - } - auto result = absl::from_chars(str.data(), str.data() + str.size(), *out); - if (result.ec == std::errc::invalid_argument) { - return false; - } - if (result.ptr != str.data() + str.size()) { - // not all non-whitespace characters consumed - return false; - } - // from_chars() with DR 3081's current wording will return max() on - // overflow. SimpleAtof returns infinity instead. - if (result.ec == std::errc::result_out_of_range) { - if (*out > 1.0) { - *out = std::numeric_limits<float>::infinity(); - } else if (*out < -1.0) { - *out = -std::numeric_limits<float>::infinity(); - } - } - return true; -} - -bool SimpleAtod(absl::string_view str, double* out) { - *out = 0.0; - str = StripAsciiWhitespace(str); - if (!str.empty() && str[0] == '+') { - str.remove_prefix(1); - } - auto result = absl::from_chars(str.data(), str.data() + str.size(), *out); - if (result.ec == std::errc::invalid_argument) { - return false; - } - if (result.ptr != str.data() + str.size()) { - // not all non-whitespace characters consumed - return false; - } - // from_chars() with DR 3081's current wording will return max() on - // overflow. SimpleAtod returns infinity instead. - if (result.ec == std::errc::result_out_of_range) { - if (*out > 1.0) { - *out = std::numeric_limits<double>::infinity(); - } else if (*out < -1.0) { - *out = -std::numeric_limits<double>::infinity(); - } - } - return true; -} - -bool SimpleAtob(absl::string_view str, bool* out) { - ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr."); - if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") || - EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") || - EqualsIgnoreCase(str, "1")) { - *out = true; - return true; - } - if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") || - EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") || - EqualsIgnoreCase(str, "0")) { - *out = false; - return true; - } - return false; -} - -// ---------------------------------------------------------------------- -// FastIntToBuffer() overloads -// -// Like the Fast*ToBuffer() functions above, these are intended for speed. -// Unlike the Fast*ToBuffer() functions, however, these functions write -// their output to the beginning of the buffer. The caller is responsible -// for ensuring that the buffer has enough space to hold the output. -// -// Returns a pointer to the end of the string (i.e. the null character -// terminating the string). -// ---------------------------------------------------------------------- - -namespace { - -// Used to optimize printing a decimal number's final digit. -const char one_ASCII_final_digits[10][2] { - {'0', 0}, {'1', 0}, {'2', 0}, {'3', 0}, {'4', 0}, - {'5', 0}, {'6', 0}, {'7', 0}, {'8', 0}, {'9', 0}, -}; - -} // namespace - -char* numbers_internal::FastIntToBuffer(uint32_t i, char* buffer) { - uint32_t digits; - // The idea of this implementation is to trim the number of divides to as few - // as possible, and also reducing memory stores and branches, by going in - // steps of two digits at a time rather than one whenever possible. - // The huge-number case is first, in the hopes that the compiler will output - // that case in one branch-free block of code, and only output conditional - // branches into it from below. - if (i >= 1000000000) { // >= 1,000,000,000 - digits = i / 100000000; // 100,000,000 - i -= digits * 100000000; - PutTwoDigits(digits, buffer); - buffer += 2; - lt100_000_000: - digits = i / 1000000; // 1,000,000 - i -= digits * 1000000; - PutTwoDigits(digits, buffer); - buffer += 2; - lt1_000_000: - digits = i / 10000; // 10,000 - i -= digits * 10000; - PutTwoDigits(digits, buffer); - buffer += 2; - lt10_000: - digits = i / 100; - i -= digits * 100; - PutTwoDigits(digits, buffer); - buffer += 2; - lt100: - digits = i; - PutTwoDigits(digits, buffer); - buffer += 2; - *buffer = 0; - return buffer; - } - - if (i < 100) { - digits = i; - if (i >= 10) goto lt100; - memcpy(buffer, one_ASCII_final_digits[i], 2); - return buffer + 1; - } - if (i < 10000) { // 10,000 - if (i >= 1000) goto lt10_000; - digits = i / 100; - i -= digits * 100; - *buffer++ = '0' + digits; - goto lt100; - } - if (i < 1000000) { // 1,000,000 - if (i >= 100000) goto lt1_000_000; - digits = i / 10000; // 10,000 - i -= digits * 10000; - *buffer++ = '0' + digits; - goto lt10_000; - } - if (i < 100000000) { // 100,000,000 - if (i >= 10000000) goto lt100_000_000; - digits = i / 1000000; // 1,000,000 - i -= digits * 1000000; - *buffer++ = '0' + digits; - goto lt1_000_000; - } - // we already know that i < 1,000,000,000 - digits = i / 100000000; // 100,000,000 - i -= digits * 100000000; - *buffer++ = '0' + digits; - goto lt100_000_000; -} - -char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) { - uint32_t u = i; - if (i < 0) { - *buffer++ = '-'; - // We need to do the negation in modular (i.e., "unsigned") - // arithmetic; MSVC++ apprently warns for plain "-u", so - // we write the equivalent expression "0 - u" instead. - u = 0 - u; - } - return numbers_internal::FastIntToBuffer(u, buffer); -} - -char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) { - uint32_t u32 = static_cast<uint32_t>(i); - if (u32 == i) return numbers_internal::FastIntToBuffer(u32, buffer); - - // Here we know i has at least 10 decimal digits. - uint64_t top_1to11 = i / 1000000000; - u32 = static_cast<uint32_t>(i - top_1to11 * 1000000000); - uint32_t top_1to11_32 = static_cast<uint32_t>(top_1to11); - - if (top_1to11_32 == top_1to11) { - buffer = numbers_internal::FastIntToBuffer(top_1to11_32, buffer); - } else { - // top_1to11 has more than 32 bits too; print it in two steps. - uint32_t top_8to9 = static_cast<uint32_t>(top_1to11 / 100); - uint32_t mid_2 = static_cast<uint32_t>(top_1to11 - top_8to9 * 100); - buffer = numbers_internal::FastIntToBuffer(top_8to9, buffer); - PutTwoDigits(mid_2, buffer); - buffer += 2; - } - - // We have only 9 digits now, again the maximum uint32_t can handle fully. - uint32_t digits = u32 / 10000000; // 10,000,000 - u32 -= digits * 10000000; - PutTwoDigits(digits, buffer); - buffer += 2; - digits = u32 / 100000; // 100,000 - u32 -= digits * 100000; - PutTwoDigits(digits, buffer); - buffer += 2; - digits = u32 / 1000; // 1,000 - u32 -= digits * 1000; - PutTwoDigits(digits, buffer); - buffer += 2; - digits = u32 / 10; - u32 -= digits * 10; - PutTwoDigits(digits, buffer); - buffer += 2; - memcpy(buffer, one_ASCII_final_digits[u32], 2); - return buffer + 1; -} - -char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) { - uint64_t u = i; - if (i < 0) { - *buffer++ = '-'; - u = 0 - u; - } - return numbers_internal::FastIntToBuffer(u, buffer); -} - -// Given a 128-bit number expressed as a pair of uint64_t, high half first, -// return that number multiplied by the given 32-bit value. If the result is -// too large to fit in a 128-bit number, divide it by 2 until it fits. -static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num, - uint32_t mul) { - uint64_t bits0_31 = num.second & 0xFFFFFFFF; - uint64_t bits32_63 = num.second >> 32; - uint64_t bits64_95 = num.first & 0xFFFFFFFF; - uint64_t bits96_127 = num.first >> 32; - - // The picture so far: each of these 64-bit values has only the lower 32 bits - // filled in. - // bits96_127: [ 00000000 xxxxxxxx ] - // bits64_95: [ 00000000 xxxxxxxx ] - // bits32_63: [ 00000000 xxxxxxxx ] - // bits0_31: [ 00000000 xxxxxxxx ] - - bits0_31 *= mul; - bits32_63 *= mul; - bits64_95 *= mul; - bits96_127 *= mul; - - // Now the top halves may also have value, though all 64 of their bits will - // never be set at the same time, since they are a result of a 32x32 bit - // multiply. This makes the carry calculation slightly easier. - // bits96_127: [ mmmmmmmm | mmmmmmmm ] - // bits64_95: [ | mmmmmmmm mmmmmmmm | ] - // bits32_63: | [ mmmmmmmm | mmmmmmmm ] - // bits0_31: | [ | mmmmmmmm mmmmmmmm ] - // eventually: [ bits128_up | ...bits64_127.... | ..bits0_63... ] - - uint64_t bits0_63 = bits0_31 + (bits32_63 << 32); - uint64_t bits64_127 = bits64_95 + (bits96_127 << 32) + (bits32_63 >> 32) + - (bits0_63 < bits0_31); - uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95); - if (bits128_up == 0) return {bits64_127, bits0_63}; - - int shift = 64 - base_internal::CountLeadingZeros64(bits128_up); - uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift)); - uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift)); - return {hi, lo}; -} - -// Compute num * 5 ^ expfive, and return the first 128 bits of the result, -// where the first bit is always a one. So PowFive(1, 0) starts 0b100000, -// PowFive(1, 1) starts 0b101000, PowFive(1, 2) starts 0b110010, etc. -static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) { - std::pair<uint64_t, uint64_t> result = {num, 0}; - while (expfive >= 13) { - // 5^13 is the highest power of five that will fit in a 32-bit integer. - result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5); - expfive -= 13; - } - constexpr int powers_of_five[13] = { - 1, - 5, - 5 * 5, - 5 * 5 * 5, - 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5}; - result = Mul32(result, powers_of_five[expfive & 15]); - int shift = base_internal::CountLeadingZeros64(result.first); - if (shift != 0) { - result.first = (result.first << shift) + (result.second >> (64 - shift)); - result.second = (result.second << shift); - } - return result; -} - -struct ExpDigits { - int32_t exponent; - char digits[6]; -}; - -// SplitToSix converts value, a positive double-precision floating-point number, -// into a base-10 exponent and 6 ASCII digits, where the first digit is never -// zero. For example, SplitToSix(1) returns an exponent of zero and a digits -// array of {'1', '0', '0', '0', '0', '0'}. If value is exactly halfway between -// two possible representations, e.g. value = 100000.5, then "round to even" is -// performed. -static ExpDigits SplitToSix(const double value) { - ExpDigits exp_dig; - int exp = 5; - double d = value; - // First step: calculate a close approximation of the output, where the - // value d will be between 100,000 and 999,999, representing the digits - // in the output ASCII array, and exp is the base-10 exponent. It would be - // faster to use a table here, and to look up the base-2 exponent of value, - // however value is an IEEE-754 64-bit number, so the table would have 2,000 - // entries, which is not cache-friendly. - if (d >= 999999.5) { - if (d >= 1e+261) exp += 256, d *= 1e-256; - if (d >= 1e+133) exp += 128, d *= 1e-128; - if (d >= 1e+69) exp += 64, d *= 1e-64; - if (d >= 1e+37) exp += 32, d *= 1e-32; - if (d >= 1e+21) exp += 16, d *= 1e-16; - if (d >= 1e+13) exp += 8, d *= 1e-8; - if (d >= 1e+9) exp += 4, d *= 1e-4; - if (d >= 1e+7) exp += 2, d *= 1e-2; - if (d >= 1e+6) exp += 1, d *= 1e-1; - } else { - if (d < 1e-250) exp -= 256, d *= 1e256; - if (d < 1e-122) exp -= 128, d *= 1e128; - if (d < 1e-58) exp -= 64, d *= 1e64; - if (d < 1e-26) exp -= 32, d *= 1e32; - if (d < 1e-10) exp -= 16, d *= 1e16; - if (d < 1e-2) exp -= 8, d *= 1e8; - if (d < 1e+2) exp -= 4, d *= 1e4; - if (d < 1e+4) exp -= 2, d *= 1e2; - if (d < 1e+5) exp -= 1, d *= 1e1; - } - // At this point, d is in the range [99999.5..999999.5) and exp is in the - // range [-324..308]. Since we need to round d up, we want to add a half - // and truncate. - // However, the technique above may have lost some precision, due to its - // repeated multiplication by constants that each may be off by half a bit - // of precision. This only matters if we're close to the edge though. - // Since we'd like to know if the fractional part of d is close to a half, - // we multiply it by 65536 and see if the fractional part is close to 32768. - // (The number doesn't have to be a power of two,but powers of two are faster) - uint64_t d64k = d * 65536; - int dddddd; // A 6-digit decimal integer. - if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) { - // OK, it's fairly likely that precision was lost above, which is - // not a surprise given only 52 mantissa bits are available. Therefore - // redo the calculation using 128-bit numbers. (64 bits are not enough). - - // Start out with digits rounded down; maybe add one below. - dddddd = static_cast<int>(d64k / 65536); - - // mantissa is a 64-bit integer representing M.mmm... * 2^63. The actual - // value we're representing, of course, is M.mmm... * 2^exp2. - int exp2; - double m = std::frexp(value, &exp2); - uint64_t mantissa = m * (32768.0 * 65536.0 * 65536.0 * 65536.0); - // std::frexp returns an m value in the range [0.5, 1.0), however we - // can't multiply it by 2^64 and convert to an integer because some FPUs - // throw an exception when converting an number higher than 2^63 into an - // integer - even an unsigned 64-bit integer! Fortunately it doesn't matter - // since m only has 52 significant bits anyway. - mantissa <<= 1; - exp2 -= 64; // not needed, but nice for debugging - - // OK, we are here to compare: - // (dddddd + 0.5) * 10^(exp-5) vs. mantissa * 2^exp2 - // so we can round up dddddd if appropriate. Those values span the full - // range of 600 orders of magnitude of IEE 64-bit floating-point. - // Fortunately, we already know they are very close, so we don't need to - // track the base-2 exponent of both sides. This greatly simplifies the - // the math since the 2^exp2 calculation is unnecessary and the power-of-10 - // calculation can become a power-of-5 instead. - - std::pair<uint64_t, uint64_t> edge, val; - if (exp >= 6) { - // Compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa - // Since we're tossing powers of two, 2 * dddddd + 1 is the - // same as dddddd + 0.5 - edge = PowFive(2 * dddddd + 1, exp - 5); - - val.first = mantissa; - val.second = 0; - } else { - // We can't compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa as we did - // above because (exp - 5) is negative. So we compare (dddddd + 0.5) to - // mantissa * 5 ^ (5 - exp) - edge = PowFive(2 * dddddd + 1, 0); - - val = PowFive(mantissa, 5 - exp); - } - // printf("exp=%d %016lx %016lx vs %016lx %016lx\n", exp, val.first, - // val.second, edge.first, edge.second); - if (val > edge) { - dddddd++; - } else if (val == edge) { - dddddd += (dddddd & 1); - } - } else { - // Here, we are not close to the edge. - dddddd = static_cast<int>((d64k + 32768) / 65536); - } - if (dddddd == 1000000) { - dddddd = 100000; - exp += 1; - } - exp_dig.exponent = exp; - - int two_digits = dddddd / 10000; - dddddd -= two_digits * 10000; - numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]); - - two_digits = dddddd / 100; - dddddd -= two_digits * 100; - numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]); - - numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]); - return exp_dig; -} - -// Helper function for fast formatting of floating-point. -// The result is the same as "%g", a.k.a. "%.6g". -size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) { - static_assert(std::numeric_limits<float>::is_iec559, - "IEEE-754/IEC-559 support only"); - - char* out = buffer; // we write data to out, incrementing as we go, but - // FloatToBuffer always returns the address of the buffer - // passed in. - - if (std::isnan(d)) { - strcpy(out, "nan"); // NOLINT(runtime/printf) - return 3; - } - if (d == 0) { // +0 and -0 are handled here - if (std::signbit(d)) *out++ = '-'; - *out++ = '0'; - *out = 0; - return out - buffer; - } - if (d < 0) { - *out++ = '-'; - d = -d; - } - if (std::isinf(d)) { - strcpy(out, "inf"); // NOLINT(runtime/printf) - return out + 3 - buffer; - } - - auto exp_dig = SplitToSix(d); - int exp = exp_dig.exponent; - const char* digits = exp_dig.digits; - out[0] = '0'; - out[1] = '.'; - switch (exp) { - case 5: - memcpy(out, &digits[0], 6), out += 6; - *out = 0; - return out - buffer; - case 4: - memcpy(out, &digits[0], 5), out += 5; - if (digits[5] != '0') { - *out++ = '.'; - *out++ = digits[5]; - } - *out = 0; - return out - buffer; - case 3: - memcpy(out, &digits[0], 4), out += 4; - if ((digits[5] | digits[4]) != '0') { - *out++ = '.'; - *out++ = digits[4]; - if (digits[5] != '0') *out++ = digits[5]; - } - *out = 0; - return out - buffer; - case 2: - memcpy(out, &digits[0], 3), out += 3; - *out++ = '.'; - memcpy(out, &digits[3], 3); - out += 3; - while (out[-1] == '0') --out; - if (out[-1] == '.') --out; - *out = 0; - return out - buffer; - case 1: - memcpy(out, &digits[0], 2), out += 2; - *out++ = '.'; - memcpy(out, &digits[2], 4); - out += 4; - while (out[-1] == '0') --out; - if (out[-1] == '.') --out; - *out = 0; - return out - buffer; - case 0: - memcpy(out, &digits[0], 1), out += 1; - *out++ = '.'; - memcpy(out, &digits[1], 5); - out += 5; - while (out[-1] == '0') --out; - if (out[-1] == '.') --out; - *out = 0; - return out - buffer; - case -4: - out[2] = '0'; - ++out; - ABSL_FALLTHROUGH_INTENDED; - case -3: - out[2] = '0'; - ++out; - ABSL_FALLTHROUGH_INTENDED; - case -2: - out[2] = '0'; - ++out; - ABSL_FALLTHROUGH_INTENDED; - case -1: - out += 2; - memcpy(out, &digits[0], 6); - out += 6; - while (out[-1] == '0') --out; - *out = 0; - return out - buffer; - } - assert(exp < -4 || exp >= 6); - out[0] = digits[0]; - assert(out[1] == '.'); - out += 2; - memcpy(out, &digits[1], 5), out += 5; - while (out[-1] == '0') --out; - if (out[-1] == '.') --out; - *out++ = 'e'; - if (exp > 0) { - *out++ = '+'; - } else { - *out++ = '-'; - exp = -exp; - } - if (exp > 99) { - int dig1 = exp / 100; - exp -= dig1 * 100; - *out++ = '0' + dig1; - } - PutTwoDigits(exp, out); - out += 2; - *out = 0; - return out - buffer; -} - -namespace { -// Represents integer values of digits. -// Uses 36 to indicate an invalid character since we support -// bases up to 36. -static const int8_t kAsciiToInt[256] = { - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 16 36s. - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 36, 36, 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}; - -// Parse the sign and optional hex or oct prefix in text. -inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/, - int* base_ptr /*inout*/, - bool* negative_ptr /*output*/) { - if (text->data() == nullptr) { - return false; - } - - const char* start = text->data(); - const char* end = start + text->size(); - int base = *base_ptr; - - // Consume whitespace. - while (start < end && absl::ascii_isspace(start[0])) { - ++start; - } - while (start < end && absl::ascii_isspace(end[-1])) { - --end; - } - if (start >= end) { - return false; - } - - // Consume sign. - *negative_ptr = (start[0] == '-'); - if (*negative_ptr || start[0] == '+') { - ++start; - if (start >= end) { - return false; - } - } - - // Consume base-dependent prefix. - // base 0: "0x" -> base 16, "0" -> base 8, default -> base 10 - // base 16: "0x" -> base 16 - // Also validate the base. - if (base == 0) { - if (end - start >= 2 && start[0] == '0' && - (start[1] == 'x' || start[1] == 'X')) { - base = 16; - start += 2; - if (start >= end) { - // "0x" with no digits after is invalid. - return false; - } - } else if (end - start >= 1 && start[0] == '0') { - base = 8; - start += 1; - } else { - base = 10; - } - } else if (base == 16) { - if (end - start >= 2 && start[0] == '0' && - (start[1] == 'x' || start[1] == 'X')) { - start += 2; - if (start >= end) { - // "0x" with no digits after is invalid. - return false; - } - } - } else if (base >= 2 && base <= 36) { - // okay - } else { - return false; - } - *text = absl::string_view(start, end - start); - *base_ptr = base; - return true; -} - -// Consume digits. -// -// The classic loop: -// -// for each digit -// value = value * base + digit -// value *= sign -// -// The classic loop needs overflow checking. It also fails on the most -// negative integer, -2147483648 in 32-bit two's complement representation. -// -// My improved loop: -// -// if (!negative) -// for each digit -// value = value * base -// value = value + digit -// else -// for each digit -// value = value * base -// value = value - digit -// -// Overflow checking becomes simple. - -// Lookup tables per IntType: -// vmax/base and vmin/base are precomputed because division costs at least 8ns. -// TODO(junyer): Doing this per base instead (i.e. an array of structs, not a -// struct of arrays) would probably be better in terms of d-cache for the most -// commonly used bases. -template <typename IntType> -struct LookupTables { - ABSL_CONST_INIT static const IntType kVmaxOverBase[]; - ABSL_CONST_INIT static const IntType kVminOverBase[]; -}; - -// An array initializer macro for X/base where base in [0, 36]. -// However, note that lookups for base in [0, 1] should never happen because -// base has been validated to be in [2, 36] by safe_parse_sign_and_base(). -#define X_OVER_BASE_INITIALIZER(X) \ - { \ - 0, 0, X / 2, X / 3, X / 4, X / 5, X / 6, X / 7, X / 8, X / 9, X / 10, \ - X / 11, X / 12, X / 13, X / 14, X / 15, X / 16, X / 17, X / 18, \ - X / 19, X / 20, X / 21, X / 22, X / 23, X / 24, X / 25, X / 26, \ - X / 27, X / 28, X / 29, X / 30, X / 31, X / 32, X / 33, X / 34, \ - X / 35, X / 36, \ - } - -// This kVmaxOverBase is generated with -// for (int base = 2; base < 37; ++base) { -// absl::uint128 max = std::numeric_limits<absl::uint128>::max(); -// auto result = max / base; -// std::cout << " MakeUint128(" << absl::Uint128High64(result) << "u, " -// << absl::Uint128Low64(result) << "u),\n"; -// } -// See https://godbolt.org/z/aneYsb -// -// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting -// array to avoid a static initializer. -template<> -const uint128 LookupTables<uint128>::kVmaxOverBase[] = { - 0, - 0, - MakeUint128(9223372036854775807u, 18446744073709551615u), - MakeUint128(6148914691236517205u, 6148914691236517205u), - MakeUint128(4611686018427387903u, 18446744073709551615u), - MakeUint128(3689348814741910323u, 3689348814741910323u), - MakeUint128(3074457345618258602u, 12297829382473034410u), - MakeUint128(2635249153387078802u, 5270498306774157604u), - MakeUint128(2305843009213693951u, 18446744073709551615u), - MakeUint128(2049638230412172401u, 14347467612885206812u), - MakeUint128(1844674407370955161u, 11068046444225730969u), - MakeUint128(1676976733973595601u, 8384883669867978007u), - MakeUint128(1537228672809129301u, 6148914691236517205u), - MakeUint128(1418980313362273201u, 4256940940086819603u), - MakeUint128(1317624576693539401u, 2635249153387078802u), - MakeUint128(1229782938247303441u, 1229782938247303441u), - MakeUint128(1152921504606846975u, 18446744073709551615u), - MakeUint128(1085102592571150095u, 1085102592571150095u), - MakeUint128(1024819115206086200u, 16397105843297379214u), - MakeUint128(970881267037344821u, 16504981539634861972u), - MakeUint128(922337203685477580u, 14757395258967641292u), - MakeUint128(878416384462359600u, 14054662151397753612u), - MakeUint128(838488366986797800u, 13415813871788764811u), - MakeUint128(802032351030850070u, 4812194106185100421u), - MakeUint128(768614336404564650u, 12297829382473034410u), - MakeUint128(737869762948382064u, 11805916207174113034u), - MakeUint128(709490156681136600u, 11351842506898185609u), - MakeUint128(683212743470724133u, 17080318586768103348u), - MakeUint128(658812288346769700u, 10540996613548315209u), - MakeUint128(636094623231363848u, 15266270957552732371u), - MakeUint128(614891469123651720u, 9838263505978427528u), - MakeUint128(595056260442243600u, 9520900167075897608u), - MakeUint128(576460752303423487u, 18446744073709551615u), - MakeUint128(558992244657865200u, 8943875914525843207u), - MakeUint128(542551296285575047u, 9765923333140350855u), - MakeUint128(527049830677415760u, 8432797290838652167u), - MakeUint128(512409557603043100u, 8198552921648689607u), -}; - -// This kVmaxOverBase generated with -// for (int base = 2; base < 37; ++base) { -// absl::int128 max = std::numeric_limits<absl::int128>::max(); -// auto result = max / base; -// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", " -// << absl::Int128Low64(result) << "u),\n"; -// } -// See https://godbolt.org/z/7djYWz -// -// int128& operator/=(int128) is not constexpr, so hardcode the resulting array -// to avoid a static initializer. -template<> -const int128 LookupTables<int128>::kVmaxOverBase[] = { - 0, - 0, - MakeInt128(4611686018427387903, 18446744073709551615u), - MakeInt128(3074457345618258602, 12297829382473034410u), - MakeInt128(2305843009213693951, 18446744073709551615u), - MakeInt128(1844674407370955161, 11068046444225730969u), - MakeInt128(1537228672809129301, 6148914691236517205u), - MakeInt128(1317624576693539401, 2635249153387078802u), - MakeInt128(1152921504606846975, 18446744073709551615u), - MakeInt128(1024819115206086200, 16397105843297379214u), - MakeInt128(922337203685477580, 14757395258967641292u), - MakeInt128(838488366986797800, 13415813871788764811u), - MakeInt128(768614336404564650, 12297829382473034410u), - MakeInt128(709490156681136600, 11351842506898185609u), - MakeInt128(658812288346769700, 10540996613548315209u), - MakeInt128(614891469123651720, 9838263505978427528u), - MakeInt128(576460752303423487, 18446744073709551615u), - MakeInt128(542551296285575047, 9765923333140350855u), - MakeInt128(512409557603043100, 8198552921648689607u), - MakeInt128(485440633518672410, 17475862806672206794u), - MakeInt128(461168601842738790, 7378697629483820646u), - MakeInt128(439208192231179800, 7027331075698876806u), - MakeInt128(419244183493398900, 6707906935894382405u), - MakeInt128(401016175515425035, 2406097053092550210u), - MakeInt128(384307168202282325, 6148914691236517205u), - MakeInt128(368934881474191032, 5902958103587056517u), - MakeInt128(354745078340568300, 5675921253449092804u), - MakeInt128(341606371735362066, 17763531330238827482u), - MakeInt128(329406144173384850, 5270498306774157604u), - MakeInt128(318047311615681924, 7633135478776366185u), - MakeInt128(307445734561825860, 4919131752989213764u), - MakeInt128(297528130221121800, 4760450083537948804u), - MakeInt128(288230376151711743, 18446744073709551615u), - MakeInt128(279496122328932600, 4471937957262921603u), - MakeInt128(271275648142787523, 14106333703424951235u), - MakeInt128(263524915338707880, 4216398645419326083u), - MakeInt128(256204778801521550, 4099276460824344803u), -}; - -// This kVminOverBase generated with -// for (int base = 2; base < 37; ++base) { -// absl::int128 min = std::numeric_limits<absl::int128>::min(); -// auto result = min / base; -// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", " -// << absl::Int128Low64(result) << "u),\n"; -// } -// -// See https://godbolt.org/z/7djYWz -// -// int128& operator/=(int128) is not constexpr, so hardcode the resulting array -// to avoid a static initializer. -template<> -const int128 LookupTables<int128>::kVminOverBase[] = { - 0, - 0, - MakeInt128(-4611686018427387904, 0u), - MakeInt128(-3074457345618258603, 6148914691236517206u), - MakeInt128(-2305843009213693952, 0u), - MakeInt128(-1844674407370955162, 7378697629483820647u), - MakeInt128(-1537228672809129302, 12297829382473034411u), - MakeInt128(-1317624576693539402, 15811494920322472814u), - MakeInt128(-1152921504606846976, 0u), - MakeInt128(-1024819115206086201, 2049638230412172402u), - MakeInt128(-922337203685477581, 3689348814741910324u), - MakeInt128(-838488366986797801, 5030930201920786805u), - MakeInt128(-768614336404564651, 6148914691236517206u), - MakeInt128(-709490156681136601, 7094901566811366007u), - MakeInt128(-658812288346769701, 7905747460161236407u), - MakeInt128(-614891469123651721, 8608480567731124088u), - MakeInt128(-576460752303423488, 0u), - MakeInt128(-542551296285575048, 8680820740569200761u), - MakeInt128(-512409557603043101, 10248191152060862009u), - MakeInt128(-485440633518672411, 970881267037344822u), - MakeInt128(-461168601842738791, 11068046444225730970u), - MakeInt128(-439208192231179801, 11419412998010674810u), - MakeInt128(-419244183493398901, 11738837137815169211u), - MakeInt128(-401016175515425036, 16040647020617001406u), - MakeInt128(-384307168202282326, 12297829382473034411u), - MakeInt128(-368934881474191033, 12543785970122495099u), - MakeInt128(-354745078340568301, 12770822820260458812u), - MakeInt128(-341606371735362067, 683212743470724134u), - MakeInt128(-329406144173384851, 13176245766935394012u), - MakeInt128(-318047311615681925, 10813608594933185431u), - MakeInt128(-307445734561825861, 13527612320720337852u), - MakeInt128(-297528130221121801, 13686293990171602812u), - MakeInt128(-288230376151711744, 0u), - MakeInt128(-279496122328932601, 13974806116446630013u), - MakeInt128(-271275648142787524, 4340410370284600381u), - MakeInt128(-263524915338707881, 14230345428290225533u), - MakeInt128(-256204778801521551, 14347467612885206813u), -}; - -template <typename IntType> -const IntType LookupTables<IntType>::kVmaxOverBase[] = - X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max()); - -template <typename IntType> -const IntType LookupTables<IntType>::kVminOverBase[] = - X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::min()); - -#undef X_OVER_BASE_INITIALIZER - -template <typename IntType> -inline bool safe_parse_positive_int(absl::string_view text, int base, - IntType* value_p) { - IntType value = 0; - const IntType vmax = std::numeric_limits<IntType>::max(); - assert(vmax > 0); - assert(base >= 0); - assert(vmax >= static_cast<IntType>(base)); - const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base]; - assert(base < 2 || - std::numeric_limits<IntType>::max() / base == vmax_over_base); - const char* start = text.data(); - const char* end = start + text.size(); - // loop over digits - for (; start < end; ++start) { - unsigned char c = static_cast<unsigned char>(start[0]); - int digit = kAsciiToInt[c]; - if (digit >= base) { - *value_p = value; - return false; - } - if (value > vmax_over_base) { - *value_p = vmax; - return false; - } - value *= base; - if (value > vmax - digit) { - *value_p = vmax; - return false; - } - value += digit; - } - *value_p = value; - return true; -} - -template <typename IntType> -inline bool safe_parse_negative_int(absl::string_view text, int base, - IntType* value_p) { - IntType value = 0; - const IntType vmin = std::numeric_limits<IntType>::min(); - assert(vmin < 0); - assert(vmin <= 0 - base); - IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base]; - assert(base < 2 || - std::numeric_limits<IntType>::min() / base == vmin_over_base); - // 2003 c++ standard [expr.mul] - // "... the sign of the remainder is implementation-defined." - // Although (vmin/base)*base + vmin%base is always vmin. - // 2011 c++ standard tightens the spec but we cannot rely on it. - // TODO(junyer): Handle this in the lookup table generation. - if (vmin % base > 0) { - vmin_over_base += 1; - } - const char* start = text.data(); - const char* end = start + text.size(); - // loop over digits - for (; start < end; ++start) { - unsigned char c = static_cast<unsigned char>(start[0]); - int digit = kAsciiToInt[c]; - if (digit >= base) { - *value_p = value; - return false; - } - if (value < vmin_over_base) { - *value_p = vmin; - return false; - } - value *= base; - if (value < vmin + digit) { - *value_p = vmin; - return false; - } - value -= digit; - } - *value_p = value; - return true; -} - -// Input format based on POSIX.1-2008 strtol -// http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html -template <typename IntType> -inline bool safe_int_internal(absl::string_view text, IntType* value_p, - int base) { - *value_p = 0; - bool negative; - if (!safe_parse_sign_and_base(&text, &base, &negative)) { - return false; - } - if (!negative) { - return safe_parse_positive_int(text, base, value_p); - } else { - return safe_parse_negative_int(text, base, value_p); - } -} - -template <typename IntType> -inline bool safe_uint_internal(absl::string_view text, IntType* value_p, - int base) { - *value_p = 0; - bool negative; - if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) { - return false; - } - return safe_parse_positive_int(text, base, value_p); -} -} // anonymous namespace - -namespace numbers_internal { - -// Digit conversion. -ABSL_CONST_INIT ABSL_DLL const char kHexChar[] = - "0123456789abcdef"; - -ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] = - "000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f" - "505152535455565758595a5b5c5d5e5f" - "606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - -ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = { - {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, - {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'}, - {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, - {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, - {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'}, - {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, - {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'}, - {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, - {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, - {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'}, - {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, - {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'}, - {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, - {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, - {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'}, - {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, - {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}}; - -bool safe_strto32_base(absl::string_view text, int32_t* value, int base) { - return safe_int_internal<int32_t>(text, value, base); -} - -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); -} - -bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) { - return safe_uint_internal<uint64_t>(text, value, base); -} - -bool safe_strtou128_base(absl::string_view text, uint128* value, int base) { - return safe_uint_internal<absl::uint128>(text, value, base); -} - -} // namespace numbers_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/numbers.h b/third_party/abseil_cpp/absl/strings/numbers.h deleted file mode 100644 index 2e004b44f887..000000000000 --- a/third_party/abseil_cpp/absl/strings/numbers.h +++ /dev/null @@ -1,273 +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. -// -// ----------------------------------------------------------------------------- -// File: numbers.h -// ----------------------------------------------------------------------------- -// -// This package contains functions for converting strings to numbers. For -// converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h, -// which automatically detect and convert most number values appropriately. - -#ifndef ABSL_STRINGS_NUMBERS_H_ -#define ABSL_STRINGS_NUMBERS_H_ - -#ifdef __SSE4_2__ -#include <x86intrin.h> -#endif - -#include <cstddef> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <limits> -#include <string> -#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 -// we claim to support. Also, add tests for the compiler -// that doesn't support the Intel _bswap64 intrinsic but -// does support all the SSE 4.2 intrinsics -#include "absl/base/internal/endian.h" -#endif -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/numeric/int128.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// SimpleAtoi() -// -// Converts the given string (optionally followed or preceded by ASCII -// whitespace) into an integer value, returning `true` if successful. The string -// must reflect a base-10 integer whose value falls within the range of the -// integer type (optionally preceded by a `+` or `-`). If any errors are -// encountered, this function returns `false`, leaving `out` in an unspecified -// state. -template <typename int_type> -ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); - -// SimpleAtof() -// -// Converts the given string (optionally followed or preceded by ASCII -// whitespace) into a float, which may be rounded on overflow or underflow, -// returning `true` if successful. -// See https://en.cppreference.com/w/c/string/byte/strtof for details about the -// allowed formats for `str`, except SimpleAtof() is locale-independent and will -// always use the "C" locale. If any errors are encountered, this function -// returns `false`, leaving `out` in an unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); - -// SimpleAtod() -// -// Converts the given string (optionally followed or preceded by ASCII -// whitespace) into a double, which may be rounded on overflow or underflow, -// returning `true` if successful. -// See https://en.cppreference.com/w/c/string/byte/strtof for details about the -// allowed formats for `str`, except SimpleAtod is locale-independent and will -// always use the "C" locale. If any errors are encountered, this function -// returns `false`, leaving `out` in an unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); - -// SimpleAtob() -// -// Converts the given string into a boolean, returning `true` if successful. -// The following case-insensitive strings are interpreted as boolean `true`: -// "true", "t", "yes", "y", "1". The following case-insensitive strings -// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any -// errors are encountered, this function returns `false`, leaving `out` in an -// unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); - -ABSL_NAMESPACE_END -} // namespace absl - -// End of public API. Implementation details follow. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace numbers_internal { - -// Digit conversion. -ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef -ABSL_DLL extern const char - kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011... -ABSL_DLL extern const char - two_ASCII_digits[100][2]; // 00, 01, 02, 03... - -// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the -// range 0 <= i < 100, and buf must have space for two characters. Example: -// char buf[2]; -// PutTwoDigits(42, buf); -// // buf[0] == '4' -// // buf[1] == '2' -inline void PutTwoDigits(size_t i, char* buf) { - assert(i < 100); - memcpy(buf, two_ASCII_digits[i], 2); -} - -// safe_strto?() functions for implementing SimpleAtoi() -bool safe_strto32_base(absl::string_view text, int32_t* value, int base); -bool safe_strto64_base(absl::string_view text, int64_t* value, int base); -bool safe_strto128_base(absl::string_view text, absl::int128* value, - int base); -bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base); -bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base); -bool safe_strtou128_base(absl::string_view text, absl::uint128* value, - int base); - -static const int kFastToBufferSize = 32; -static const int kSixDigitsToBufferSize = 16; - -// Helper function for fast formatting of floating-point values. -// The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six -// significant digits are returned, trailing zeros are removed, and numbers -// outside the range 0.0001-999999 are output using scientific notation -// (1.23456e+06). This routine is heavily optimized. -// Required buffer size is `kSixDigitsToBufferSize`. -size_t SixDigitsToBuffer(double d, char* buffer); - -// These functions are intended for speed. All functions take an output buffer -// as an argument and return a pointer to the last byte they wrote, which is the -// terminating '\0'. At most `kFastToBufferSize` bytes are written. -char* FastIntToBuffer(int32_t, char*); -char* FastIntToBuffer(uint32_t, char*); -char* FastIntToBuffer(int64_t, char*); -char* FastIntToBuffer(uint64_t, char*); - -// For enums and integer types that are not an exact match for the types above, -// use templates to call the appropriate one of the four overloads above. -template <typename int_type> -char* FastIntToBuffer(int_type i, char* buffer) { - static_assert(sizeof(i) <= 64 / 8, - "FastIntToBuffer works only with 64-bit-or-less integers."); - // TODO(jorg): This signed-ness check is used because it works correctly - // with enums, and it also serves to check that int_type is not a pointer. - // If one day something like std::is_signed<enum E> works, switch to it. - if (static_cast<int_type>(1) - 2 < 0) { // Signed - if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit - return FastIntToBuffer(static_cast<int64_t>(i), buffer); - } else { // 32-bit or less - return FastIntToBuffer(static_cast<int32_t>(i), buffer); - } - } else { // Unsigned - if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit - return FastIntToBuffer(static_cast<uint64_t>(i), buffer); - } else { // 32-bit or less - return FastIntToBuffer(static_cast<uint32_t>(i), buffer); - } - } -} - -// Implementation of SimpleAtoi, generalized to support arbitrary base (used -// with base different from 10 elsewhere in Abseil implementation). -template <typename int_type> -ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, - int base) { - static_assert(sizeof(*out) == 4 || sizeof(*out) == 8, - "SimpleAtoi works only with 32-bit or 64-bit integers."); - static_assert(!std::is_floating_point<int_type>::value, - "Use SimpleAtof or SimpleAtod instead."); - bool parsed; - // TODO(jorg): This signed-ness check is used because it works correctly - // with enums, and it also serves to check that int_type is not a pointer. - // If one day something like std::is_signed<enum E> works, switch to it. - if (static_cast<int_type>(1) - 2 < 0) { // Signed - if (sizeof(*out) == 64 / 8) { // 64-bit - int64_t val; - parsed = numbers_internal::safe_strto64_base(s, &val, base); - *out = static_cast<int_type>(val); - } else { // 32-bit - int32_t val; - parsed = numbers_internal::safe_strto32_base(s, &val, base); - *out = static_cast<int_type>(val); - } - } else { // Unsigned - if (sizeof(*out) == 64 / 8) { // 64-bit - uint64_t val; - parsed = numbers_internal::safe_strtou64_base(s, &val, base); - *out = static_cast<int_type>(val); - } else { // 32-bit - uint32_t val; - parsed = numbers_internal::safe_strtou32_base(s, &val, base); - *out = static_cast<int_type>(val); - } - } - return parsed; -} - -// FastHexToBufferZeroPad16() -// -// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but -// without the terminating null character. Thus `out` must be of length >= 16. -// Returns the number of non-pad digits of the output (it can never be zero -// since 0 has one digit). -inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) { -#ifdef __SSE4_2__ - uint64_t be = absl::big_endian::FromHost64(val); - const auto kNibbleMask = _mm_set1_epi8(0xf); - const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword - auto v4 = _mm_srli_epi64(v, 4); // shift 4 right - auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes - auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles - auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars - _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars); -#else - for (int i = 0; i < 8; ++i) { - auto byte = (val >> (56 - 8 * i)) & 0xFF; - auto* hex = &absl::numbers_internal::kHexTable[byte * 2]; - std::memcpy(out + 2 * i, hex, 2); - } -#endif - // | 0x1 so that even 0 has 1 digit. - return 16 - 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); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_NUMBERS_H_ diff --git a/third_party/abseil_cpp/absl/strings/numbers_benchmark.cc b/third_party/abseil_cpp/absl/strings/numbers_benchmark.cc deleted file mode 100644 index 6e79b3e811ff..000000000000 --- a/third_party/abseil_cpp/absl/strings/numbers_benchmark.cc +++ /dev/null @@ -1,286 +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 <cstdint> -#include <random> -#include <string> -#include <type_traits> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/distributions.h" -#include "absl/random/random.h" -#include "absl/strings/numbers.h" - -namespace { - -template <typename T> -void BM_FastIntToBuffer(benchmark::State& state) { - const int inc = state.range(0); - char buf[absl::numbers_internal::kFastToBufferSize]; - // Use the unsigned type to increment to take advantage of well-defined - // modular arithmetic. - typename std::make_unsigned<T>::type x = 0; - for (auto _ : state) { - absl::numbers_internal::FastIntToBuffer(static_cast<T>(x), buf); - x += inc; - } -} -BENCHMARK_TEMPLATE(BM_FastIntToBuffer, int32_t)->Range(0, 1 << 15); -BENCHMARK_TEMPLATE(BM_FastIntToBuffer, int64_t)->Range(0, 1 << 30); - -// Creates an integer that would be printed as `num_digits` repeated 7s in the -// given `base`. `base` must be greater than or equal to 8. -int64_t RepeatedSevens(int num_digits, int base) { - ABSL_RAW_CHECK(base >= 8, ""); - int64_t num = 7; - while (--num_digits) num = base * num + 7; - return num; -} - -void BM_safe_strto32_string(benchmark::State& state) { - const int digits = state.range(0); - const int base = state.range(1); - std::string str(digits, '7'); // valid in octal, decimal and hex - int32_t value = 0; - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::numbers_internal::safe_strto32_base(str, &value, base)); - } - ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), ""); -} -BENCHMARK(BM_safe_strto32_string) - ->ArgPair(1, 8) - ->ArgPair(1, 10) - ->ArgPair(1, 16) - ->ArgPair(2, 8) - ->ArgPair(2, 10) - ->ArgPair(2, 16) - ->ArgPair(4, 8) - ->ArgPair(4, 10) - ->ArgPair(4, 16) - ->ArgPair(8, 8) - ->ArgPair(8, 10) - ->ArgPair(8, 16) - ->ArgPair(10, 8) - ->ArgPair(9, 10); - -void BM_safe_strto64_string(benchmark::State& state) { - const int digits = state.range(0); - const int base = state.range(1); - std::string str(digits, '7'); // valid in octal, decimal and hex - int64_t value = 0; - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::numbers_internal::safe_strto64_base(str, &value, base)); - } - ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), ""); -} -BENCHMARK(BM_safe_strto64_string) - ->ArgPair(1, 8) - ->ArgPair(1, 10) - ->ArgPair(1, 16) - ->ArgPair(2, 8) - ->ArgPair(2, 10) - ->ArgPair(2, 16) - ->ArgPair(4, 8) - ->ArgPair(4, 10) - ->ArgPair(4, 16) - ->ArgPair(8, 8) - ->ArgPair(8, 10) - ->ArgPair(8, 16) - ->ArgPair(16, 8) - ->ArgPair(16, 10) - ->ArgPair(16, 16); - -void BM_safe_strtou32_string(benchmark::State& state) { - const int digits = state.range(0); - const int base = state.range(1); - std::string str(digits, '7'); // valid in octal, decimal and hex - uint32_t value = 0; - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::numbers_internal::safe_strtou32_base(str, &value, base)); - } - ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), ""); -} -BENCHMARK(BM_safe_strtou32_string) - ->ArgPair(1, 8) - ->ArgPair(1, 10) - ->ArgPair(1, 16) - ->ArgPair(2, 8) - ->ArgPair(2, 10) - ->ArgPair(2, 16) - ->ArgPair(4, 8) - ->ArgPair(4, 10) - ->ArgPair(4, 16) - ->ArgPair(8, 8) - ->ArgPair(8, 10) - ->ArgPair(8, 16) - ->ArgPair(10, 8) - ->ArgPair(9, 10); - -void BM_safe_strtou64_string(benchmark::State& state) { - const int digits = state.range(0); - const int base = state.range(1); - std::string str(digits, '7'); // valid in octal, decimal and hex - uint64_t value = 0; - for (auto _ : state) { - benchmark::DoNotOptimize( - absl::numbers_internal::safe_strtou64_base(str, &value, base)); - } - ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), ""); -} -BENCHMARK(BM_safe_strtou64_string) - ->ArgPair(1, 8) - ->ArgPair(1, 10) - ->ArgPair(1, 16) - ->ArgPair(2, 8) - ->ArgPair(2, 10) - ->ArgPair(2, 16) - ->ArgPair(4, 8) - ->ArgPair(4, 10) - ->ArgPair(4, 16) - ->ArgPair(8, 8) - ->ArgPair(8, 10) - ->ArgPair(8, 16) - ->ArgPair(16, 8) - ->ArgPair(16, 10) - ->ArgPair(16, 16); - -// Returns a vector of `num_strings` strings. Each string represents a -// floating point number with `num_digits` digits before the decimal point and -// another `num_digits` digits after. -std::vector<std::string> MakeFloatStrings(int num_strings, int num_digits) { - // For convenience, use a random number generator to generate the test data. - // We don't actually need random properties, so use a fixed seed. - std::minstd_rand0 rng(1); - std::uniform_int_distribution<int> random_digit('0', '9'); - - std::vector<std::string> float_strings(num_strings); - for (std::string& s : float_strings) { - s.reserve(2 * num_digits + 1); - for (int i = 0; i < num_digits; ++i) { - s.push_back(static_cast<char>(random_digit(rng))); - } - s.push_back('.'); - for (int i = 0; i < num_digits; ++i) { - s.push_back(static_cast<char>(random_digit(rng))); - } - } - return float_strings; -} - -template <typename StringType> -StringType GetStringAs(const std::string& s) { - return static_cast<StringType>(s); -} -template <> -const char* GetStringAs<const char*>(const std::string& s) { - return s.c_str(); -} - -template <typename StringType> -std::vector<StringType> GetStringsAs(const std::vector<std::string>& strings) { - std::vector<StringType> result; - result.reserve(strings.size()); - for (const std::string& s : strings) { - result.push_back(GetStringAs<StringType>(s)); - } - return result; -} - -template <typename T> -void BM_SimpleAtof(benchmark::State& state) { - const int num_strings = state.range(0); - const int num_digits = state.range(1); - std::vector<std::string> backing_strings = - MakeFloatStrings(num_strings, num_digits); - std::vector<T> inputs = GetStringsAs<T>(backing_strings); - float value; - for (auto _ : state) { - for (const T& input : inputs) { - benchmark::DoNotOptimize(absl::SimpleAtof(input, &value)); - } - } -} -BENCHMARK_TEMPLATE(BM_SimpleAtof, absl::string_view) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); -BENCHMARK_TEMPLATE(BM_SimpleAtof, const char*) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); -BENCHMARK_TEMPLATE(BM_SimpleAtof, std::string) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); - -template <typename T> -void BM_SimpleAtod(benchmark::State& state) { - const int num_strings = state.range(0); - const int num_digits = state.range(1); - std::vector<std::string> backing_strings = - MakeFloatStrings(num_strings, num_digits); - std::vector<T> inputs = GetStringsAs<T>(backing_strings); - double value; - for (auto _ : state) { - for (const T& input : inputs) { - benchmark::DoNotOptimize(absl::SimpleAtod(input, &value)); - } - } -} -BENCHMARK_TEMPLATE(BM_SimpleAtod, absl::string_view) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); -BENCHMARK_TEMPLATE(BM_SimpleAtod, const char*) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); -BENCHMARK_TEMPLATE(BM_SimpleAtod, std::string) - ->ArgPair(10, 1) - ->ArgPair(10, 2) - ->ArgPair(10, 4) - ->ArgPair(10, 8); - -void BM_FastHexToBufferZeroPad16(benchmark::State& state) { - absl::BitGen rng; - std::vector<uint64_t> nums; - nums.resize(1000); - auto min = std::numeric_limits<uint64_t>::min(); - auto max = std::numeric_limits<uint64_t>::max(); - for (auto& num : nums) { - num = absl::LogUniform(rng, min, max); - } - - char buf[16]; - while (state.KeepRunningBatch(nums.size())) { - for (auto num : nums) { - auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(num, buf); - benchmark::DoNotOptimize(digits); - benchmark::DoNotOptimize(buf); - } - } -} -BENCHMARK(BM_FastHexToBufferZeroPad16); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/numbers_test.cc b/third_party/abseil_cpp/absl/strings/numbers_test.cc deleted file mode 100644 index 4ab67fb669be..000000000000 --- a/third_party/abseil_cpp/absl/strings/numbers_test.cc +++ /dev/null @@ -1,1356 +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 tests string processing functions related to numeric values. - -#include "absl/strings/numbers.h" - -#include <sys/types.h> - -#include <cfenv> // NOLINT(build/c++11) -#include <cinttypes> -#include <climits> -#include <cmath> -#include <cstddef> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <limits> -#include <numeric> -#include <random> -#include <set> -#include <string> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/random/distributions.h" -#include "absl/random/random.h" -#include "absl/strings/internal/numbers_test_common.h" -#include "absl/strings/internal/ostringstream.h" -#include "absl/strings/internal/pow10_helper.h" -#include "absl/strings/str_cat.h" - -namespace { - -using absl::numbers_internal::kSixDigitsToBufferSize; -using absl::numbers_internal::safe_strto32_base; -using absl::numbers_internal::safe_strto64_base; -using absl::numbers_internal::safe_strtou32_base; -using absl::numbers_internal::safe_strtou64_base; -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; - -// Number of floats to test with. -// 5,000,000 is a reasonable default for a test that only takes a few seconds. -// 1,000,000,000+ triggers checking for all possible mantissa values for -// double-precision tests. 2,000,000,000+ triggers checking for every possible -// single-precision float. -const int kFloatNumCases = 5000000; - -// This is a slow, brute-force routine to compute the exact base-10 -// representation of a double-precision floating-point number. It -// is useful for debugging only. -std::string PerfectDtoa(double d) { - if (d == 0) return "0"; - if (d < 0) return "-" + PerfectDtoa(-d); - - // Basic theory: decompose d into mantissa and exp, where - // d = mantissa * 2^exp, and exp is as close to zero as possible. - int64_t mantissa, exp = 0; - while (d >= 1ULL << 63) ++exp, d *= 0.5; - while ((mantissa = d) != d) --exp, d *= 2.0; - - // Then convert mantissa to ASCII, and either double it (if - // exp > 0) or halve it (if exp < 0) repeatedly. "halve it" - // in this case means multiplying it by five and dividing by 10. - constexpr int maxlen = 1100; // worst case is actually 1030 or so. - char buf[maxlen + 5]; - for (int64_t num = mantissa, pos = maxlen; --pos >= 0;) { - buf[pos] = '0' + (num % 10); - num /= 10; - } - char* begin = &buf[0]; - char* end = buf + maxlen; - for (int i = 0; i != exp; i += (exp > 0) ? 1 : -1) { - int carry = 0; - for (char* p = end; --p != begin;) { - int dig = *p - '0'; - dig = dig * (exp > 0 ? 2 : 5) + carry; - carry = dig / 10; - dig %= 10; - *p = '0' + dig; - } - } - if (exp < 0) { - // "dividing by 10" above means we have to add the decimal point. - memmove(end + 1 + exp, end + exp, 1 - exp); - end[exp] = '.'; - ++end; - } - while (*begin == '0' && begin[1] != '.') ++begin; - return {begin, end}; -} - -TEST(ToString, PerfectDtoa) { - EXPECT_THAT(PerfectDtoa(1), Eq("1")); - EXPECT_THAT(PerfectDtoa(0.1), - Eq("0.1000000000000000055511151231257827021181583404541015625")); - EXPECT_THAT(PerfectDtoa(1e24), Eq("999999999999999983222784")); - EXPECT_THAT(PerfectDtoa(5e-324), MatchesRegex("0.0000.*625")); - for (int i = 0; i < 100; ++i) { - for (double multiplier : - {1e-300, 1e-200, 1e-100, 0.1, 1.0, 10.0, 1e100, 1e300}) { - double d = multiplier * i; - std::string s = PerfectDtoa(d); - EXPECT_DOUBLE_EQ(d, strtod(s.c_str(), nullptr)); - } - } -} - -template <typename integer> -struct MyInteger { - integer i; - explicit constexpr MyInteger(integer i) : i(i) {} - constexpr operator integer() const { return i; } - - constexpr MyInteger operator+(MyInteger other) const { return i + other.i; } - constexpr MyInteger operator-(MyInteger other) const { return i - other.i; } - constexpr MyInteger operator*(MyInteger other) const { return i * other.i; } - constexpr MyInteger operator/(MyInteger other) const { return i / other.i; } - - constexpr bool operator<(MyInteger other) const { return i < other.i; } - constexpr bool operator<=(MyInteger other) const { return i <= other.i; } - constexpr bool operator==(MyInteger other) const { return i == other.i; } - constexpr bool operator>=(MyInteger other) const { return i >= other.i; } - constexpr bool operator>(MyInteger other) const { return i > other.i; } - constexpr bool operator!=(MyInteger other) const { return i != other.i; } - - integer as_integer() const { return i; } -}; - -typedef MyInteger<int64_t> MyInt64; -typedef MyInteger<uint64_t> MyUInt64; - -void CheckInt32(int32_t x) { - char buffer[absl::numbers_internal::kFastToBufferSize]; - char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer); - std::string expected = std::to_string(x); - EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x; - - char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer); - EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x; -} - -void CheckInt64(int64_t x) { - char buffer[absl::numbers_internal::kFastToBufferSize + 3]; - buffer[0] = '*'; - buffer[23] = '*'; - buffer[24] = '*'; - char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]); - std::string expected = std::to_string(x); - EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x; - EXPECT_EQ(buffer[0], '*'); - EXPECT_EQ(buffer[23], '*'); - EXPECT_EQ(buffer[24], '*'); - - char* my_actual = - absl::numbers_internal::FastIntToBuffer(MyInt64(x), &buffer[1]); - EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x; -} - -void CheckUInt32(uint32_t x) { - char buffer[absl::numbers_internal::kFastToBufferSize]; - char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer); - std::string expected = std::to_string(x); - EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x; - - char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer); - EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x; -} - -void CheckUInt64(uint64_t x) { - char buffer[absl::numbers_internal::kFastToBufferSize + 1]; - char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]); - std::string expected = std::to_string(x); - EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x; - - char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]); - EXPECT_EQ(expected, std::string(&buffer[1], generic_actual)) - << " Input " << x; - - char* my_actual = - absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]); - EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x; -} - -void CheckHex64(uint64_t v) { - char expected[16 + 1]; - std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16)); - snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v)); - EXPECT_EQ(expected, actual) << " Input " << v; - actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16)); - snprintf(expected, sizeof(expected), "%16" PRIx64, static_cast<uint64_t>(v)); - EXPECT_EQ(expected, actual) << " Input " << v; -} - -TEST(Numbers, TestFastPrints) { - for (int i = -100; i <= 100; i++) { - CheckInt32(i); - CheckInt64(i); - } - for (int i = 0; i <= 100; i++) { - CheckUInt32(i); - CheckUInt64(i); - } - // Test min int to make sure that works - CheckInt32(INT_MIN); - CheckInt32(INT_MAX); - CheckInt64(LONG_MIN); - CheckInt64(uint64_t{1000000000}); - CheckInt64(uint64_t{9999999999}); - CheckInt64(uint64_t{100000000000000}); - CheckInt64(uint64_t{999999999999999}); - CheckInt64(uint64_t{1000000000000000000}); - CheckInt64(uint64_t{1199999999999999999}); - CheckInt64(int64_t{-700000000000000000}); - CheckInt64(LONG_MAX); - CheckUInt32(std::numeric_limits<uint32_t>::max()); - CheckUInt64(uint64_t{1000000000}); - CheckUInt64(uint64_t{9999999999}); - CheckUInt64(uint64_t{100000000000000}); - CheckUInt64(uint64_t{999999999999999}); - CheckUInt64(uint64_t{1000000000000000000}); - CheckUInt64(uint64_t{1199999999999999999}); - CheckUInt64(std::numeric_limits<uint64_t>::max()); - - for (int i = 0; i < 10000; i++) { - CheckHex64(i); - } - CheckHex64(uint64_t{0x123456789abcdef0}); -} - -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. - absl::strings_internal::OStringStream(&s) << in_value; - int_type x = static_cast<int_type>(~exp_value); - EXPECT_TRUE(SimpleAtoi(s, &x)) - << "in_value=" << in_value << " s=" << s << " x=" << x; - EXPECT_EQ(exp_value, x); - x = static_cast<int_type>(~exp_value); - EXPECT_TRUE(SimpleAtoi(s.c_str(), &x)); - EXPECT_EQ(exp_value, x); -} - -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; - int_type x; - EXPECT_FALSE(SimpleAtoi(s, &x)); - EXPECT_FALSE(SimpleAtoi(s.c_str(), &x)); -} - -TEST(NumbersTest, Atoi) { - // SimpleAtoi(absl::string_view, int32_t) - VerifySimpleAtoiGood<int32_t>(0, 0); - VerifySimpleAtoiGood<int32_t>(42, 42); - VerifySimpleAtoiGood<int32_t>(-42, -42); - - VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(), - std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - - // SimpleAtoi(absl::string_view, uint32_t) - VerifySimpleAtoiGood<uint32_t>(0, 0); - VerifySimpleAtoiGood<uint32_t>(42, 42); - VerifySimpleAtoiBad<uint32_t>(-42); - - VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(), - std::numeric_limits<uint32_t>::max()); - VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min()); - VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max()); - VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max()); - - // SimpleAtoi(absl::string_view, int64_t) - VerifySimpleAtoiGood<int64_t>(0, 0); - VerifySimpleAtoiGood<int64_t>(42, 42); - VerifySimpleAtoiGood<int64_t>(-42, -42); - - VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(), - std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - VerifySimpleAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(), - std::numeric_limits<uint32_t>::max()); - VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(), - std::numeric_limits<int64_t>::min()); - VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(), - std::numeric_limits<int64_t>::max()); - VerifySimpleAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max()); - - // SimpleAtoi(absl::string_view, uint64_t) - VerifySimpleAtoiGood<uint64_t>(0, 0); - VerifySimpleAtoiGood<uint64_t>(42, 42); - VerifySimpleAtoiBad<uint64_t>(-42); - - VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(), - std::numeric_limits<uint32_t>::max()); - VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min()); - VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(), - std::numeric_limits<int64_t>::max()); - VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(), - std::numeric_limits<uint64_t>::max()); - - // SimpleAtoi(absl::string_view, absl::uint128) - VerifySimpleAtoiGood<absl::uint128>(0, 0); - VerifySimpleAtoiGood<absl::uint128>(42, 42); - VerifySimpleAtoiBad<absl::uint128>(-42); - - VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(), - std::numeric_limits<uint32_t>::max()); - VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min()); - VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(), - std::numeric_limits<int64_t>::max()); - VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(), - std::numeric_limits<uint64_t>::max()); - VerifySimpleAtoiGood<absl::uint128>( - std::numeric_limits<absl::uint128>::max(), - std::numeric_limits<absl::uint128>::max()); - - // SimpleAtoi(absl::string_view, absl::int128) - VerifySimpleAtoiGood<absl::int128>(0, 0); - VerifySimpleAtoiGood<absl::int128>(42, 42); - VerifySimpleAtoiGood<absl::int128>(-42, -42); - - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(), - std::numeric_limits<int32_t>::min()); - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(), - std::numeric_limits<int32_t>::max()); - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(), - std::numeric_limits<uint32_t>::max()); - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(), - std::numeric_limits<int64_t>::min()); - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(), - std::numeric_limits<int64_t>::max()); - VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(), - std::numeric_limits<uint64_t>::max()); - VerifySimpleAtoiGood<absl::int128>( - std::numeric_limits<absl::int128>::min(), - std::numeric_limits<absl::int128>::min()); - VerifySimpleAtoiGood<absl::int128>( - std::numeric_limits<absl::int128>::max(), - std::numeric_limits<absl::int128>::max()); - VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max()); - - // Some other types - VerifySimpleAtoiGood<int>(-42, -42); - VerifySimpleAtoiGood<int32_t>(-42, -42); - VerifySimpleAtoiGood<uint32_t>(42, 42); - VerifySimpleAtoiGood<unsigned int>(42, 42); - VerifySimpleAtoiGood<int64_t>(-42, -42); - VerifySimpleAtoiGood<long>(-42, -42); // NOLINT(runtime/int) - VerifySimpleAtoiGood<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, Atoenum) { - enum E01 { - E01_zero = 0, - E01_one = 1, - }; - - VerifySimpleAtoiGood<E01>(E01_zero, E01_zero); - VerifySimpleAtoiGood<E01>(E01_one, E01_one); - - enum E_101 { - E_101_minusone = -1, - E_101_zero = 0, - E_101_one = 1, - }; - - VerifySimpleAtoiGood<E_101>(E_101_minusone, E_101_minusone); - VerifySimpleAtoiGood<E_101>(E_101_zero, E_101_zero); - VerifySimpleAtoiGood<E_101>(E_101_one, E_101_one); - - enum E_bigint { - E_bigint_zero = 0, - E_bigint_one = 1, - E_bigint_max31 = static_cast<int32_t>(0x7FFFFFFF), - }; - - VerifySimpleAtoiGood<E_bigint>(E_bigint_zero, E_bigint_zero); - VerifySimpleAtoiGood<E_bigint>(E_bigint_one, E_bigint_one); - VerifySimpleAtoiGood<E_bigint>(E_bigint_max31, E_bigint_max31); - - enum E_fullint { - E_fullint_zero = 0, - E_fullint_one = 1, - E_fullint_max31 = static_cast<int32_t>(0x7FFFFFFF), - E_fullint_min32 = INT32_MIN, - }; - - VerifySimpleAtoiGood<E_fullint>(E_fullint_zero, E_fullint_zero); - VerifySimpleAtoiGood<E_fullint>(E_fullint_one, E_fullint_one); - VerifySimpleAtoiGood<E_fullint>(E_fullint_max31, E_fullint_max31); - VerifySimpleAtoiGood<E_fullint>(E_fullint_min32, E_fullint_min32); - - enum E_biguint { - E_biguint_zero = 0, - E_biguint_one = 1, - E_biguint_max31 = static_cast<uint32_t>(0x7FFFFFFF), - E_biguint_max32 = static_cast<uint32_t>(0xFFFFFFFF), - }; - - VerifySimpleAtoiGood<E_biguint>(E_biguint_zero, E_biguint_zero); - VerifySimpleAtoiGood<E_biguint>(E_biguint_one, E_biguint_one); - VerifySimpleAtoiGood<E_biguint>(E_biguint_max31, E_biguint_max31); - VerifySimpleAtoiGood<E_biguint>(E_biguint_max32, E_biguint_max32); -} - -TEST(stringtest, safe_strto32_base) { - 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); - - EXPECT_TRUE(safe_strto32_base("34234324", &value, 16)); - EXPECT_EQ(0x34234324, value); - - EXPECT_TRUE(safe_strto32_base("0", &value, 16)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto32_base(" \t\n -0x34234324", &value, 16)); - EXPECT_EQ(-0x34234324, value); - - EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 16)); - EXPECT_EQ(-0x34234324, value); - - EXPECT_TRUE(safe_strto32_base("7654321", &value, 8)); - EXPECT_EQ(07654321, value); - - EXPECT_TRUE(safe_strto32_base("-01234", &value, 8)); - EXPECT_EQ(-01234, value); - - EXPECT_FALSE(safe_strto32_base("1834", &value, 8)); - - // Autodetect base. - EXPECT_TRUE(safe_strto32_base("0", &value, 0)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto32_base("077", &value, 0)); - EXPECT_EQ(077, value); // Octal interpretation - - // Leading zero indicates octal, but then followed by invalid digit. - EXPECT_FALSE(safe_strto32_base("088", &value, 0)); - - // Leading 0x indicated hex, but then followed by invalid digit. - EXPECT_FALSE(safe_strto32_base("0xG", &value, 0)); - - // Base-10 version. - EXPECT_TRUE(safe_strto32_base("34234324", &value, 10)); - EXPECT_EQ(34234324, value); - - EXPECT_TRUE(safe_strto32_base("0", &value, 10)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 10)); - EXPECT_EQ(-34234324, value); - - EXPECT_TRUE(safe_strto32_base("34234324 \n\t ", &value, 10)); - EXPECT_EQ(34234324, value); - - // Invalid ints. - EXPECT_FALSE(safe_strto32_base("", &value, 10)); - EXPECT_FALSE(safe_strto32_base(" ", &value, 10)); - EXPECT_FALSE(safe_strto32_base("abc", &value, 10)); - EXPECT_FALSE(safe_strto32_base("34234324a", &value, 10)); - EXPECT_FALSE(safe_strto32_base("34234.3", &value, 10)); - - // Out of bounds. - EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10)); - EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10)); - - // String version. - EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16)); - EXPECT_EQ(0x1234, value); - - // Base-10 string version. - EXPECT_TRUE(safe_strto32_base("1234", &value, 10)); - EXPECT_EQ(1234, value); -} - -TEST(stringtest, safe_strto32_range) { - // These tests verify underflow/overflow behaviour. - int32_t value; - EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10)); - EXPECT_EQ(std::numeric_limits<int32_t>::max(), value); - - EXPECT_TRUE(safe_strto32_base("-2147483648", &value, 10)); - EXPECT_EQ(std::numeric_limits<int32_t>::min(), value); - - EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10)); - EXPECT_EQ(std::numeric_limits<int32_t>::min(), value); -} - -TEST(stringtest, safe_strto64_range) { - // These tests verify underflow/overflow behaviour. - int64_t value; - EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10)); - EXPECT_EQ(std::numeric_limits<int64_t>::max(), value); - - EXPECT_TRUE(safe_strto64_base("-9223372036854775808", &value, 10)); - EXPECT_EQ(std::numeric_limits<int64_t>::min(), value); - - EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10)); - EXPECT_EQ(std::numeric_limits<int64_t>::min(), value); -} - -TEST(stringtest, safe_strto32_leading_substring) { - // These tests verify this comment in numbers.h: - // On error, returns false, and sets *value to: [...] - // conversion of leading substring if available ("123@@@" -> 123) - // 0 if no leading substring available - int32_t value; - EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 10)); - EXPECT_EQ(4069, value); - - EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 8)); - EXPECT_EQ(0406, value); - - EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 10)); - EXPECT_EQ(4069, value); - - EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 16)); - EXPECT_EQ(0x4069ba, value); - - EXPECT_FALSE(safe_strto32_base("@@@", &value, 10)); - EXPECT_EQ(0, value); // there was no leading substring -} - -TEST(stringtest, safe_strto64_leading_substring) { - // These tests verify this comment in numbers.h: - // On error, returns false, and sets *value to: [...] - // conversion of leading substring if available ("123@@@" -> 123) - // 0 if no leading substring available - int64_t value; - EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 10)); - EXPECT_EQ(4069, value); - - EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 8)); - EXPECT_EQ(0406, value); - - EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 10)); - EXPECT_EQ(4069, value); - - EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 16)); - EXPECT_EQ(0x4069ba, value); - - EXPECT_FALSE(safe_strto64_base("@@@", &value, 10)); - EXPECT_EQ(0, value); // there was no leading substring -} - -TEST(stringtest, safe_strto64_base) { - int64_t value; - EXPECT_TRUE(safe_strto64_base("0x3423432448783446", &value, 16)); - EXPECT_EQ(int64_t{0x3423432448783446}, value); - - EXPECT_TRUE(safe_strto64_base("3423432448783446", &value, 16)); - EXPECT_EQ(int64_t{0x3423432448783446}, value); - - EXPECT_TRUE(safe_strto64_base("0", &value, 16)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto64_base(" \t\n -0x3423432448783446", &value, 16)); - EXPECT_EQ(int64_t{-0x3423432448783446}, value); - - EXPECT_TRUE(safe_strto64_base(" \t\n -3423432448783446", &value, 16)); - EXPECT_EQ(int64_t{-0x3423432448783446}, value); - - EXPECT_TRUE(safe_strto64_base("123456701234567012", &value, 8)); - EXPECT_EQ(int64_t{0123456701234567012}, value); - - EXPECT_TRUE(safe_strto64_base("-017777777777777", &value, 8)); - EXPECT_EQ(int64_t{-017777777777777}, value); - - EXPECT_FALSE(safe_strto64_base("19777777777777", &value, 8)); - - // Autodetect base. - EXPECT_TRUE(safe_strto64_base("0", &value, 0)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto64_base("077", &value, 0)); - EXPECT_EQ(077, value); // Octal interpretation - - // Leading zero indicates octal, but then followed by invalid digit. - EXPECT_FALSE(safe_strto64_base("088", &value, 0)); - - // Leading 0x indicated hex, but then followed by invalid digit. - EXPECT_FALSE(safe_strto64_base("0xG", &value, 0)); - - // Base-10 version. - EXPECT_TRUE(safe_strto64_base("34234324487834466", &value, 10)); - EXPECT_EQ(int64_t{34234324487834466}, value); - - EXPECT_TRUE(safe_strto64_base("0", &value, 10)); - EXPECT_EQ(0, value); - - EXPECT_TRUE(safe_strto64_base(" \t\n -34234324487834466", &value, 10)); - EXPECT_EQ(int64_t{-34234324487834466}, value); - - EXPECT_TRUE(safe_strto64_base("34234324487834466 \n\t ", &value, 10)); - EXPECT_EQ(int64_t{34234324487834466}, value); - - // Invalid ints. - EXPECT_FALSE(safe_strto64_base("", &value, 10)); - EXPECT_FALSE(safe_strto64_base(" ", &value, 10)); - EXPECT_FALSE(safe_strto64_base("abc", &value, 10)); - EXPECT_FALSE(safe_strto64_base("34234324487834466a", &value, 10)); - EXPECT_FALSE(safe_strto64_base("34234487834466.3", &value, 10)); - - // Out of bounds. - EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10)); - EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10)); - - // String version. - EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16)); - EXPECT_EQ(0x1234, value); - - // Base-10 string version. - EXPECT_TRUE(safe_strto64_base("1234", &value, 10)); - EXPECT_EQ(1234, value); -} - -const size_t kNumRandomTests = 10000; - -template <typename IntType> -void test_random_integer_parse_base(bool (*parse_func)(absl::string_view, - IntType* value, - int base)) { - using RandomEngine = std::minstd_rand0; - std::random_device rd; - RandomEngine rng(rd()); - std::uniform_int_distribution<IntType> random_int( - std::numeric_limits<IntType>::min()); - std::uniform_int_distribution<int> random_base(2, 35); - for (size_t i = 0; i < kNumRandomTests; i++) { - IntType value = random_int(rng); - int base = random_base(rng); - std::string str_value; - EXPECT_TRUE(Itoa<IntType>(value, base, &str_value)); - IntType parsed_value; - - // Test successful parse - EXPECT_TRUE(parse_func(str_value, &parsed_value, base)); - EXPECT_EQ(parsed_value, value); - - // Test overflow - EXPECT_FALSE( - parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value), - &parsed_value, base)); - - // Test underflow - if (std::numeric_limits<IntType>::min() < 0) { - EXPECT_FALSE( - parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value), - &parsed_value, base)); - } else { - EXPECT_FALSE(parse_func(absl::StrCat("-", value), &parsed_value, base)); - } - } -} - -TEST(stringtest, safe_strto32_random) { - test_random_integer_parse_base<int32_t>(&safe_strto32_base); -} -TEST(stringtest, safe_strto64_random) { - test_random_integer_parse_base<int64_t>(&safe_strto64_base); -} -TEST(stringtest, safe_strtou32_random) { - test_random_integer_parse_base<uint32_t>(&safe_strtou32_base); -} -TEST(stringtest, safe_strtou64_random) { - test_random_integer_parse_base<uint64_t>(&safe_strtou64_base); -} -TEST(stringtest, safe_strtou128_random) { - // random number generators don't work for uint128, and - // uint128 can be streamed but not StrCat'd, so this code must be custom - // implemented for uint128, but is generally the same as what's above. - // test_random_integer_parse_base<absl::uint128>( - // &absl::numbers_internal::safe_strtou128_base); - using RandomEngine = std::minstd_rand0; - using IntType = absl::uint128; - constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base; - - std::random_device rd; - RandomEngine rng(rd()); - std::uniform_int_distribution<uint64_t> random_uint64( - std::numeric_limits<uint64_t>::min()); - std::uniform_int_distribution<int> random_base(2, 35); - - for (size_t i = 0; i < kNumRandomTests; i++) { - IntType value = random_uint64(rng); - value = (value << 64) + random_uint64(rng); - int base = random_base(rng); - std::string str_value; - EXPECT_TRUE(Itoa<IntType>(value, base, &str_value)); - IntType parsed_value; - - // Test successful parse - EXPECT_TRUE(parse_func(str_value, &parsed_value, base)); - EXPECT_EQ(parsed_value, value); - - // Test overflow - std::string s; - absl::strings_internal::OStringStream(&s) - << std::numeric_limits<IntType>::max() << value; - EXPECT_FALSE(parse_func(s, &parsed_value, base)); - - // Test underflow - s.clear(); - absl::strings_internal::OStringStream(&s) << "-" << value; - EXPECT_FALSE(parse_func(s, &parsed_value, base)); - } -} -TEST(stringtest, safe_strto128_random) { - // random number generators don't work for int128, and - // int128 can be streamed but not StrCat'd, so this code must be custom - // implemented for int128, but is generally the same as what's above. - // test_random_integer_parse_base<absl::int128>( - // &absl::numbers_internal::safe_strto128_base); - using RandomEngine = std::minstd_rand0; - using IntType = absl::int128; - constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base; - - std::random_device rd; - RandomEngine rng(rd()); - std::uniform_int_distribution<int64_t> random_int64( - std::numeric_limits<int64_t>::min()); - std::uniform_int_distribution<uint64_t> random_uint64( - std::numeric_limits<uint64_t>::min()); - std::uniform_int_distribution<int> random_base(2, 35); - - for (size_t i = 0; i < kNumRandomTests; ++i) { - int64_t high = random_int64(rng); - uint64_t low = random_uint64(rng); - IntType value = absl::MakeInt128(high, low); - - int base = random_base(rng); - std::string str_value; - EXPECT_TRUE(Itoa<IntType>(value, base, &str_value)); - IntType parsed_value; - - // Test successful parse - EXPECT_TRUE(parse_func(str_value, &parsed_value, base)); - EXPECT_EQ(parsed_value, value); - - // Test overflow - std::string s; - absl::strings_internal::OStringStream(&s) - << std::numeric_limits<IntType>::max() << value; - EXPECT_FALSE(parse_func(s, &parsed_value, base)); - - // Test underflow - s.clear(); - absl::strings_internal::OStringStream(&s) - << std::numeric_limits<IntType>::min() << value; - EXPECT_FALSE(parse_func(s, &parsed_value, base)); - } -} - -TEST(stringtest, safe_strtou32_base) { - for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) { - const auto& e = strtouint32_test_cases()[i]; - uint32_t value; - EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base)) - << "str=\"" << e.str << "\" base=" << e.base; - if (e.expect_ok) { - EXPECT_EQ(e.expected, value) << "i=" << i << " str=\"" << e.str - << "\" base=" << e.base; - } - } -} - -TEST(stringtest, safe_strtou32_base_length_delimited) { - for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) { - const auto& e = strtouint32_test_cases()[i]; - std::string tmp(e.str); - tmp.append("12"); // Adds garbage at the end. - - uint32_t value; - EXPECT_EQ(e.expect_ok, - safe_strtou32_base(absl::string_view(tmp.data(), strlen(e.str)), - &value, e.base)) - << "str=\"" << e.str << "\" base=" << e.base; - if (e.expect_ok) { - EXPECT_EQ(e.expected, value) << "i=" << i << " str=" << e.str - << " base=" << e.base; - } - } -} - -TEST(stringtest, safe_strtou64_base) { - for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) { - const auto& e = strtouint64_test_cases()[i]; - uint64_t value; - EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base)) - << "str=\"" << e.str << "\" base=" << e.base; - if (e.expect_ok) { - EXPECT_EQ(e.expected, value) << "str=" << e.str << " base=" << e.base; - } - } -} - -TEST(stringtest, safe_strtou64_base_length_delimited) { - for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) { - const auto& e = strtouint64_test_cases()[i]; - std::string tmp(e.str); - tmp.append("12"); // Adds garbage at the end. - - uint64_t value; - EXPECT_EQ(e.expect_ok, - safe_strtou64_base(absl::string_view(tmp.data(), strlen(e.str)), - &value, e.base)) - << "str=\"" << e.str << "\" base=" << e.base; - if (e.expect_ok) { - EXPECT_EQ(e.expected, value) << "str=\"" << e.str << "\" base=" << e.base; - } - } -} - -// feenableexcept() and fedisableexcept() are extensions supported by some libc -// implementations. -#if defined(__GLIBC__) || defined(__BIONIC__) -#define ABSL_HAVE_FEENABLEEXCEPT 1 -#define ABSL_HAVE_FEDISABLEEXCEPT 1 -#endif - -class SimpleDtoaTest : public testing::Test { - protected: - void SetUp() override { - // Store the current floating point env & clear away any pending exceptions. - feholdexcept(&fp_env_); -#ifdef ABSL_HAVE_FEENABLEEXCEPT - // Turn on floating point exceptions. - feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); -#endif - } - - void TearDown() override { - // Restore the floating point environment to the original state. - // In theory fedisableexcept is unnecessary; fesetenv will also do it. - // In practice, our toolchains have subtle bugs. -#ifdef ABSL_HAVE_FEDISABLEEXCEPT - fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); -#endif - fesetenv(&fp_env_); - } - - std::string ToNineDigits(double value) { - char buffer[16]; // more than enough for %.9g - snprintf(buffer, sizeof(buffer), "%.9g", value); - return buffer; - } - - fenv_t fp_env_; -}; - -// Run the given runnable functor for "cases" test cases, chosen over the -// available range of float. pi and e and 1/e are seeded, and then all -// available integer powers of 2 and 10 are multiplied against them. In -// addition to trying all those values, we try the next higher and next lower -// float, and then we add additional test cases evenly distributed between them. -// Each test case is passed to runnable as both a positive and negative value. -template <typename R> -void ExhaustiveFloat(uint32_t cases, R&& runnable) { - runnable(0.0f); - runnable(-0.0f); - if (cases >= 2e9) { // more than 2 billion? Might as well run them all. - for (float f = 0; f < std::numeric_limits<float>::max(); ) { - f = nextafterf(f, std::numeric_limits<float>::max()); - runnable(-f); - runnable(f); - } - return; - } - std::set<float> floats = {3.4028234e38f}; - for (float f : {1.0, 3.14159265, 2.718281828, 1 / 2.718281828}) { - for (float testf = f; testf != 0; testf *= 0.1f) floats.insert(testf); - for (float testf = f; testf != 0; testf *= 0.5f) floats.insert(testf); - for (float testf = f; testf < 3e38f / 2; testf *= 2.0f) - floats.insert(testf); - for (float testf = f; testf < 3e38f / 10; testf *= 10) floats.insert(testf); - } - - float last = *floats.begin(); - - runnable(last); - runnable(-last); - int iters_per_float = cases / floats.size(); - if (iters_per_float == 0) iters_per_float = 1; - for (float f : floats) { - if (f == last) continue; - float testf = std::nextafter(last, std::numeric_limits<float>::max()); - runnable(testf); - runnable(-testf); - last = testf; - if (f == last) continue; - double step = (double{f} - last) / iters_per_float; - for (double d = last + step; d < f; d += step) { - testf = d; - if (testf != last) { - runnable(testf); - runnable(-testf); - last = testf; - } - } - testf = std::nextafter(f, 0.0f); - if (testf > last) { - runnable(testf); - runnable(-testf); - last = testf; - } - if (f != last) { - runnable(f); - runnable(-f); - last = f; - } - } -} - -TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) { - uint64_t test_count = 0; - std::vector<double> mismatches; - auto checker = [&](double d) { - if (d != d) return; // rule out NaNs - ++test_count; - char sixdigitsbuf[kSixDigitsToBufferSize] = {0}; - SixDigitsToBuffer(d, sixdigitsbuf); - char snprintfbuf[kSixDigitsToBufferSize] = {0}; - snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d); - if (strcmp(sixdigitsbuf, snprintfbuf) != 0) { - mismatches.push_back(d); - if (mismatches.size() < 10) { - ABSL_RAW_LOG(ERROR, "%s", - absl::StrCat("Six-digit failure with double. ", "d=", d, - "=", d, " sixdigits=", sixdigitsbuf, - " printf(%g)=", snprintfbuf) - .c_str()); - } - } - }; - // Some quick sanity checks... - checker(5e-324); - checker(1e-308); - checker(1.0); - checker(1.000005); - checker(1.7976931348623157e308); - checker(0.00390625); -#ifndef _MSC_VER - // on MSVC, snprintf() rounds it to 0.00195313. SixDigitsToBuffer() rounds it - // to 0.00195312 (round half to even). - checker(0.001953125); -#endif - checker(0.005859375); - // Some cases where the rounding is very very close - checker(1.089095e-15); - checker(3.274195e-55); - checker(6.534355e-146); - checker(2.920845e+234); - - if (mismatches.empty()) { - test_count = 0; - ExhaustiveFloat(kFloatNumCases, checker); - - test_count = 0; - std::vector<int> digit_testcases{ - 100000, 100001, 100002, 100005, 100010, 100020, 100050, 100100, // misc - 195312, 195313, // 1.953125 is a case where we round down, just barely. - 200000, 500000, 800000, // misc mid-range cases - 585937, 585938, // 5.859375 is a case where we round up, just barely. - 900000, 990000, 999000, 999900, 999990, 999996, 999997, 999998, 999999}; - if (kFloatNumCases >= 1e9) { - // If at least 1 billion test cases were requested, user wants an - // exhaustive test. So let's test all mantissas, too. - constexpr int min_mantissa = 100000, max_mantissa = 999999; - digit_testcases.resize(max_mantissa - min_mantissa + 1); - std::iota(digit_testcases.begin(), digit_testcases.end(), min_mantissa); - } - - for (int exponent = -324; exponent <= 308; ++exponent) { - double powten = absl::strings_internal::Pow10(exponent); - if (powten == 0) powten = 5e-324; - if (kFloatNumCases >= 1e9) { - // The exhaustive test takes a very long time, so log progress. - char buf[kSixDigitsToBufferSize]; - ABSL_RAW_LOG( - INFO, "%s", - absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten, - ") (", - std::string(buf, SixDigitsToBuffer(powten, buf)), ")") - .c_str()); - } - for (int digits : digit_testcases) { - if (exponent == 308 && digits >= 179769) break; // don't overflow! - double digiform = (digits + 0.5) * 0.00001; - double testval = digiform * powten; - double pretestval = nextafter(testval, 0); - double posttestval = nextafter(testval, 1.7976931348623157e308); - checker(testval); - checker(pretestval); - checker(posttestval); - } - } - } else { - EXPECT_EQ(mismatches.size(), 0); - for (size_t i = 0; i < mismatches.size(); ++i) { - if (i > 100) i = mismatches.size() - 1; - double d = mismatches[i]; - char sixdigitsbuf[kSixDigitsToBufferSize] = {0}; - SixDigitsToBuffer(d, sixdigitsbuf); - char snprintfbuf[kSixDigitsToBufferSize] = {0}; - snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d); - double before = nextafter(d, 0.0); - double after = nextafter(d, 1.7976931348623157e308); - char b1[32], b2[kSixDigitsToBufferSize]; - ABSL_RAW_LOG( - ERROR, "%s", - absl::StrCat( - "Mismatch #", i, " d=", d, " (", ToNineDigits(d), ")", - " sixdigits='", sixdigitsbuf, "'", " snprintf='", snprintfbuf, - "'", " Before.=", PerfectDtoa(before), " ", - (SixDigitsToBuffer(before, b2), b2), - " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", before), b1), - " Perfect=", PerfectDtoa(d), " ", (SixDigitsToBuffer(d, b2), b2), - " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", d), b1), - " After.=.", PerfectDtoa(after), " ", - (SixDigitsToBuffer(after, b2), b2), - " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", after), b1)) - .c_str()); - } - } -} - -TEST(StrToInt32, Partial) { - struct Int32TestLine { - std::string input; - bool status; - int32_t value; - }; - const int32_t int32_min = std::numeric_limits<int32_t>::min(); - const int32_t int32_max = std::numeric_limits<int32_t>::max(); - Int32TestLine int32_test_line[] = { - {"", false, 0}, - {" ", false, 0}, - {"-", false, 0}, - {"123@@@", false, 123}, - {absl::StrCat(int32_min, int32_max), false, int32_min}, - {absl::StrCat(int32_max, int32_max), false, int32_max}, - }; - - for (const Int32TestLine& test_line : int32_test_line) { - int32_t value = -2; - bool status = safe_strto32_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = -2; - status = safe_strto32_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = -2; - status = safe_strto32_base(absl::string_view(test_line.input), &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - } -} - -TEST(StrToUint32, Partial) { - struct Uint32TestLine { - std::string input; - bool status; - uint32_t value; - }; - const uint32_t uint32_max = std::numeric_limits<uint32_t>::max(); - Uint32TestLine uint32_test_line[] = { - {"", false, 0}, - {" ", false, 0}, - {"-", false, 0}, - {"123@@@", false, 123}, - {absl::StrCat(uint32_max, uint32_max), false, uint32_max}, - }; - - for (const Uint32TestLine& test_line : uint32_test_line) { - uint32_t value = 2; - bool status = safe_strtou32_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = 2; - status = safe_strtou32_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = 2; - status = safe_strtou32_base(absl::string_view(test_line.input), &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - } -} - -TEST(StrToInt64, Partial) { - struct Int64TestLine { - std::string input; - bool status; - int64_t value; - }; - const int64_t int64_min = std::numeric_limits<int64_t>::min(); - const int64_t int64_max = std::numeric_limits<int64_t>::max(); - Int64TestLine int64_test_line[] = { - {"", false, 0}, - {" ", false, 0}, - {"-", false, 0}, - {"123@@@", false, 123}, - {absl::StrCat(int64_min, int64_max), false, int64_min}, - {absl::StrCat(int64_max, int64_max), false, int64_max}, - }; - - for (const Int64TestLine& test_line : int64_test_line) { - int64_t value = -2; - bool status = safe_strto64_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = -2; - status = safe_strto64_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = -2; - status = safe_strto64_base(absl::string_view(test_line.input), &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - } -} - -TEST(StrToUint64, Partial) { - struct Uint64TestLine { - std::string input; - bool status; - uint64_t value; - }; - const uint64_t uint64_max = std::numeric_limits<uint64_t>::max(); - Uint64TestLine uint64_test_line[] = { - {"", false, 0}, - {" ", false, 0}, - {"-", false, 0}, - {"123@@@", false, 123}, - {absl::StrCat(uint64_max, uint64_max), false, uint64_max}, - }; - - for (const Uint64TestLine& test_line : uint64_test_line) { - uint64_t value = 2; - bool status = safe_strtou64_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = 2; - status = safe_strtou64_base(test_line.input, &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - value = 2; - status = safe_strtou64_base(absl::string_view(test_line.input), &value, 10); - EXPECT_EQ(test_line.status, status) << test_line.input; - EXPECT_EQ(test_line.value, value) << test_line.input; - } -} - -TEST(StrToInt32Base, PrefixOnly) { - struct Int32TestLine { - std::string input; - bool status; - int32_t value; - }; - Int32TestLine int32_test_line[] = { - { "", false, 0 }, - { "-", false, 0 }, - { "-0", true, 0 }, - { "0", true, 0 }, - { "0x", false, 0 }, - { "-0x", false, 0 }, - }; - const int base_array[] = { 0, 2, 8, 10, 16 }; - - for (const Int32TestLine& line : int32_test_line) { - for (const int base : base_array) { - int32_t value = 2; - bool status = safe_strto32_base(line.input.c_str(), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strto32_base(line.input, &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strto32_base(absl::string_view(line.input), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - } - } -} - -TEST(StrToUint32Base, PrefixOnly) { - struct Uint32TestLine { - std::string input; - bool status; - uint32_t value; - }; - Uint32TestLine uint32_test_line[] = { - { "", false, 0 }, - { "0", true, 0 }, - { "0x", false, 0 }, - }; - const int base_array[] = { 0, 2, 8, 10, 16 }; - - for (const Uint32TestLine& line : uint32_test_line) { - for (const int base : base_array) { - uint32_t value = 2; - bool status = safe_strtou32_base(line.input.c_str(), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strtou32_base(line.input, &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strtou32_base(absl::string_view(line.input), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - } - } -} - -TEST(StrToInt64Base, PrefixOnly) { - struct Int64TestLine { - std::string input; - bool status; - int64_t value; - }; - Int64TestLine int64_test_line[] = { - { "", false, 0 }, - { "-", false, 0 }, - { "-0", true, 0 }, - { "0", true, 0 }, - { "0x", false, 0 }, - { "-0x", false, 0 }, - }; - const int base_array[] = { 0, 2, 8, 10, 16 }; - - for (const Int64TestLine& line : int64_test_line) { - for (const int base : base_array) { - int64_t value = 2; - bool status = safe_strto64_base(line.input.c_str(), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strto64_base(line.input, &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strto64_base(absl::string_view(line.input), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - } - } -} - -TEST(StrToUint64Base, PrefixOnly) { - struct Uint64TestLine { - std::string input; - bool status; - uint64_t value; - }; - Uint64TestLine uint64_test_line[] = { - { "", false, 0 }, - { "0", true, 0 }, - { "0x", false, 0 }, - }; - const int base_array[] = { 0, 2, 8, 10, 16 }; - - for (const Uint64TestLine& line : uint64_test_line) { - for (const int base : base_array) { - uint64_t value = 2; - bool status = safe_strtou64_base(line.input.c_str(), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strtou64_base(line.input, &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - value = 2; - status = safe_strtou64_base(absl::string_view(line.input), &value, base); - EXPECT_EQ(line.status, status) << line.input << " " << base; - EXPECT_EQ(line.value, value) << line.input << " " << base; - } - } -} - -void TestFastHexToBufferZeroPad16(uint64_t v) { - char buf[16]; - auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(v, buf); - absl::string_view res(buf, 16); - char buf2[17]; - snprintf(buf2, sizeof(buf2), "%016" PRIx64, v); - EXPECT_EQ(res, buf2) << v; - size_t expected_digits = snprintf(buf2, sizeof(buf2), "%" PRIx64, v); - EXPECT_EQ(digits, expected_digits) << v; -} - -TEST(FastHexToBufferZeroPad16, Smoke) { - TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::min()); - TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::max()); - TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::min()); - TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::max()); - absl::BitGen rng; - for (int i = 0; i < 100000; ++i) { - TestFastHexToBufferZeroPad16( - absl::LogUniform(rng, std::numeric_limits<uint64_t>::min(), - std::numeric_limits<uint64_t>::max())); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_cat.cc b/third_party/abseil_cpp/absl/strings/str_cat.cc deleted file mode 100644 index dd5d25b0d6df..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_cat.cc +++ /dev/null @@ -1,246 +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/strings/str_cat.h" - -#include <assert.h> - -#include <algorithm> -#include <cstdint> -#include <cstring> - -#include "absl/strings/ascii.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/numbers.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -AlphaNum::AlphaNum(Hex hex) { - static_assert(numbers_internal::kFastToBufferSize >= 32, - "This function only works when output buffer >= 32 bytes long"); - char* const end = &digits_[numbers_internal::kFastToBufferSize]; - auto real_width = - absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16); - if (real_width >= hex.width) { - piece_ = absl::string_view(end - real_width, real_width); - } else { - // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and - // max pad width can be up to 20. - std::memset(end - 32, hex.fill, 16); - // Patch up everything else up to the real_width. - std::memset(end - real_width - 16, hex.fill, 16); - piece_ = absl::string_view(end - hex.width, hex.width); - } -} - -AlphaNum::AlphaNum(Dec dec) { - assert(dec.width <= numbers_internal::kFastToBufferSize); - char* const end = &digits_[numbers_internal::kFastToBufferSize]; - char* const minfill = end - dec.width; - char* writer = end; - uint64_t value = dec.value; - bool neg = dec.neg; - while (value > 9) { - *--writer = '0' + (value % 10); - value /= 10; - } - *--writer = '0' + value; - if (neg) *--writer = '-'; - - ptrdiff_t fillers = writer - minfill; - if (fillers > 0) { - // Tricky: if the fill character is ' ', then it's <fill><+/-><digits> - // But...: if the fill character is '0', then it's <+/-><fill><digits> - bool add_sign_again = false; - if (neg && dec.fill == '0') { // If filling with '0', - ++writer; // ignore the sign we just added - add_sign_again = true; // and re-add the sign later. - } - writer -= fillers; - std::fill_n(writer, fillers, dec.fill); - if (add_sign_again) *--writer = '-'; - } - - piece_ = absl::string_view(writer, end - writer); -} - -// ---------------------------------------------------------------------- -// StrCat() -// This merges the given strings or integers, with no delimiter. This -// is designed to be the fastest possible way to construct a string out -// of a mix of raw C strings, string_views, strings, and integer values. -// ---------------------------------------------------------------------- - -// Append is merely a version of memcpy that returns the address of the byte -// after the area just overwritten. -static char* Append(char* out, const AlphaNum& x) { - // memcpy is allowed to overwrite arbitrary memory, so doing this after the - // call would force an extra fetch of x.size(). - char* after = out + x.size(); - if (x.size() != 0) { - memcpy(out, x.data(), x.size()); - } - return after; -} - -std::string StrCat(const AlphaNum& a, const AlphaNum& b) { - std::string result; - absl::strings_internal::STLStringResizeUninitialized(&result, - a.size() + b.size()); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - assert(out == begin + result.size()); - return result; -} - -std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) { - std::string result; - strings_internal::STLStringResizeUninitialized( - &result, a.size() + b.size() + c.size()); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - assert(out == begin + result.size()); - return result; -} - -std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, - const AlphaNum& d) { - std::string result; - strings_internal::STLStringResizeUninitialized( - &result, a.size() + b.size() + c.size() + d.size()); - char* const begin = &result[0]; - char* out = begin; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - out = Append(out, d); - assert(out == begin + result.size()); - return result; -} - -namespace strings_internal { - -// Do not call directly - these are not part of the public API. -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(); - strings_internal::STLStringResizeUninitialized(&result, total_size); - - char* const begin = &result[0]; - char* out = begin; - for (const absl::string_view& piece : pieces) { - const size_t this_size = piece.size(); - if (this_size != 0) { - memcpy(out, piece.data(), this_size); - out += this_size; - } - } - assert(out == begin + result.size()); - return result; -} - -// It's possible to call StrAppend with an absl::string_view that is itself a -// fragment of the string we're appending to. However the results of this are -// random. Therefore, check for this in debug mode. Use unsigned math so we -// only have to do one comparison. Note, there's an exception case: appending an -// empty string is always allowed. -#define ASSERT_NO_OVERLAP(dest, src) \ - assert(((src).size() == 0) || \ - (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size()))) - -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) { - ASSERT_NO_OVERLAP(*dest, piece); - total_size += piece.size(); - } - strings_internal::STLStringResizeUninitialized(dest, total_size); - - char* const begin = &(*dest)[0]; - char* out = begin + old_size; - for (const absl::string_view& piece : pieces) { - const size_t this_size = piece.size(); - if (this_size != 0) { - memcpy(out, piece.data(), this_size); - out += this_size; - } - } - assert(out == begin + dest->size()); -} - -} // namespace strings_internal - -void StrAppend(std::string* dest, const AlphaNum& a) { - ASSERT_NO_OVERLAP(*dest, a); - dest->append(a.data(), a.size()); -} - -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::STLStringResizeUninitialized( - dest, old_size + a.size() + b.size()); - char* const begin = &(*dest)[0]; - char* out = begin + old_size; - out = Append(out, a); - out = Append(out, b); - assert(out == begin + dest->size()); -} - -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c) { - ASSERT_NO_OVERLAP(*dest, a); - ASSERT_NO_OVERLAP(*dest, b); - ASSERT_NO_OVERLAP(*dest, c); - std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitialized( - dest, old_size + a.size() + b.size() + c.size()); - char* const begin = &(*dest)[0]; - char* out = begin + old_size; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - assert(out == begin + dest->size()); -} - -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d) { - ASSERT_NO_OVERLAP(*dest, a); - ASSERT_NO_OVERLAP(*dest, b); - ASSERT_NO_OVERLAP(*dest, c); - ASSERT_NO_OVERLAP(*dest, d); - std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitialized( - dest, old_size + a.size() + b.size() + c.size() + d.size()); - char* const begin = &(*dest)[0]; - char* out = begin + old_size; - out = Append(out, a); - out = Append(out, b); - out = Append(out, c); - out = Append(out, d); - assert(out == begin + dest->size()); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/str_cat.h b/third_party/abseil_cpp/absl/strings/str_cat.h deleted file mode 100644 index a8a85c7322b2..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_cat.h +++ /dev/null @@ -1,408 +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. -// -// ----------------------------------------------------------------------------- -// File: str_cat.h -// ----------------------------------------------------------------------------- -// -// This package contains functions for efficiently concatenating and appending -// strings: `StrCat()` and `StrAppend()`. Most of the work within these routines -// is actually handled through use of a special AlphaNum type, which was -// designed to be used as a parameter type that efficiently manages conversion -// to strings and avoids copies in the above operations. -// -// Any routine accepting either a string or a number may accept `AlphaNum`. -// The basic idea is that by accepting a `const AlphaNum &` as an argument -// to your function, your callers will automagically convert bools, integers, -// and floating point values to strings for you. -// -// NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported -// except for the specific case of function parameters of type `AlphaNum` or -// `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a -// stack variable is not supported. -// -// Conversion from 8-bit values is not accepted because, if it were, then an -// attempt to pass ':' instead of ":" might result in a 58 ending up in your -// result. -// -// Bools convert to "0" or "1". Pointers to types other than `char *` are not -// valid inputs. No output is generated for null `char *` pointers. -// -// Floating point numbers are formatted with six-digit precision, which is -// the default for "std::cout <<" or printf "%g" (the same as "%.6g"). -// -// You can convert to hexadecimal output rather than decimal output using the -// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to -// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using -// a `PadSpec` enum. -// -// ----------------------------------------------------------------------------- - -#ifndef ABSL_STRINGS_STR_CAT_H_ -#define ABSL_STRINGS_STR_CAT_H_ - -#include <array> -#include <cstdint> -#include <string> -#include <type_traits> -#include <vector> - -#include "absl/base/port.h" -#include "absl/strings/numbers.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace strings_internal { -// AlphaNumBuffer allows a way to pass a string to StrCat without having to do -// memory allocation. It is simply a pair of a fixed-size character array, and -// a size. Please don't use outside of absl, yet. -template <size_t max_size> -struct AlphaNumBuffer { - std::array<char, max_size> data; - size_t size; -}; - -} // namespace strings_internal - -// Enum that specifies the number of significant digits to return in a `Hex` or -// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example, -// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value -// would produce hexadecimal strings such as " a"," f". -enum PadSpec : uint8_t { - kNoPad = 1, - kZeroPad2, - kZeroPad3, - kZeroPad4, - kZeroPad5, - kZeroPad6, - kZeroPad7, - kZeroPad8, - kZeroPad9, - kZeroPad10, - kZeroPad11, - kZeroPad12, - kZeroPad13, - kZeroPad14, - kZeroPad15, - kZeroPad16, - kZeroPad17, - kZeroPad18, - kZeroPad19, - kZeroPad20, - - kSpacePad2 = kZeroPad2 + 64, - kSpacePad3, - kSpacePad4, - kSpacePad5, - kSpacePad6, - kSpacePad7, - kSpacePad8, - kSpacePad9, - kSpacePad10, - kSpacePad11, - kSpacePad12, - kSpacePad13, - kSpacePad14, - kSpacePad15, - kSpacePad16, - kSpacePad17, - kSpacePad18, - kSpacePad19, - kSpacePad20, -}; - -// ----------------------------------------------------------------------------- -// Hex -// ----------------------------------------------------------------------------- -// -// `Hex` stores a set of hexadecimal string conversion parameters for use -// within `AlphaNum` string conversions. -struct Hex { - uint64_t value; - uint8_t width; - char fill; - - template <typename Int> - explicit Hex( - Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 1 && - !std::is_pointer<Int>::value>::type* = nullptr) - : Hex(spec, static_cast<uint8_t>(v)) {} - template <typename Int> - explicit Hex( - Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 2 && - !std::is_pointer<Int>::value>::type* = nullptr) - : Hex(spec, static_cast<uint16_t>(v)) {} - template <typename Int> - explicit Hex( - Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 4 && - !std::is_pointer<Int>::value>::type* = nullptr) - : Hex(spec, static_cast<uint32_t>(v)) {} - template <typename Int> - explicit Hex( - Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<sizeof(Int) == 8 && - !std::is_pointer<Int>::value>::type* = nullptr) - : Hex(spec, static_cast<uint64_t>(v)) {} - template <typename Pointee> - explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad) - : Hex(spec, reinterpret_cast<uintptr_t>(v)) {} - - private: - Hex(PadSpec spec, uint64_t v) - : value(v), - width(spec == absl::kNoPad - ? 1 - : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2 - : spec - absl::kZeroPad2 + 2), - fill(spec >= absl::kSpacePad2 ? ' ' : '0') {} -}; - -// ----------------------------------------------------------------------------- -// Dec -// ----------------------------------------------------------------------------- -// -// `Dec` stores a set of decimal string conversion parameters for use -// within `AlphaNum` string conversions. Dec is slower than the default -// integer conversion, so use it only if you need padding. -struct Dec { - uint64_t value; - uint8_t width; - char fill; - bool neg; - - template <typename Int> - explicit Dec(Int v, PadSpec spec = absl::kNoPad, - typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr) - : value(v >= 0 ? static_cast<uint64_t>(v) - : uint64_t{0} - static_cast<uint64_t>(v)), - width(spec == absl::kNoPad - ? 1 - : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2 - : spec - absl::kZeroPad2 + 2), - fill(spec >= absl::kSpacePad2 ? ' ' : '0'), - neg(v < 0) {} -}; - -// ----------------------------------------------------------------------------- -// AlphaNum -// ----------------------------------------------------------------------------- -// -// The `AlphaNum` class acts as the main parameter type for `StrCat()` and -// `StrAppend()`, providing efficient conversion of numeric, boolean, and -// hexadecimal values (through the `Hex` type) into strings. - -class AlphaNum { - public: - // No bool ctor -- bools convert to an integral type. - // A bool ctor would also convert incoming pointers (bletch). - - AlphaNum(int x) // NOLINT(runtime/explicit) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - AlphaNum(unsigned int x) // NOLINT(runtime/explicit) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - AlphaNum(long x) // NOLINT(*) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - AlphaNum(unsigned long x) // NOLINT(*) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - AlphaNum(long long x) // NOLINT(*) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - AlphaNum(unsigned long long x) // NOLINT(*) - : piece_(digits_, - numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {} - - AlphaNum(float f) // NOLINT(runtime/explicit) - : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {} - AlphaNum(double f) // NOLINT(runtime/explicit) - : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {} - - AlphaNum(Hex hex); // NOLINT(runtime/explicit) - AlphaNum(Dec dec); // NOLINT(runtime/explicit) - - template <size_t size> - AlphaNum( // NOLINT(runtime/explicit) - const strings_internal::AlphaNumBuffer<size>& buf) - : piece_(&buf.data[0], buf.size) {} - - AlphaNum(const char* c_str) : piece_(c_str) {} // NOLINT(runtime/explicit) - AlphaNum(absl::string_view pc) : piece_(pc) {} // NOLINT(runtime/explicit) - - template <typename Allocator> - AlphaNum( // NOLINT(runtime/explicit) - const std::basic_string<char, std::char_traits<char>, Allocator>& str) - : piece_(str) {} - - // Use string literals ":" instead of character literals ':'. - AlphaNum(char c) = delete; // NOLINT(runtime/explicit) - - AlphaNum(const AlphaNum&) = delete; - AlphaNum& operator=(const AlphaNum&) = delete; - - absl::string_view::size_type size() const { return piece_.size(); } - const char* data() const { return piece_.data(); } - absl::string_view Piece() const { return piece_; } - - // Normal enums are already handled by the integer formatters. - // This overload matches only scoped enums. - template <typename T, - typename = typename std::enable_if< - std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type> - AlphaNum(T e) // NOLINT(runtime/explicit) - : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {} - - // vector<bool>::reference and const_reference require special help to - // convert to `AlphaNum` because it requires two user defined conversions. - template < - typename T, - typename std::enable_if< - std::is_class<T>::value && - (std::is_same<T, std::vector<bool>::reference>::value || - std::is_same<T, std::vector<bool>::const_reference>::value)>::type* = - nullptr> - AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit) - - private: - absl::string_view piece_; - char digits_[numbers_internal::kFastToBufferSize]; -}; - -// ----------------------------------------------------------------------------- -// StrCat() -// ----------------------------------------------------------------------------- -// -// Merges given strings or numbers, using no delimiter(s), returning the merged -// result as a string. -// -// `StrCat()` is designed to be the fastest possible way to construct a string -// out of a mix of raw C strings, string_views, strings, bool values, -// and numeric values. -// -// Don't use `StrCat()` for user-visible strings. The localization process -// works poorly on strings built up out of fragments. -// -// For clarity and performance, don't use `StrCat()` when appending to a -// string. Use `StrAppend()` instead. In particular, avoid using any of these -// (anti-)patterns: -// -// str.append(StrCat(...)) -// str += StrCat(...) -// str = StrCat(str, ...) -// -// The last case is the worst, with a potential to change a loop -// from a linear time operation with O(1) dynamic allocations into a -// quadratic time operation with O(n) dynamic allocations. -// -// See `StrAppend()` below for more information. - -namespace strings_internal { - -// Do not call directly - this is not part of the public API. -std::string CatPieces(std::initializer_list<absl::string_view> pieces); -void AppendPieces(std::string* dest, - std::initializer_list<absl::string_view> pieces); - -} // namespace strings_internal - -ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); } - -ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) { - return std::string(a.data(), a.size()); -} - -ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b); -ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); - -// Support 5 or more arguments -template <typename... AV> -ABSL_MUST_USE_RESULT inline std::string StrCat( - const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AV&... args) { - return strings_internal::CatPieces( - {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(), - static_cast<const AlphaNum&>(args).Piece()...}); -} - -// ----------------------------------------------------------------------------- -// StrAppend() -// ----------------------------------------------------------------------------- -// -// Appends a string or set of strings to an existing string, in a similar -// fashion to `StrCat()`. -// -// WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the -// a, b, c, parameters be a reference into str. For speed, `StrAppend()` does -// not try to check each of its input arguments to be sure that they are not -// a subset of the string being appended to. That is, while this will work: -// -// std::string s = "foo"; -// s += s; -// -// This output is undefined: -// -// std::string s = "foo"; -// StrAppend(&s, s); -// -// This output is undefined as well, since `absl::string_view` does not own its -// data: -// -// std::string s = "foobar"; -// absl::string_view p = s; -// StrAppend(&s, p); - -inline void StrAppend(std::string*) {} -void StrAppend(std::string* dest, const AlphaNum& a); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); - -// Support 5 or more arguments -template <typename... AV> -inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, const AlphaNum& e, - const AV&... args) { - strings_internal::AppendPieces( - dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(), - static_cast<const AlphaNum&>(args).Piece()...}); -} - -// Helper function for the future StrCat default floating-point format, %.6g -// This is fast. -inline strings_internal::AlphaNumBuffer< - numbers_internal::kSixDigitsToBufferSize> -SixDigits(double d) { - strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize> - result; - result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]); - return result; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STR_CAT_H_ diff --git a/third_party/abseil_cpp/absl/strings/str_cat_benchmark.cc b/third_party/abseil_cpp/absl/strings/str_cat_benchmark.cc deleted file mode 100644 index 02c4dbe6d8f1..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_cat_benchmark.cc +++ /dev/null @@ -1,187 +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/strings/str_cat.h" - -#include <cstdint> -#include <string> - -#include "benchmark/benchmark.h" -#include "absl/strings/substitute.h" - -namespace { - -const char kStringOne[] = "Once Upon A Time, "; -const char kStringTwo[] = "There was a string benchmark"; - -// We want to include negative numbers in the benchmark, so this function -// is used to count 0, 1, -1, 2, -2, 3, -3, ... -inline int IncrementAlternatingSign(int i) { - return i > 0 ? -i : 1 - i; -} - -void BM_Sum_By_StrCat(benchmark::State& state) { - int i = 0; - char foo[100]; - for (auto _ : state) { - // NOLINTNEXTLINE(runtime/printf) - strcpy(foo, absl::StrCat(kStringOne, i, kStringTwo, i * 65536ULL).c_str()); - int sum = 0; - for (char* f = &foo[0]; *f != 0; ++f) { - sum += *f; - } - benchmark::DoNotOptimize(sum); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_Sum_By_StrCat); - -void BM_StrCat_By_snprintf(benchmark::State& state) { - int i = 0; - char on_stack[1000]; - for (auto _ : state) { - snprintf(on_stack, sizeof(on_stack), "%s %s:%d", kStringOne, kStringTwo, i); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_StrCat_By_snprintf); - -void BM_StrCat_By_Strings(benchmark::State& state) { - int i = 0; - for (auto _ : state) { - std::string result = - std::string(kStringOne) + " " + kStringTwo + ":" + absl::StrCat(i); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_StrCat_By_Strings); - -void BM_StrCat_By_StringOpPlus(benchmark::State& state) { - int i = 0; - for (auto _ : state) { - std::string result = kStringOne; - result += " "; - result += kStringTwo; - result += ":"; - result += absl::StrCat(i); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_StrCat_By_StringOpPlus); - -void BM_StrCat_By_StrCat(benchmark::State& state) { - int i = 0; - for (auto _ : state) { - std::string result = absl::StrCat(kStringOne, " ", kStringTwo, ":", i); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_StrCat_By_StrCat); - -void BM_HexCat_By_StrCat(benchmark::State& state) { - int i = 0; - for (auto _ : state) { - std::string result = - absl::StrCat(kStringOne, " ", absl::Hex(int64_t{i} + 0x10000000)); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_HexCat_By_StrCat); - -void BM_HexCat_By_Substitute(benchmark::State& state) { - int i = 0; - for (auto _ : state) { - std::string result = absl::Substitute( - "$0 $1", kStringOne, reinterpret_cast<void*>(int64_t{i} + 0x10000000)); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_HexCat_By_Substitute); - -void BM_FloatToString_By_StrCat(benchmark::State& state) { - int i = 0; - float foo = 0.0f; - for (auto _ : state) { - std::string result = absl::StrCat(foo += 1.001f, " != ", int64_t{i}); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -BENCHMARK(BM_FloatToString_By_StrCat); - -void BM_DoubleToString_By_SixDigits(benchmark::State& state) { - int i = 0; - double foo = 0.0; - for (auto _ : state) { - std::string result = - absl::StrCat(absl::SixDigits(foo += 1.001), " != ", int64_t{i}); - benchmark::DoNotOptimize(result); - i = IncrementAlternatingSign(i); - } -} -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 deleted file mode 100644 index f3770dc076f0..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_cat_test.cc +++ /dev/null @@ -1,610 +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. - -// Unit tests for all str_cat.h functions - -#include "absl/strings/str_cat.h" - -#include <cstdint> -#include <string> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/strings/substitute.h" - -#ifdef __ANDROID__ -// Android assert messages only go to system log, so death tests cannot inspect -// the message for matching. -#define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \ - EXPECT_DEBUG_DEATH(statement, ".*") -#else -#define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \ - EXPECT_DEBUG_DEATH(statement, regex) -#endif - -namespace { - -// Test absl::StrCat of ints and longs of various sizes and signdedness. -TEST(StrCat, Ints) { - const short s = -1; // NOLINT(runtime/int) - const uint16_t us = 2; - const int i = -3; - const unsigned int ui = 4; - const long l = -5; // NOLINT(runtime/int) - const unsigned long ul = 6; // NOLINT(runtime/int) - const long long ll = -7; // NOLINT(runtime/int) - const unsigned long long ull = 8; // NOLINT(runtime/int) - const ptrdiff_t ptrdiff = -9; - const size_t size = 10; - const intptr_t intptr = -12; - const uintptr_t uintptr = 13; - std::string answer; - answer = absl::StrCat(s, us); - EXPECT_EQ(answer, "-12"); - answer = absl::StrCat(i, ui); - EXPECT_EQ(answer, "-34"); - answer = absl::StrCat(l, ul); - EXPECT_EQ(answer, "-56"); - answer = absl::StrCat(ll, ull); - EXPECT_EQ(answer, "-78"); - answer = absl::StrCat(ptrdiff, size); - EXPECT_EQ(answer, "-910"); - answer = absl::StrCat(ptrdiff, intptr); - EXPECT_EQ(answer, "-9-12"); - answer = absl::StrCat(uintptr, 0); - EXPECT_EQ(answer, "130"); -} - -TEST(StrCat, Enums) { - enum SmallNumbers { One = 1, Ten = 10 } e = Ten; - EXPECT_EQ("10", absl::StrCat(e)); - EXPECT_EQ("-5", absl::StrCat(SmallNumbers(-5))); - - enum class Option { Boxers = 1, Briefs = -1 }; - - EXPECT_EQ("-1", absl::StrCat(Option::Briefs)); - - enum class Airplane : uint64_t { - Airbus = 1, - Boeing = 1000, - Canary = 10000000000 // too big for "int" - }; - - EXPECT_EQ("10000000000", absl::StrCat(Airplane::Canary)); - - enum class TwoGig : int32_t { - TwoToTheZero = 1, - TwoToTheSixteenth = 1 << 16, - TwoToTheThirtyFirst = INT32_MIN - }; - EXPECT_EQ("65536", absl::StrCat(TwoGig::TwoToTheSixteenth)); - EXPECT_EQ("-2147483648", absl::StrCat(TwoGig::TwoToTheThirtyFirst)); - EXPECT_EQ("-1", absl::StrCat(static_cast<TwoGig>(-1))); - - enum class FourGig : uint32_t { - TwoToTheZero = 1, - TwoToTheSixteenth = 1 << 16, - TwoToTheThirtyFirst = 1U << 31 // too big for "int" - }; - EXPECT_EQ("65536", absl::StrCat(FourGig::TwoToTheSixteenth)); - EXPECT_EQ("2147483648", absl::StrCat(FourGig::TwoToTheThirtyFirst)); - EXPECT_EQ("4294967295", absl::StrCat(static_cast<FourGig>(-1))); - - EXPECT_EQ("10000000000", absl::StrCat(Airplane::Canary)); -} - -TEST(StrCat, Basics) { - std::string result; - - std::string strs[] = {"Hello", "Cruel", "World"}; - - std::string stdstrs[] = { - "std::Hello", - "std::Cruel", - "std::World" - }; - - absl::string_view pieces[] = {"Hello", "Cruel", "World"}; - - const char* c_strs[] = { - "Hello", - "Cruel", - "World" - }; - - int32_t i32s[] = {'H', 'C', 'W'}; - uint64_t ui64s[] = {12345678910LL, 10987654321LL}; - - EXPECT_EQ(absl::StrCat(), ""); - - result = absl::StrCat(false, true, 2, 3); - EXPECT_EQ(result, "0123"); - - result = absl::StrCat(-1); - EXPECT_EQ(result, "-1"); - - result = absl::StrCat(absl::SixDigits(0.5)); - EXPECT_EQ(result, "0.5"); - - result = absl::StrCat(strs[1], pieces[2]); - EXPECT_EQ(result, "CruelWorld"); - - result = absl::StrCat(stdstrs[1], " ", stdstrs[2]); - EXPECT_EQ(result, "std::Cruel std::World"); - - result = absl::StrCat(strs[0], ", ", pieces[2]); - EXPECT_EQ(result, "Hello, World"); - - result = absl::StrCat(strs[0], ", ", strs[1], " ", strs[2], "!"); - EXPECT_EQ(result, "Hello, Cruel World!"); - - result = absl::StrCat(pieces[0], ", ", pieces[1], " ", pieces[2]); - EXPECT_EQ(result, "Hello, Cruel World"); - - result = absl::StrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]); - EXPECT_EQ(result, "Hello, Cruel World"); - - result = absl::StrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!"); - EXPECT_EQ(result, "ASCII 72, 67 87!"); - - result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!"); - EXPECT_EQ(result, "12345678910, 10987654321!"); - - std::string one = - "1"; // Actually, it's the size of this string that we want; a - // 64-bit build distinguishes between size_t and uint64_t, - // even though they're both unsigned 64-bit values. - result = absl::StrCat("And a ", one.size(), " and a ", - &result[2] - &result[0], " and a ", one, " 2 3 4", "!"); - EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!"); - - // result = absl::StrCat("Single chars won't compile", '!'); - // result = absl::StrCat("Neither will nullptrs", nullptr); - result = - absl::StrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0); - EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33"); - - float f = 100000.5; - result = absl::StrCat("A hundred K and a half is ", absl::SixDigits(f)); - EXPECT_EQ(result, "A hundred K and a half is 100000"); - - f = 100001.5; - result = - absl::StrCat("A hundred K and one and a half is ", absl::SixDigits(f)); - EXPECT_EQ(result, "A hundred K and one and a half is 100002"); - - double d = 100000.5; - d *= d; - result = - absl::StrCat("A hundred K and a half squared is ", absl::SixDigits(d)); - EXPECT_EQ(result, "A hundred K and a half squared is 1.00001e+10"); - - result = absl::StrCat(1, 2, 333, 4444, 55555, 666666, 7777777, 88888888, - 999999999); - EXPECT_EQ(result, "12333444455555666666777777788888888999999999"); -} - -TEST(StrCat, CornerCases) { - std::string result; - - result = absl::StrCat(""); // NOLINT - EXPECT_EQ(result, ""); - result = absl::StrCat("", ""); - EXPECT_EQ(result, ""); - result = absl::StrCat("", "", ""); - EXPECT_EQ(result, ""); - result = absl::StrCat("", "", "", ""); - EXPECT_EQ(result, ""); - result = absl::StrCat("", "", "", "", ""); - EXPECT_EQ(result, ""); -} - -// A minimal allocator that uses malloc(). -template <typename T> -struct Mallocator { - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - size_type max_size() const { - return size_t(std::numeric_limits<size_type>::max()) / sizeof(value_type); - } - template <typename U> - struct rebind { - typedef Mallocator<U> other; - }; - Mallocator() = default; - template <class U> - Mallocator(const Mallocator<U>&) {} // NOLINT(runtime/explicit) - - T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); } - void deallocate(T* p, size_t) { std::free(p); } -}; -template <typename T, typename U> -bool operator==(const Mallocator<T>&, const Mallocator<U>&) { - return true; -} -template <typename T, typename U> -bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { - return false; -} - -TEST(StrCat, CustomAllocator) { - using mstring = - std::basic_string<char, std::char_traits<char>, Mallocator<char>>; - const mstring str1("PARACHUTE OFF A BLIMP INTO MOSCONE!!"); - - const mstring str2("Read this book about coffee tables"); - - std::string result = absl::StrCat(str1, str2); - EXPECT_EQ(result, - "PARACHUTE OFF A BLIMP INTO MOSCONE!!" - "Read this book about coffee tables"); -} - -TEST(StrCat, MaxArgs) { - std::string result; - // Test 10 up to 26 arguments, the old maximum - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a"); - EXPECT_EQ(result, "123456789a"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b"); - EXPECT_EQ(result, "123456789ab"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c"); - EXPECT_EQ(result, "123456789abc"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d"); - EXPECT_EQ(result, "123456789abcd"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e"); - EXPECT_EQ(result, "123456789abcde"); - result = - absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"); - EXPECT_EQ(result, "123456789abcdef"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g"); - EXPECT_EQ(result, "123456789abcdefg"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h"); - EXPECT_EQ(result, "123456789abcdefgh"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i"); - EXPECT_EQ(result, "123456789abcdefghi"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j"); - EXPECT_EQ(result, "123456789abcdefghij"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k"); - EXPECT_EQ(result, "123456789abcdefghijk"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l"); - EXPECT_EQ(result, "123456789abcdefghijkl"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m"); - EXPECT_EQ(result, "123456789abcdefghijklm"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m", "n"); - EXPECT_EQ(result, "123456789abcdefghijklmn"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m", "n", "o"); - EXPECT_EQ(result, "123456789abcdefghijklmno"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"); - EXPECT_EQ(result, "123456789abcdefghijklmnop"); - result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q"); - EXPECT_EQ(result, "123456789abcdefghijklmnopq"); - // No limit thanks to C++11's variadic templates - result = absl::StrCat( - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h", - "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", - "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", - "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"); - EXPECT_EQ(result, - "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); -} - -TEST(StrAppend, Basics) { - std::string result = "existing text"; - - std::string strs[] = {"Hello", "Cruel", "World"}; - - std::string stdstrs[] = { - "std::Hello", - "std::Cruel", - "std::World" - }; - - absl::string_view pieces[] = {"Hello", "Cruel", "World"}; - - const char* c_strs[] = { - "Hello", - "Cruel", - "World" - }; - - int32_t i32s[] = {'H', 'C', 'W'}; - uint64_t ui64s[] = {12345678910LL, 10987654321LL}; - - std::string::size_type old_size = result.size(); - absl::StrAppend(&result); - EXPECT_EQ(result.size(), old_size); - - old_size = result.size(); - absl::StrAppend(&result, strs[0]); - EXPECT_EQ(result.substr(old_size), "Hello"); - - old_size = result.size(); - absl::StrAppend(&result, strs[1], pieces[2]); - EXPECT_EQ(result.substr(old_size), "CruelWorld"); - - old_size = result.size(); - absl::StrAppend(&result, stdstrs[0], ", ", pieces[2]); - EXPECT_EQ(result.substr(old_size), "std::Hello, World"); - - old_size = result.size(); - absl::StrAppend(&result, strs[0], ", ", stdstrs[1], " ", strs[2], "!"); - EXPECT_EQ(result.substr(old_size), "Hello, std::Cruel World!"); - - old_size = result.size(); - absl::StrAppend(&result, pieces[0], ", ", pieces[1], " ", pieces[2]); - EXPECT_EQ(result.substr(old_size), "Hello, Cruel World"); - - old_size = result.size(); - absl::StrAppend(&result, c_strs[0], ", ", c_strs[1], " ", c_strs[2]); - EXPECT_EQ(result.substr(old_size), "Hello, Cruel World"); - - old_size = result.size(); - absl::StrAppend(&result, "ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!"); - EXPECT_EQ(result.substr(old_size), "ASCII 72, 67 87!"); - - old_size = result.size(); - absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!"); - EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!"); - - std::string one = - "1"; // Actually, it's the size of this string that we want; a - // 64-bit build distinguishes between size_t and uint64_t, - // even though they're both unsigned 64-bit values. - old_size = result.size(); - absl::StrAppend(&result, "And a ", one.size(), " and a ", - &result[2] - &result[0], " and a ", one, " 2 3 4", "!"); - EXPECT_EQ(result.substr(old_size), "And a 1 and a 2 and a 1 2 3 4!"); - - // result = absl::StrCat("Single chars won't compile", '!'); - // result = absl::StrCat("Neither will nullptrs", nullptr); - old_size = result.size(); - absl::StrAppend(&result, - "To output a char by ASCII/numeric value, use +: ", '!' + 0); - EXPECT_EQ(result.substr(old_size), - "To output a char by ASCII/numeric value, use +: 33"); - - // Test 9 arguments, the old maximum - old_size = result.size(); - absl::StrAppend(&result, 1, 22, 333, 4444, 55555, 666666, 7777777, 88888888, - 9); - EXPECT_EQ(result.substr(old_size), "1223334444555556666667777777888888889"); - - // No limit thanks to C++11's variadic templates - old_size = result.size(); - absl::StrAppend( - &result, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", // - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", // - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", // - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", // - "No limit thanks to C++11's variadic templates"); - EXPECT_EQ(result.substr(old_size), - "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - "No limit thanks to C++11's variadic templates"); -} - -TEST(StrCat, VectorBoolReferenceTypes) { - std::vector<bool> v; - v.push_back(true); - v.push_back(false); - std::vector<bool> const& cv = v; - // Test that vector<bool>::reference and vector<bool>::const_reference - // are handled as if the were really bool types and not the proxy types - // they really are. - std::string result = absl::StrCat(v[0], v[1], cv[0], cv[1]); // NOLINT - EXPECT_EQ(result, "1010"); -} - -// Passing nullptr to memcpy is undefined behavior and this test -// provides coverage of codepaths that handle empty strings with nullptrs. -TEST(StrCat, AvoidsMemcpyWithNullptr) { - EXPECT_EQ(absl::StrCat(42, absl::string_view{}), "42"); - - // Cover CatPieces code. - EXPECT_EQ(absl::StrCat(1, 2, 3, 4, 5, absl::string_view{}), "12345"); - - // Cover AppendPieces. - std::string result; - absl::StrAppend(&result, 1, 2, 3, 4, 5, absl::string_view{}); - EXPECT_EQ(result, "12345"); -} - -#ifdef GTEST_HAS_DEATH_TEST -TEST(StrAppend, Death) { - std::string s = "self"; - // on linux it's "assertion", on mac it's "Assertion", - // on chromiumos it's "Assertion ... failed". - ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s.c_str() + 1), - "ssertion.*failed"); - ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s), "ssertion.*failed"); -} -#endif // GTEST_HAS_DEATH_TEST - -TEST(StrAppend, CornerCases) { - std::string result; - absl::StrAppend(&result, ""); - EXPECT_EQ(result, ""); - absl::StrAppend(&result, "", ""); - EXPECT_EQ(result, ""); - absl::StrAppend(&result, "", "", ""); - EXPECT_EQ(result, ""); - absl::StrAppend(&result, "", "", "", ""); - EXPECT_EQ(result, ""); - absl::StrAppend(&result, "", "", "", "", ""); - EXPECT_EQ(result, ""); -} - -TEST(StrAppend, CornerCasesNonEmptyAppend) { - for (std::string result : {"hello", "a string too long to fit in the SSO"}) { - const std::string expected = result; - absl::StrAppend(&result, ""); - EXPECT_EQ(result, expected); - absl::StrAppend(&result, "", ""); - EXPECT_EQ(result, expected); - absl::StrAppend(&result, "", "", ""); - EXPECT_EQ(result, expected); - absl::StrAppend(&result, "", "", "", ""); - EXPECT_EQ(result, expected); - absl::StrAppend(&result, "", "", "", "", ""); - EXPECT_EQ(result, expected); - } -} - -template <typename IntType> -void CheckHex(IntType v, const char* nopad_format, const char* zeropad_format, - const char* spacepad_format) { - char expected[256]; - - std::string actual = absl::StrCat(absl::Hex(v, absl::kNoPad)); - snprintf(expected, sizeof(expected), nopad_format, v); - EXPECT_EQ(expected, actual) << " decimal value " << v; - - for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) { - std::string actual = - absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec))); - snprintf(expected, sizeof(expected), zeropad_format, - spec - absl::kZeroPad2 + 2, v); - EXPECT_EQ(expected, actual) << " decimal value " << v; - } - - for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) { - std::string actual = - absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec))); - snprintf(expected, sizeof(expected), spacepad_format, - spec - absl::kSpacePad2 + 2, v); - EXPECT_EQ(expected, actual) << " decimal value " << v; - } -} - -template <typename IntType> -void CheckDec(IntType v, const char* nopad_format, const char* zeropad_format, - const char* spacepad_format) { - char expected[256]; - - std::string actual = absl::StrCat(absl::Dec(v, absl::kNoPad)); - snprintf(expected, sizeof(expected), nopad_format, v); - EXPECT_EQ(expected, actual) << " decimal value " << v; - - for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) { - std::string actual = - absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec))); - snprintf(expected, sizeof(expected), zeropad_format, - spec - absl::kZeroPad2 + 2, v); - EXPECT_EQ(expected, actual) - << " decimal value " << v << " format '" << zeropad_format - << "' digits " << (spec - absl::kZeroPad2 + 2); - } - - for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) { - std::string actual = - absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec))); - snprintf(expected, sizeof(expected), spacepad_format, - spec - absl::kSpacePad2 + 2, v); - EXPECT_EQ(expected, actual) - << " decimal value " << v << " format '" << spacepad_format - << "' digits " << (spec - absl::kSpacePad2 + 2); - } -} - -void CheckHexDec64(uint64_t v) { - unsigned long long ullv = v; // NOLINT(runtime/int) - - CheckHex(ullv, "%llx", "%0*llx", "%*llx"); - CheckDec(ullv, "%llu", "%0*llu", "%*llu"); - - long long llv = static_cast<long long>(ullv); // NOLINT(runtime/int) - CheckDec(llv, "%lld", "%0*lld", "%*lld"); - - if (sizeof(v) == sizeof(&v)) { - auto uintptr = static_cast<uintptr_t>(v); - void* ptr = reinterpret_cast<void*>(uintptr); - CheckHex(ptr, "%llx", "%0*llx", "%*llx"); - } -} - -void CheckHexDec32(uint32_t uv) { - CheckHex(uv, "%x", "%0*x", "%*x"); - CheckDec(uv, "%u", "%0*u", "%*u"); - int32_t v = static_cast<int32_t>(uv); - CheckDec(v, "%d", "%0*d", "%*d"); - - if (sizeof(v) == sizeof(&v)) { - auto uintptr = static_cast<uintptr_t>(v); - void* ptr = reinterpret_cast<void*>(uintptr); - CheckHex(ptr, "%x", "%0*x", "%*x"); - } -} - -void CheckAll(uint64_t v) { - CheckHexDec64(v); - CheckHexDec32(static_cast<uint32_t>(v)); -} - -void TestFastPrints() { - // Test all small ints; there aren't many and they're common. - for (int i = 0; i < 10000; i++) { - CheckAll(i); - } - - CheckAll(std::numeric_limits<uint64_t>::max()); - CheckAll(std::numeric_limits<uint64_t>::max() - 1); - CheckAll(std::numeric_limits<int64_t>::min()); - CheckAll(std::numeric_limits<int64_t>::min() + 1); - CheckAll(std::numeric_limits<uint32_t>::max()); - CheckAll(std::numeric_limits<uint32_t>::max() - 1); - CheckAll(std::numeric_limits<int32_t>::min()); - CheckAll(std::numeric_limits<int32_t>::min() + 1); - CheckAll(999999999); // fits in 32 bits - CheckAll(1000000000); // fits in 32 bits - CheckAll(9999999999); // doesn't fit in 32 bits - CheckAll(10000000000); // doesn't fit in 32 bits - CheckAll(999999999999999999); // fits in signed 64-bit - CheckAll(9999999999999999999u); // fits in unsigned 64-bit, but not signed. - CheckAll(1000000000000000000); // fits in signed 64-bit - CheckAll(10000000000000000000u); // fits in unsigned 64-bit, but not signed. - - CheckAll(999999999876543210); // check all decimal digits, signed - CheckAll(9999999999876543210u); // check all decimal digits, unsigned. - CheckAll(0x123456789abcdef0); // check all hex digits - CheckAll(0x12345678); - - int8_t minus_one_8bit = -1; - EXPECT_EQ("ff", absl::StrCat(absl::Hex(minus_one_8bit))); - - int16_t minus_one_16bit = -1; - EXPECT_EQ("ffff", absl::StrCat(absl::Hex(minus_one_16bit))); -} - -TEST(Numbers, TestFunctionsMovedOverFromNumbersMain) { - TestFastPrints(); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_format.h b/third_party/abseil_cpp/absl/strings/str_format.h deleted file mode 100644 index 01465107e105..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_format.h +++ /dev/null @@ -1,813 +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: str_format.h -// ----------------------------------------------------------------------------- -// -// 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 -// perform argument substitutions based on types. See the `FormatSpec` section -// below for format string documentation. -// -// Example: -// -// std::string s = absl::StrFormat( -// "%s %s You have $%d!", "Hello", name, dollars); -// -// The library consists of the following basic utilities: -// -// * `absl::StrFormat()`, a type-safe replacement for `std::sprintf()`, to -// write a format string to a `string` value. -// * `absl::StrAppendFormat()` to append a format string to a `string` -// * `absl::StreamFormat()` to more efficiently write a format string to a -// stream, such as`std::cout`. -// * `absl::PrintF()`, `absl::FPrintF()` and `absl::SNPrintF()` as -// replacements for `std::printf()`, `std::fprintf()` and `std::snprintf()`. -// -// Note: a version of `std::sprintf()` is not supported as it is -// generally unsafe due to buffer overflows. -// -// Additionally, you can provide a format string (and its associated arguments) -// using one of the following abstractions: -// -// * A `FormatSpec` class template fully encapsulates a format string and its -// type arguments and is usually provided to `str_format` functions as a -// variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>` -// template is evaluated at compile-time, providing type safety. -// * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled -// format string for a specific set of type(s), and which can be passed -// between API boundaries. (The `FormatSpec` type should not be used -// directly except as an argument type for wrapper functions.) -// -// The `str_format` library provides the ability to output its format strings to -// arbitrary sink types: -// -// * A generic `Format()` function to write outputs to arbitrary sink types, -// which must implement a `FormatRawSink` interface. -// -// * A `FormatUntyped()` function that is similar to `Format()` except it is -// loosely typed. `FormatUntyped()` is not a template and does not perform -// any compile-time checking of the format string; instead, it returns a -// boolean from a runtime check. -// -// In addition, the `str_format` library provides extension points for -// augmenting formatting to new types. See "StrFormat Extensions" below. - -#ifndef ABSL_STRINGS_STR_FORMAT_H_ -#define ABSL_STRINGS_STR_FORMAT_H_ - -#include <cstdio> -#include <string> - -#include "absl/strings/internal/str_format/arg.h" // IWYU pragma: export -#include "absl/strings/internal/str_format/bind.h" // IWYU pragma: export -#include "absl/strings/internal/str_format/checker.h" // IWYU pragma: export -#include "absl/strings/internal/str_format/extension.h" // IWYU pragma: export -#include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// UntypedFormatSpec -// -// A type-erased class that can be used directly within untyped API entry -// points. An `UntypedFormatSpec` is specifically used as an argument to -// `FormatUntyped()`. -// -// Example: -// -// absl::UntypedFormatSpec format("%d"); -// std::string out; -// CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)})); -class UntypedFormatSpec { - public: - UntypedFormatSpec() = delete; - UntypedFormatSpec(const UntypedFormatSpec&) = delete; - UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete; - - explicit UntypedFormatSpec(string_view s) : spec_(s) {} - - protected: - explicit UntypedFormatSpec(const str_format_internal::ParsedFormatBase* pc) - : spec_(pc) {} - - private: - friend str_format_internal::UntypedFormatSpecImpl; - str_format_internal::UntypedFormatSpecImpl spec_; -}; - -// FormatStreamed() -// -// Takes a streamable argument and returns an object that can print it -// with '%s'. Allows printing of types that have an `operator<<` but no -// intrinsic type support within `StrFormat()` itself. -// -// Example: -// -// absl::StrFormat("%s", absl::FormatStreamed(obj)); -template <typename T> -str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) { - return str_format_internal::StreamedWrapper<T>(v); -} - -// FormatCountCapture -// -// This class provides a way to safely wrap `StrFormat()` captures of `%n` -// conversions, which denote the number of characters written by a formatting -// operation to this point, into an integer value. -// -// This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in -// the `printf()` family of functions, `%n` is not safe to use, as the `int *` -// buffer can be used to capture arbitrary data. -// -// Example: -// -// int n = 0; -// std::string s = absl::StrFormat("%s%d%n", "hello", 123, -// absl::FormatCountCapture(&n)); -// EXPECT_EQ(8, n); -class FormatCountCapture { - public: - explicit FormatCountCapture(int* p) : p_(p) {} - - private: - // FormatCountCaptureHelper is used to define FormatConvertImpl() for this - // class. - friend struct str_format_internal::FormatCountCaptureHelper; - // Unused() is here because of the false positive from -Wunused-private-field - // p_ is used in the templated function of the friend FormatCountCaptureHelper - // class. - int* Unused() { return p_; } - int* p_; -}; - -// FormatSpec -// -// The `FormatSpec` type defines the makeup of a format string within the -// `str_format` library. It is a variadic class template that is evaluated at -// compile-time, according to the format string and arguments that are passed to -// it. -// -// You should not need to manipulate this type directly. You should only name it -// if you are writing wrapper functions which accept format arguments that will -// be provided unmodified to functions in this library. Such a wrapper function -// might be a class method that provides format arguments and/or internally uses -// the result of formatting. -// -// For a `FormatSpec` to be valid at compile-time, it must be provided as -// either: -// -// * A `constexpr` literal or `absl::string_view`, which is how it most often -// used. -// * A `ParsedFormat` instantiation, which ensures the format string is -// valid before use. (See below.) -// -// Example: -// -// // Provided as a string literal. -// absl::StrFormat("Welcome to %s, Number %d!", "The Village", 6); -// -// // Provided as a constexpr absl::string_view. -// constexpr absl::string_view formatString = "Welcome to %s, Number %d!"; -// absl::StrFormat(formatString, "The Village", 6); -// -// // Provided as a pre-compiled ParsedFormat object. -// // Note that this example is useful only for illustration purposes. -// absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!"); -// absl::StrFormat(formatString, "TheVillage", 6); -// -// A format string generally follows the POSIX syntax as used within the POSIX -// `printf` specification. -// -// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.) -// -// In specific, the `FormatSpec` supports the following type specifiers: -// * `c` for characters -// * `s` for strings -// * `d` or `i` for integers -// * `o` for unsigned integer conversions into octal -// * `x` or `X` for unsigned integer conversions into hex -// * `u` for unsigned integers -// * `f` or `F` for floating point values into decimal notation -// * `e` or `E` for floating point values into exponential notation -// * `a` or `A` for floating point values into hex exponential notation -// * `g` or `G` for floating point values into decimal or exponential -// notation based on their precision -// * `p` for pointer address values -// * `n` for the special case of writing out the number of characters -// written to this point. The resulting value must be captured within an -// `absl::FormatCountCapture` type. -// -// Implementation-defined behavior: -// * A null pointer provided to "%s" or "%p" is output as "(nil)". -// * A non-null pointer provided to "%p" is output in hex as if by %#x or -// %#lx. -// -// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned -// counterpart before formatting. -// -// Examples: -// "%c", 'a' -> "a" -// "%c", 32 -> " " -// "%s", "C" -> "C" -// "%s", std::string("C++") -> "C++" -// "%d", -10 -> "-10" -// "%o", 10 -> "12" -// "%x", 16 -> "10" -// "%f", 123456789 -> "123456789.000000" -// "%e", .01 -> "1.00000e-2" -// "%a", -3.0 -> "-0x1.8p+1" -// "%g", .01 -> "1e-2" -// "%p", (void*)&value -> "0x7ffdeb6ad2a4" -// -// int n = 0; -// std::string s = absl::StrFormat( -// "%s%d%n", "hello", 123, absl::FormatCountCapture(&n)); -// EXPECT_EQ(8, n); -// -// The `FormatSpec` intrinsically supports all of these fundamental C++ types: -// -// * Characters: `char`, `signed char`, `unsigned char` -// * Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`, -// `unsigned long`, `long long`, `unsigned long long` -// * Floating-point: `float`, `double`, `long double` -// -// However, in the `str_format` library, a format conversion specifies a broader -// C++ conceptual category instead of an exact type. For example, `%s` binds to -// any string-like argument, so `std::string`, `absl::string_view`, and -// `const char*` are all accepted. Likewise, `%d` accepts any integer-like -// argument, etc. - -template <typename... Args> -using FormatSpec = str_format_internal::FormatSpecTemplate< - str_format_internal::ArgumentToConv<Args>()...>; - -// ParsedFormat -// -// A `ParsedFormat` is a class template representing a preparsed `FormatSpec`, -// with template arguments specifying the conversion characters used within the -// format string. Such characters must be valid format type specifiers, and -// these type specifiers are checked at compile-time. -// -// Instances of `ParsedFormat` can be created, copied, and reused to speed up -// formatting loops. A `ParsedFormat` may either be constructed statically, or -// dynamically through its `New()` factory function, which only constructs a -// runtime object if the format is valid at that time. -// -// Example: -// -// // Verified at compile time. -// absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!"); -// absl::StrFormat(formatString, "TheVillage", 6); -// -// // Verified at runtime. -// auto format_runtime = absl::ParsedFormat<'d'>::New(format_string); -// if (format_runtime) { -// value = absl::StrFormat(*format_runtime, i); -// } 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) - -// StrFormat() -// -// Returns a `string` given a `printf()`-style format string and zero or more -// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the -// primary formatting function within the `str_format` library, and should be -// used in most cases where you need type-safe conversion of types into -// formatted strings. -// -// The format string generally consists of ordinary character data along with -// one or more format conversion specifiers (denoted by the `%` character). -// Ordinary character data is returned unchanged into the result string, while -// each conversion specification performs a type substitution from -// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full -// information on the makeup of this format string. -// -// Example: -// -// std::string s = absl::StrFormat( -// "Welcome to %s, Number %d!", "The Village", 6); -// EXPECT_EQ("Welcome to The Village, Number 6!", s); -// -// Returns an empty string in case of error. -template <typename... Args> -ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format, - const Args&... args) { - return str_format_internal::FormatPack( - str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// StrAppendFormat() -// -// Appends to a `dst` string given a format string, and zero or more additional -// arguments, returning `*dst` as a convenience for chaining purposes. Appends -// nothing in case of error (but possibly alters its capacity). -// -// Example: -// -// std::string orig("For example PI is approximately "); -// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14); -template <typename... Args> -std::string& StrAppendFormat(std::string* dst, - const FormatSpec<Args...>& format, - const Args&... args) { - return str_format_internal::AppendPack( - dst, str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// StreamFormat() -// -// Writes to an output stream given a format string and zero or more arguments, -// generally in a manner that is more efficient than streaming the result of -// `absl:: StrFormat()`. The returned object must be streamed before the full -// expression ends. -// -// Example: -// -// std::cout << StreamFormat("%12.6f", 3.14); -template <typename... Args> -ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat( - const FormatSpec<Args...>& format, const Args&... args) { - return str_format_internal::Streamable( - str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// PrintF() -// -// Writes to stdout given a format string and zero or more arguments. This -// function is functionally equivalent to `std::printf()` (and type-safe); -// prefer `absl::PrintF()` over `std::printf()`. -// -// Example: -// -// std::string_view s = "Ulaanbaatar"; -// absl::PrintF("The capital of Mongolia is %s", s); -// -// Outputs: "The capital of Mongolia is Ulaanbaatar" -// -template <typename... Args> -int PrintF(const FormatSpec<Args...>& format, const Args&... args) { - return str_format_internal::FprintF( - stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// FPrintF() -// -// Writes to a file given a format string and zero or more arguments. This -// function is functionally equivalent to `std::fprintf()` (and type-safe); -// prefer `absl::FPrintF()` over `std::fprintf()`. -// -// Example: -// -// std::string_view s = "Ulaanbaatar"; -// absl::FPrintF(stdout, "The capital of Mongolia is %s", s); -// -// Outputs: "The capital of Mongolia is Ulaanbaatar" -// -template <typename... Args> -int FPrintF(std::FILE* output, const FormatSpec<Args...>& format, - const Args&... args) { - return str_format_internal::FprintF( - output, str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// SNPrintF() -// -// Writes to a sized buffer given a format string and zero or more arguments. -// This function is functionally equivalent to `std::snprintf()` (and -// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`. -// -// In particular, a successful call to `absl::SNPrintF()` writes at most `size` -// bytes of the formatted output to `output`, including a NUL-terminator, and -// returns the number of bytes that would have been written if truncation did -// not occur. In the event of an error, a negative value is returned and `errno` -// is set. -// -// Example: -// -// std::string_view s = "Ulaanbaatar"; -// char output[128]; -// absl::SNPrintF(output, sizeof(output), -// "The capital of Mongolia is %s", s); -// -// Post-condition: output == "The capital of Mongolia is Ulaanbaatar" -// -template <typename... Args> -int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format, - const Args&... args) { - return str_format_internal::SnprintF( - output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// ----------------------------------------------------------------------------- -// Custom Output Formatting Functions -// ----------------------------------------------------------------------------- - -// FormatRawSink -// -// 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 { - public: - // Implicitly convert from any type that provides the hook function as - // described above. - template <typename T, - typename = typename std::enable_if<std::is_constructible< - str_format_internal::FormatRawSinkImpl, T*>::value>::type> - FormatRawSink(T* raw) // NOLINT - : sink_(raw) {} - - private: - friend str_format_internal::FormatRawSinkImpl; - str_format_internal::FormatRawSinkImpl sink_; -}; - -// Format() -// -// Writes a formatted string to an arbitrary sink object (implementing the -// `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. -// -// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for -// custom sinks. The format string, like format strings for `StrFormat()`, is -// checked at compile-time. -// -// On failure, this function returns `false` and the state of the sink is -// unspecified. -template <typename... Args> -bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format, - const Args&... args) { - return str_format_internal::FormatUntyped( - str_format_internal::FormatRawSinkImpl::Extract(raw_sink), - str_format_internal::UntypedFormatSpecImpl::Extract(format), - {str_format_internal::FormatArgImpl(args)...}); -} - -// FormatArg -// -// A type-erased handle to a format argument specifically used as an argument to -// `FormatUntyped()`. You may construct `FormatArg` by passing -// reference-to-const of any printable type. `FormatArg` is both copyable and -// assignable. The source data must outlive the `FormatArg` instance. See -// example below. -// -using FormatArg = str_format_internal::FormatArgImpl; - -// FormatUntyped() -// -// Writes a formatted string to an arbitrary sink object (implementing the -// `absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or -// more additional arguments. -// -// This function acts as the most generic formatting function in the -// `str_format` library. The caller provides a raw sink, an unchecked format -// string, and (usually) a runtime specified list of arguments; no compile-time -// checking of formatting is performed within this function. As a result, a -// caller should check the return value to verify that no error occurred. -// On failure, this function returns `false` and the state of the sink is -// unspecified. -// -// 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. (See `str_format_arg.h` for information on -// the `FormatArg` class.)_ -// -// Example: -// -// std::optional<std::string> FormatDynamic( -// const std::string& in_format, -// const vector<std::string>& in_args) { -// std::string out; -// std::vector<absl::FormatArg> args; -// for (const auto& v : in_args) { -// // It is important that 'v' is a reference to the objects in in_args. -// // The values we pass to FormatArg must outlive the call to -// // FormatUntyped. -// args.emplace_back(v); -// } -// absl::UntypedFormatSpec format(in_format); -// if (!absl::FormatUntyped(&out, format, args)) { -// return std::nullopt; -// } -// return std::move(out); -// } -// -ABSL_MUST_USE_RESULT inline bool FormatUntyped( - FormatRawSink raw_sink, const UntypedFormatSpec& format, - absl::Span<const FormatArg> args) { - return str_format_internal::FormatUntyped( - str_format_internal::FormatRawSinkImpl::Extract(raw_sink), - str_format_internal::UntypedFormatSpecImpl::Extract(format), args); -} - -//------------------------------------------------------------------------------ -// StrFormat Extensions -//------------------------------------------------------------------------------ -// -// AbslFormatConvert() -// -// The StrFormat library provides a customization API for formatting -// user-defined types using absl::StrFormat(). The API relies on detecting an -// overload in the user-defined type's namespace of a free (non-member) -// `AbslFormatConvert()` function, usually as a friend definition with the -// following signature: -// -// absl::FormatConvertResult<...> AbslFormatConvert( -// const X& value, -// const absl::FormatConversionSpec& spec, -// absl::FormatSink *sink); -// -// An `AbslFormatConvert()` overload for a type should only be declared in the -// same file and namespace as said type. -// -// The abstractions within this definition include: -// -// * An `absl::FormatConversionSpec` to specify the fields to pull from a -// user-defined type's format string -// * An `absl::FormatSink` to hold the converted string data during the -// conversion process. -// * An `absl::FormatConvertResult` to hold the status of the returned -// formatting operation -// -// The return type encodes all the conversion characters that your -// AbslFormatConvert() routine accepts. The return value should be {true}. -// A return value of {false} will result in `StrFormat()` returning -// an empty string. This result will be propagated to the result of -// `FormatUntyped`. -// -// Example: -// -// struct Point { -// // To add formatting support to `Point`, we simply need to add a free -// // (non-member) function `AbslFormatConvert()`. This method interprets -// // `spec` to print in the request format. The allowed conversion characters -// // can be restricted via the type of the result, in this example -// // string and integral formatting are allowed (but not, for instance -// // floating point characters like "%f"). You can add such a free function -// // using a friend declaration within the body of the class: -// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString | -// absl::FormatConversionCharSet::kIntegral> -// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec, -// absl::FormatSink* s) { -// if (spec.conversion_char() == absl::FormatConversionChar::s) { -// s->Append(absl::StrCat("x=", p.x, " y=", p.y)); -// } else { -// s->Append(absl::StrCat(p.x, ",", p.y)); -// } -// return {true}; -// } -// -// int x; -// int y; -// }; - -// clang-format off - -// FormatConversionChar -// -// Specifies the formatting character provided in the format string -// passed to `StrFormat()`. -enum class FormatConversionChar : uint8_t { - c, s, // text - d, i, o, u, x, X, // int - f, F, e, E, g, G, a, A, // float - n, p // misc -}; -// clang-format on - -// FormatConversionSpec -// -// Specifies modifications to the conversion of the format string, through use -// of one or more format flags in the source format string. -class FormatConversionSpec { - public: - // FormatConversionSpec::is_basic() - // - // Indicates that width and precision are not specified, and no additional - // flags are set for this conversion character in the format string. - bool is_basic() const { return impl_.is_basic(); } - - // FormatConversionSpec::has_left_flag() - // - // Indicates whether the result should be left justified for this conversion - // character in the format string. This flag is set through use of a '-' - // character in the format string. E.g. "%-s" - bool has_left_flag() const { return impl_.has_left_flag(); } - - // FormatConversionSpec::has_show_pos_flag() - // - // Indicates whether a sign column is prepended to the result for this - // conversion character in the format string, even if the result is positive. - // This flag is set through use of a '+' character in the format string. - // E.g. "%+d" - bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); } - - // FormatConversionSpec::has_sign_col_flag() - // - // Indicates whether a mandatory sign column is added to the result for this - // conversion character. This flag is set through use of a space character - // (' ') in the format string. E.g. "% i" - bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); } - - // FormatConversionSpec::has_alt_flag() - // - // Indicates whether an "alternate" format is applied to the result for this - // conversion character. Alternative forms depend on the type of conversion - // character, and unallowed alternatives are undefined. This flag is set - // through use of a '#' character in the format string. E.g. "%#h" - bool has_alt_flag() const { return impl_.has_alt_flag(); } - - // FormatConversionSpec::has_zero_flag() - // - // Indicates whether zeroes should be prepended to the result for this - // conversion character instead of spaces. This flag is set through use of the - // '0' character in the format string. E.g. "%0f" - bool has_zero_flag() const { return impl_.has_zero_flag(); } - - // FormatConversionSpec::conversion_char() - // - // Returns the underlying conversion character. - FormatConversionChar conversion_char() const { - return impl_.conversion_char(); - } - - // FormatConversionSpec::width() - // - // Returns the specified width (indicated through use of a non-zero integer - // value or '*' character) of the conversion character. If width is - // unspecified, it returns a negative value. - int width() const { return impl_.width(); } - - // FormatConversionSpec::precision() - // - // Returns the specified precision (through use of the '.' character followed - // by a non-zero integer value or '*' character) of the conversion character. - // If precision is unspecified, it returns a negative value. - int precision() const { return impl_.precision(); } - - private: - explicit FormatConversionSpec( - str_format_internal::FormatConversionSpecImpl impl) - : impl_(impl) {} - - friend str_format_internal::FormatConversionSpecImpl; - - absl::str_format_internal::FormatConversionSpecImpl impl_; -}; - -// Type safe OR operator for FormatConversionCharSet to allow accepting multiple -// conversion chars in custom format converters. -constexpr FormatConversionCharSet operator|(FormatConversionCharSet a, - FormatConversionCharSet b) { - return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) | - static_cast<uint64_t>(b)); -} - -// FormatConversionCharSet -// -// Specifies the _accepted_ conversion types as a template parameter to -// FormatConvertResult for custom implementations of `AbslFormatConvert`. -// Note the helper predefined alias definitions (kIntegral, etc.) below. -enum class FormatConversionCharSet : uint64_t { - // text - c = str_format_internal::FormatConversionCharToConvInt('c'), - s = str_format_internal::FormatConversionCharToConvInt('s'), - // integer - d = str_format_internal::FormatConversionCharToConvInt('d'), - i = str_format_internal::FormatConversionCharToConvInt('i'), - o = str_format_internal::FormatConversionCharToConvInt('o'), - u = str_format_internal::FormatConversionCharToConvInt('u'), - x = str_format_internal::FormatConversionCharToConvInt('x'), - X = str_format_internal::FormatConversionCharToConvInt('X'), - // Float - f = str_format_internal::FormatConversionCharToConvInt('f'), - F = str_format_internal::FormatConversionCharToConvInt('F'), - e = str_format_internal::FormatConversionCharToConvInt('e'), - E = str_format_internal::FormatConversionCharToConvInt('E'), - g = str_format_internal::FormatConversionCharToConvInt('g'), - G = str_format_internal::FormatConversionCharToConvInt('G'), - a = str_format_internal::FormatConversionCharToConvInt('a'), - A = str_format_internal::FormatConversionCharToConvInt('A'), - // misc - n = str_format_internal::FormatConversionCharToConvInt('n'), - p = str_format_internal::FormatConversionCharToConvInt('p'), - - // Used for width/precision '*' specification. - kStar = static_cast<uint64_t>( - absl::str_format_internal::FormatConversionCharSetInternal::kStar), - // Some predefined values: - kIntegral = d | i | u | o | x | X, - kFloating = a | e | f | g | A | E | F | G, - kNumeric = kIntegral | kFloating, - kString = s, - kPointer = p, -}; - -// FormatSink -// -// An abstraction to which conversions write their string data. -// -class FormatSink { - public: - // Appends `count` copies of `ch`. - void Append(size_t count, char ch) { sink_->Append(count, ch); } - - void Append(string_view v) { sink_->Append(v); } - - // Appends the first `precision` bytes of `v`. If this is less than - // `width`, spaces will be appended first (if `left` is false), or - // after (if `left` is true) to ensure the total amount appended is - // at least `width`. - bool PutPaddedString(string_view v, int width, int precision, bool left) { - return sink_->PutPaddedString(v, width, precision, left); - } - - private: - friend str_format_internal::FormatSinkImpl; - explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {} - str_format_internal::FormatSinkImpl* sink_; -}; - -// FormatConvertResult -// -// Indicates whether a call to AbslFormatConvert() was successful. -// This return type informs the StrFormat extension framework (through -// ADL but using the return type) of what conversion characters are supported. -// It is strongly discouraged to return {false}, as this will result in an -// empty string in StrFormat. -template <FormatConversionCharSet C> -struct FormatConvertResult { - bool value; -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STR_FORMAT_H_ diff --git a/third_party/abseil_cpp/absl/strings/str_format_test.cc b/third_party/abseil_cpp/absl/strings/str_format_test.cc deleted file mode 100644 index c60027ad297d..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_format_test.cc +++ /dev/null @@ -1,774 +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/str_format.h" - -#include <cstdarg> -#include <cstdint> -#include <cstdio> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/cord.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { -using str_format_internal::FormatArgImpl; - -using FormatEntryPointTest = ::testing::Test; - -TEST_F(FormatEntryPointTest, Format) { - std::string sink; - EXPECT_TRUE(Format(&sink, "A format %d", 123)); - EXPECT_EQ("A format 123", sink); - sink.clear(); - - ParsedFormat<'d'> pc("A format %d"); - EXPECT_TRUE(Format(&sink, pc, 123)); - EXPECT_EQ("A format 123", sink); -} -TEST_F(FormatEntryPointTest, UntypedFormat) { - constexpr const char* formats[] = { - "", - "a", - "%80d", -#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) - // MSVC, NaCL and Android don't support positional syntax. - "complicated multipart %% %1$d format %1$0999d", -#endif // _MSC_VER - }; - for (const char* fmt : formats) { - std::string actual; - int i = 123; - FormatArgImpl arg_123(i); - absl::Span<const FormatArgImpl> args(&arg_123, 1); - UntypedFormatSpec format(fmt); - - EXPECT_TRUE(FormatUntyped(&actual, format, args)); - char buf[4096]{}; - snprintf(buf, sizeof(buf), fmt, 123); - EXPECT_EQ( - str_format_internal::FormatPack( - str_format_internal::UntypedFormatSpecImpl::Extract(format), args), - buf); - EXPECT_EQ(actual, buf); - } - // The internal version works with a preparsed format. - ParsedFormat<'d'> pc("A format %d"); - int i = 345; - FormatArg arg(i); - std::string out; - EXPECT_TRUE(str_format_internal::FormatUntyped( - &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1})); - EXPECT_EQ("A format 345", out); -} - -TEST_F(FormatEntryPointTest, StringFormat) { - EXPECT_EQ("123", StrFormat("%d", 123)); - constexpr absl::string_view view("=%d=", 4); - EXPECT_EQ("=123=", StrFormat(view, 123)); -} - -TEST_F(FormatEntryPointTest, AppendFormat) { - std::string s; - std::string& r = StrAppendFormat(&s, "%d", 123); - EXPECT_EQ(&s, &r); // should be same object - EXPECT_EQ("123", r); -} - -TEST_F(FormatEntryPointTest, AppendFormatFail) { - std::string s = "orig"; - - UntypedFormatSpec format(" more %d"); - FormatArgImpl arg("not an int"); - - EXPECT_EQ("orig", - str_format_internal::AppendPack( - &s, str_format_internal::UntypedFormatSpecImpl::Extract(format), - {&arg, 1})); -} - - -TEST_F(FormatEntryPointTest, ManyArgs) { - EXPECT_EQ("24", StrFormat("%24$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)); - EXPECT_EQ("60", StrFormat("%60$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60)); -} - -TEST_F(FormatEntryPointTest, Preparsed) { - ParsedFormat<'d'> pc("%d"); - EXPECT_EQ("123", StrFormat(pc, 123)); - // rvalue ok? - EXPECT_EQ("123", StrFormat(ParsedFormat<'d'>("%d"), 123)); - constexpr absl::string_view view("=%d=", 4); - EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123)); -} - -TEST_F(FormatEntryPointTest, FormatCountCapture) { - int n = 0; - EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n))); - EXPECT_EQ(0, n); - EXPECT_EQ("123", StrFormat("%d%n", 123, FormatCountCapture(&n))); - EXPECT_EQ(3, n); -} - -TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) { - // Should reject int*. - int n = 0; - UntypedFormatSpec format("%d%n"); - int i = 123, *ip = &n; - FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)}; - - EXPECT_EQ("", str_format_internal::FormatPack( - str_format_internal::UntypedFormatSpecImpl::Extract(format), - absl::MakeSpan(args))); -} - -TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) { - int n1 = 0; - int n2 = 0; - EXPECT_EQ(" 1 2", - StrFormat("%5d%n%10d%n", 1, FormatCountCapture(&n1), 2, - FormatCountCapture(&n2))); - EXPECT_EQ(5, n1); - EXPECT_EQ(15, n2); -} - -TEST_F(FormatEntryPointTest, FormatCountCaptureExample) { - int n; - std::string s; - StrAppendFormat(&s, "%s: %n%s\n", "(1,1)", FormatCountCapture(&n), "(1,2)"); - StrAppendFormat(&s, "%*s%s\n", n, "", "(2,2)"); - EXPECT_EQ(7, n); - EXPECT_EQ( - "(1,1): (1,2)\n" - " (2,2)\n", - s); -} - -TEST_F(FormatEntryPointTest, Stream) { - const std::string formats[] = { - "", - "a", - "%80d", - "%d %u %c %s %f %g", -#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) - // MSVC, NaCL and Android don't support positional syntax. - "complicated multipart %% %1$d format %1$080d", -#endif // _MSC_VER - }; - std::string buf(4096, '\0'); - for (const auto& fmt : formats) { - const auto parsed = - ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt); - std::ostringstream oss; - oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01); - int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), // - 123, 3, 49, "multistreaming!!!", 1.01, 1.01); - ASSERT_TRUE(oss) << fmt; - ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size()) - << fmt_result; - EXPECT_EQ(buf.c_str(), oss.str()); - } -} - -TEST_F(FormatEntryPointTest, StreamOk) { - std::ostringstream oss; - oss << StreamFormat("hello %d", 123); - EXPECT_EQ("hello 123", oss.str()); - EXPECT_TRUE(oss.good()); -} - -TEST_F(FormatEntryPointTest, StreamFail) { - std::ostringstream oss; - UntypedFormatSpec format("hello %d"); - FormatArgImpl arg("non-numeric"); - oss << str_format_internal::Streamable( - str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1}); - EXPECT_EQ("hello ", oss.str()); // partial write - EXPECT_TRUE(oss.fail()); -} - -std::string WithSnprintf(const char* fmt, ...) { - std::string buf; - buf.resize(128); - va_list va; - va_start(va, fmt); - int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va); - va_end(va); - EXPECT_GE(r, 0); - EXPECT_LT(r, buf.size()); - buf.resize(r); - return buf; -} - -TEST_F(FormatEntryPointTest, FloatPrecisionArg) { - // Test that positional parameters for width and precision - // are indexed to precede the value. - // Also sanity check the same formats against snprintf. - EXPECT_EQ("0.1", StrFormat("%.1f", 0.1)); - EXPECT_EQ("0.1", WithSnprintf("%.1f", 0.1)); - EXPECT_EQ(" 0.1", StrFormat("%*.1f", 5, 0.1)); - EXPECT_EQ(" 0.1", WithSnprintf("%*.1f", 5, 0.1)); - EXPECT_EQ("0.1", StrFormat("%.*f", 1, 0.1)); - EXPECT_EQ("0.1", WithSnprintf("%.*f", 1, 0.1)); - EXPECT_EQ(" 0.1", StrFormat("%*.*f", 5, 1, 0.1)); - EXPECT_EQ(" 0.1", WithSnprintf("%*.*f", 5, 1, 0.1)); -} -namespace streamed_test { -struct X {}; -std::ostream& operator<<(std::ostream& os, const X&) { - return os << "X"; -} -} // streamed_test - -TEST_F(FormatEntryPointTest, FormatStreamed) { - EXPECT_EQ("123", StrFormat("%s", FormatStreamed(123))); - EXPECT_EQ(" 123", StrFormat("%5s", FormatStreamed(123))); - EXPECT_EQ("123 ", StrFormat("%-5s", FormatStreamed(123))); - EXPECT_EQ("X", StrFormat("%s", FormatStreamed(streamed_test::X()))); - EXPECT_EQ("123", StrFormat("%s", FormatStreamed(StreamFormat("%d", 123)))); -} - -// Helper class that creates a temporary file and exposes a FILE* to it. -// It will close the file on destruction. -class TempFile { - public: - TempFile() : file_(std::tmpfile()) {} - ~TempFile() { std::fclose(file_); } - - std::FILE* file() const { return file_; } - - // Read the file into a string. - std::string ReadFile() { - std::fseek(file_, 0, SEEK_END); - int size = std::ftell(file_); - EXPECT_GT(size, 0); - std::rewind(file_); - std::string str(2 * size, ' '); - int read_bytes = std::fread(&str[0], 1, str.size(), file_); - EXPECT_EQ(read_bytes, size); - str.resize(read_bytes); - EXPECT_TRUE(std::feof(file_)); - return str; - } - - private: - std::FILE* file_; -}; - -TEST_F(FormatEntryPointTest, FPrintF) { - TempFile tmp; - int result = - FPrintF(tmp.file(), "STRING: %s NUMBER: %010d", std::string("ABC"), -19); - EXPECT_EQ(result, 30); - EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); -} - -TEST_F(FormatEntryPointTest, FPrintFError) { - errno = 0; - int result = FPrintF(stdin, "ABC"); - EXPECT_LT(result, 0); - EXPECT_EQ(errno, EBADF); -} - -#ifdef __GLIBC__ -TEST_F(FormatEntryPointTest, FprintfTooLarge) { - std::FILE* f = std::fopen("/dev/null", "w"); - int width = 2000000000; - errno = 0; - int result = FPrintF(f, "%*d %*d", width, 0, width, 0); - EXPECT_LT(result, 0); - EXPECT_EQ(errno, EFBIG); - std::fclose(f); -} - -TEST_F(FormatEntryPointTest, PrintF) { - int stdout_tmp = dup(STDOUT_FILENO); - - TempFile tmp; - std::fflush(stdout); - dup2(fileno(tmp.file()), STDOUT_FILENO); - - int result = PrintF("STRING: %s NUMBER: %010d", std::string("ABC"), -19); - - std::fflush(stdout); - dup2(stdout_tmp, STDOUT_FILENO); - close(stdout_tmp); - - EXPECT_EQ(result, 30); - EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); -} -#endif // __GLIBC__ - -TEST_F(FormatEntryPointTest, SNPrintF) { - char buffer[16]; - int result = - SNPrintF(buffer, sizeof(buffer), "STRING: %s", std::string("ABC")); - EXPECT_EQ(result, 11); - EXPECT_EQ(std::string(buffer), "STRING: ABC"); - - result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456); - EXPECT_EQ(result, 14); - EXPECT_EQ(std::string(buffer), "NUMBER: 123456"); - - result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567); - EXPECT_EQ(result, 15); - EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); - - result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678); - EXPECT_EQ(result, 16); - EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); - - result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789); - EXPECT_EQ(result, 17); - EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); - - result = SNPrintF(nullptr, 0, "Just checking the %s of the output.", "size"); - EXPECT_EQ(result, 37); -} - -TEST(StrFormat, BehavesAsDocumented) { - std::string s = absl::StrFormat("%s, %d!", "Hello", 123); - EXPECT_EQ("Hello, 123!", s); - // The format of a replacement is - // '%'[position][flags][width['.'precision]][length_modifier][format] - EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10"); - // Text conversion: - // "c" - Character. Eg: 'a' -> "A", 20 -> " " - EXPECT_EQ(StrFormat("%c", 'a'), "a"); - EXPECT_EQ(StrFormat("%c", 0x20), " "); - // Formats char and integral types: int, long, uint64_t, etc. - 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++" - // 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"); - EXPECT_EQ(StrFormat("%d", int{10}), "10"); - EXPECT_EQ(StrFormat("%d", long{10}), "10"); // NOLINT - EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10"); - // d,i - signed decimal Eg: -10 -> "-10" - EXPECT_EQ(StrFormat("%d", -10), "-10"); - EXPECT_EQ(StrFormat("%i", -10), "-10"); - // o - octal Eg: 10 -> "12" - EXPECT_EQ(StrFormat("%o", 10), "12"); - // u - unsigned decimal Eg: 10 -> "10" - EXPECT_EQ(StrFormat("%u", 10), "10"); - // x/X - lower,upper case hex Eg: 10 -> "a"/"A" - EXPECT_EQ(StrFormat("%x", 10), "a"); - EXPECT_EQ(StrFormat("%X", 10), "A"); - // Floating-point, with upper/lower-case output. - // These format floating points types: float, double, long double, etc. - EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0"); - EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0"); - const long double long_double = 1.0; - EXPECT_EQ(StrFormat("%.1f", long_double), "1.0"); - // These also format integral types: char, int, long, uint64_t, etc.: - EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0"); - EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0"); - EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0"); // NOLINT - EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0"); - // f/F - decimal. Eg: 123456789 -> "123456789.000000" - EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000"); - EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000"); - // e/E - exponentiated Eg: .01 -> "1.00000e-2"/"1.00000E-2" - EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02"); - EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02"); - // g/G - exponentiate to fit Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10" - EXPECT_EQ(StrFormat("%g", .01), "0.01"); - EXPECT_EQ(StrFormat("%g", 1e10), "1e+10"); - EXPECT_EQ(StrFormat("%G", 1e10), "1E+10"); - // a/A - lower,upper case hex Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1" - -// On Android platform <=21, there is a regression in hexfloat formatting. -#if !defined(__ANDROID_API__) || __ANDROID_API__ > 21 - EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1"); // .1 to fix MSVC output - EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1"); // .1 to fix MSVC output -#endif - - // Other conversion - int64_t value = 0x7ffdeb4; - auto ptr_value = static_cast<uintptr_t>(value); - const int& something = *reinterpret_cast<const int*>(ptr_value); - EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value)); - - // Output widths are supported, with optional flags. - EXPECT_EQ(StrFormat("%3d", 1), " 1"); - EXPECT_EQ(StrFormat("%3d", 123456), "123456"); - EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23"); - EXPECT_EQ(StrFormat("%+d", 1), "+1"); - EXPECT_EQ(StrFormat("% d", 1), " 1"); - EXPECT_EQ(StrFormat("%-4d", -1), "-1 "); - EXPECT_EQ(StrFormat("%#o", 10), "012"); - EXPECT_EQ(StrFormat("%#x", 15), "0xf"); - EXPECT_EQ(StrFormat("%04d", 8), "0008"); - // Posix positional substitution. - EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"), - "veni, vidi, vici!"); - // Length modifiers are ignored. - EXPECT_EQ(StrFormat("%hhd", int{1}), "1"); - EXPECT_EQ(StrFormat("%hd", int{1}), "1"); - EXPECT_EQ(StrFormat("%ld", int{1}), "1"); - EXPECT_EQ(StrFormat("%lld", int{1}), "1"); - EXPECT_EQ(StrFormat("%Ld", int{1}), "1"); - EXPECT_EQ(StrFormat("%jd", int{1}), "1"); - EXPECT_EQ(StrFormat("%zd", int{1}), "1"); - EXPECT_EQ(StrFormat("%td", int{1}), "1"); - EXPECT_EQ(StrFormat("%qd", int{1}), "1"); -} - -using str_format_internal::ExtendedParsedFormat; -using str_format_internal::ParsedFormatBase; - -struct SummarizeConsumer { - std::string* out; - explicit SummarizeConsumer(std::string* out) : out(out) {} - - bool Append(string_view s) { - *out += "[" + std::string(s) + "]"; - return true; - } - - bool ConvertOne(const str_format_internal::UnboundConversion& conv, - string_view s) { - *out += "{"; - *out += std::string(s); - *out += ":"; - *out += std::to_string(conv.arg_position) + "$"; - if (conv.width.is_from_arg()) { - *out += std::to_string(conv.width.get_from_arg()) + "$*"; - } - if (conv.precision.is_from_arg()) { - *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*"; - } - *out += str_format_internal::FormatConversionCharToChar(conv.conv); - *out += "}"; - return true; - } -}; - -std::string SummarizeParsedFormat(const ParsedFormatBase& pc) { - std::string out; - if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!"; - return out; -} - -using ParsedFormatTest = ::testing::Test; - -TEST_F(ParsedFormatTest, SimpleChecked) { - EXPECT_EQ("[ABC]{d:1$d}[DEF]", - SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF"))); - EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", - SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f"))); - EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}", - SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d"))); -} - -TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) { - auto f = ParsedFormat<'d'>::New("ABC%dDEF"); - ASSERT_TRUE(f); - EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f)); - - std::string format = "%sFFF%dZZZ%f"; - auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format); - - ASSERT_TRUE(f2); - EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); - - f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f"); - - ASSERT_TRUE(f2); - EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); - - auto star = ParsedFormat<'*', 'd'>::New("%*d"); - ASSERT_TRUE(star); - EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star)); - - auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d"); - ASSERT_TRUE(dollar); - EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar)); - // with reuse - dollar = ParsedFormat<'d', '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, SimpleUncheckedIgnoredArgs) { - EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC"))); - EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC"))); - EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s"))); - auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC"); - ASSERT_TRUE(f); - EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); - f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC"); - ASSERT_TRUE(f); - EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f)); - f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s"); - ASSERT_TRUE(f); - EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f)); -} - -TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) { - EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x")); - EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x")); -} - -TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) { - EXPECT_FALSE(ParsedFormat<'d'>::New("")); - - EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d")); - - std::string format = "%sFFF%dZZZ%f"; - 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 - -TEST_F(ParsedFormatTest, UncheckedCorrect) { - auto f = - ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF"); - ASSERT_TRUE(f); - EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f)); - - std::string format = "%sFFF%dZZZ%f"; - auto f2 = ExtendedParsedFormat< - absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d, - absl::FormatConversionCharSet::kFloating>::New(format); - - ASSERT_TRUE(f2); - EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); - - f2 = ExtendedParsedFormat< - absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d, - absl::FormatConversionCharSet::kFloating>::New("%s %d %f"); - - ASSERT_TRUE(f2); - EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); - - auto star = - ExtendedParsedFormat<absl::FormatConversionCharSet::kStar, - absl::FormatConversionCharSet::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"); - 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"); - 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"); - ASSERT_TRUE(f); - EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); - f = ExtendedParsedFormat< - absl::FormatConversionCharSet::d, - absl::FormatConversionCharSet::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"); - 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"); - 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"); - 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<absl::FormatConversionCharSet::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))); -} - -TEST_F(ParsedFormatTest, RegressionMixPositional) { - EXPECT_FALSE( - (ExtendedParsedFormat<absl::FormatConversionCharSet::d, - absl::FormatConversionCharSet::o>::New("%1$d %o"))); -} - -using FormatWrapperTest = ::testing::Test; - -// Plain wrapper for StrFormat. -template <typename... Args> -std::string WrappedFormat(const absl::FormatSpec<Args...>& format, - const Args&... args) { - return StrFormat(format, args...); -} - -TEST_F(FormatWrapperTest, ConstexprStringFormat) { - EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there"); -} - -TEST_F(FormatWrapperTest, ParsedFormat) { - ParsedFormat<'s'> format("%s there"); - EXPECT_EQ(WrappedFormat(format, "hello"), "hello there"); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -using FormatExtensionTest = ::testing::Test; - -struct Point { - friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString | - absl::FormatConversionCharSet::kIntegral> - AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec, - absl::FormatSink* s) { - if (spec.conversion_char() == absl::FormatConversionChar::s) { - s->Append(absl::StrCat("x=", p.x, " y=", p.y)); - } else { - s->Append(absl::StrCat(p.x, ",", p.y)); - } - return {true}; - } - - int x = 10; - int y = 20; -}; - -TEST_F(FormatExtensionTest, AbslFormatConvertExample) { - Point p; - EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z"); - EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z"); - - // Typed formatting will fail to compile an invalid format. - // StrFormat("%f", p); // Does not compile. - std::string actual; - absl::UntypedFormatSpec f1("%f"); - // FormatUntyped will return false for bad character. - EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)})); -} - -// Some codegen thunks that we can use to easily dump the generated assembly for -// different StrFormat calls. - -std::string CodegenAbslStrFormatInt(int i) { // NOLINT - return absl::StrFormat("%d", i); -} - -std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s, - int64_t i64) { // NOLINT - return absl::StrFormat("%d %s %d", i, s, i64); -} - -void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT - absl::StrAppendFormat(out, "%d", i); -} - -void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i, - const std::string& s, - int64_t i64) { // NOLINT - absl::StrAppendFormat(out, "%d %s %d", i, s, i64); -} diff --git a/third_party/abseil_cpp/absl/strings/str_join.h b/third_party/abseil_cpp/absl/strings/str_join.h deleted file mode 100644 index ae5731a42b3d..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_join.h +++ /dev/null @@ -1,293 +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. -// -// ----------------------------------------------------------------------------- -// File: str_join.h -// ----------------------------------------------------------------------------- -// -// This header file contains functions for joining a range of elements and -// returning the result as a std::string. StrJoin operations are specified by -// passing a range, a separator string to use between the elements joined, and -// an optional Formatter responsible for converting each argument in the range -// to a string. If omitted, a default `AlphaNumFormatter()` is called on the -// elements to be joined, using the same formatting that `absl::StrCat()` uses. -// This package defines a number of default formatters, and you can define your -// own implementations. -// -// Ranges are specified by passing a container with `std::begin()` and -// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a -// brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous -// objects. The separator string is specified as an `absl::string_view`. -// -// Because the default formatter uses the `absl::AlphaNum` class, -// `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on -// collections of strings, ints, floats, doubles, etc. -// -// Example: -// -// std::vector<std::string> v = {"foo", "bar", "baz"}; -// std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("foo-bar-baz", s); -// -// See comments on the `absl::StrJoin()` function for more examples. - -#ifndef ABSL_STRINGS_STR_JOIN_H_ -#define ABSL_STRINGS_STR_JOIN_H_ - -#include <cstdio> -#include <cstring> -#include <initializer_list> -#include <iterator> -#include <string> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/strings/internal/str_join_internal.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// Concept: Formatter -// ----------------------------------------------------------------------------- -// -// A Formatter is a function object that is responsible for formatting its -// argument as a string and appending it to a given output std::string. -// Formatters may be implemented as function objects, lambdas, or normal -// functions. You may provide your own Formatter to enable `absl::StrJoin()` to -// work with arbitrary types. -// -// The following is an example of a custom Formatter that simply uses -// `std::to_string()` to format an integer as a std::string. -// -// struct MyFormatter { -// void operator()(std::string* out, int i) const { -// out->append(std::to_string(i)); -// } -// }; -// -// You would use the above formatter by passing an instance of it as the final -// argument to `absl::StrJoin()`: -// -// std::vector<int> v = {1, 2, 3, 4}; -// std::string s = absl::StrJoin(v, "-", MyFormatter()); -// EXPECT_EQ("1-2-3-4", s); -// -// The following standard formatters are provided within this file: -// -// - `AlphaNumFormatter()` (the default) -// - `StreamFormatter()` -// - `PairFormatter()` -// - `DereferenceFormatter()` - -// AlphaNumFormatter() -// -// Default formatter used if none is specified. Uses `absl::AlphaNum` to convert -// numeric arguments to strings. -inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() { - return strings_internal::AlphaNumFormatterImpl(); -} - -// StreamFormatter() -// -// Formats its argument using the << operator. -inline strings_internal::StreamFormatterImpl StreamFormatter() { - return strings_internal::StreamFormatterImpl(); -} - -// Function Template: PairFormatter(Formatter, absl::string_view, Formatter) -// -// Formats a `std::pair` by putting a given separator between the pair's -// `.first` and `.second` members. This formatter allows you to specify -// custom Formatters for both the first and second member of each pair. -template <typename FirstFormatter, typename SecondFormatter> -inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter> -PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) { - return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>( - std::move(f1), sep, std::move(f2)); -} - -// Function overload of PairFormatter() for using a default -// `AlphaNumFormatter()` for each Formatter in the pair. -inline strings_internal::PairFormatterImpl< - strings_internal::AlphaNumFormatterImpl, - strings_internal::AlphaNumFormatterImpl> -PairFormatter(absl::string_view sep) { - return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter()); -} - -// Function Template: DereferenceFormatter(Formatter) -// -// Formats its argument by dereferencing it and then applying the given -// formatter. This formatter is useful for formatting a container of -// pointer-to-T. This pattern often shows up when joining repeated fields in -// protocol buffers. -template <typename Formatter> -strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter( - Formatter&& f) { - return strings_internal::DereferenceFormatterImpl<Formatter>( - std::forward<Formatter>(f)); -} - -// Function overload of `DererefenceFormatter()` for using a default -// `AlphaNumFormatter()`. -inline strings_internal::DereferenceFormatterImpl< - strings_internal::AlphaNumFormatterImpl> -DereferenceFormatter() { - return strings_internal::DereferenceFormatterImpl< - strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter()); -} - -// ----------------------------------------------------------------------------- -// StrJoin() -// ----------------------------------------------------------------------------- -// -// Joins a range of elements and returns the result as a std::string. -// `absl::StrJoin()` takes a range, a separator string to use between the -// elements joined, and an optional Formatter responsible for converting each -// argument in the range to a string. -// -// If omitted, the default `AlphaNumFormatter()` is called on the elements to be -// joined. -// -// Example 1: -// // Joins a collection of strings. This pattern also works with a collection -// // of `absl::string_view` or even `const char*`. -// std::vector<std::string> v = {"foo", "bar", "baz"}; -// std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("foo-bar-baz", s); -// -// Example 2: -// // Joins the values in the given `std::initializer_list<>` specified using -// // brace initialization. This pattern also works with an initializer_list -// // of ints or `absl::string_view` -- any `AlphaNum`-compatible type. -// std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-"); -// EXPECT_EQ("foo-bar-baz", s); -// -// Example 3: -// // Joins a collection of ints. This pattern also works with floats, -// // doubles, int64s -- any `StrCat()`-compatible type. -// std::vector<int> v = {1, 2, 3, -4}; -// std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3--4", s); -// -// Example 4: -// // Joins a collection of pointer-to-int. By default, pointers are -// // dereferenced and the pointee is formatted using the default format for -// // that type; such dereferencing occurs for all levels of indirection, so -// // this pattern works just as well for `std::vector<int**>` as for -// // `std::vector<int*>`. -// int x = 1, y = 2, z = 3; -// std::vector<int*> v = {&x, &y, &z}; -// std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3", s); -// -// Example 5: -// // Dereferencing of `std::unique_ptr<>` is also supported: -// std::vector<std::unique_ptr<int>> v -// v.emplace_back(new int(1)); -// v.emplace_back(new int(2)); -// v.emplace_back(new int(3)); -// std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3", s); -// -// Example 6: -// // Joins a `std::map`, with each key-value pair separated by an equals -// // sign. This pattern would also work with, say, a -// // `std::vector<std::pair<>>`. -// std::map<std::string, int> m = { -// std::make_pair("a", 1), -// std::make_pair("b", 2), -// std::make_pair("c", 3)}; -// std::string s = absl::StrJoin(m, ",", absl::PairFormatter("=")); -// EXPECT_EQ("a=1,b=2,c=3", s); -// -// Example 7: -// // These examples show how `absl::StrJoin()` handles a few common edge -// // cases: -// std::vector<std::string> v_empty; -// EXPECT_EQ("", absl::StrJoin(v_empty, "-")); -// -// std::vector<std::string> v_one_item = {"foo"}; -// EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-")); -// -// std::vector<std::string> v_empty_string = {""}; -// EXPECT_EQ("", absl::StrJoin(v_empty_string, "-")); -// -// std::vector<std::string> v_one_item_empty_string = {"a", ""}; -// EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-")); -// -// std::vector<std::string> v_two_empty_string = {"", ""}; -// EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-")); -// -// Example 8: -// // Joins a `std::tuple<T...>` of heterogeneous types, converting each to -// // a std::string using the `absl::AlphaNum` class. -// std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); -// EXPECT_EQ("123-abc-0.456", s); - -template <typename Iterator, typename Formatter> -std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, - Formatter&& fmt) { - return strings_internal::JoinAlgorithm(start, end, sep, fmt); -} - -template <typename Range, typename Formatter> -std::string StrJoin(const Range& range, absl::string_view separator, - Formatter&& fmt) { - return strings_internal::JoinRange(range, separator, fmt); -} - -template <typename T, typename Formatter> -std::string StrJoin(std::initializer_list<T> il, absl::string_view separator, - Formatter&& fmt) { - return strings_internal::JoinRange(il, separator, fmt); -} - -template <typename... T, typename Formatter> -std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator, - Formatter&& fmt) { - return strings_internal::JoinAlgorithm(value, separator, fmt); -} - -template <typename Iterator> -std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) { - return strings_internal::JoinRange(start, end, separator); -} - -template <typename Range> -std::string StrJoin(const Range& range, absl::string_view separator) { - return strings_internal::JoinRange(range, separator); -} - -template <typename T> -std::string StrJoin(std::initializer_list<T> il, - absl::string_view separator) { - return strings_internal::JoinRange(il, separator); -} - -template <typename... T> -std::string StrJoin(const std::tuple<T...>& value, - absl::string_view separator) { - return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter()); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STR_JOIN_H_ diff --git a/third_party/abseil_cpp/absl/strings/str_join_benchmark.cc b/third_party/abseil_cpp/absl/strings/str_join_benchmark.cc deleted file mode 100644 index d6f689ff300b..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_join_benchmark.cc +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT 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_join.h" - -#include <string> -#include <vector> -#include <utility> - -#include "benchmark/benchmark.h" - -namespace { - -void BM_Join2_Strings(benchmark::State& state) { - const int string_len = state.range(0); - const int num_strings = state.range(1); - const std::string s(string_len, 'x'); - const std::vector<std::string> v(num_strings, s); - for (auto _ : state) { - std::string s = absl::StrJoin(v, "-"); - benchmark::DoNotOptimize(s); - } -} -BENCHMARK(BM_Join2_Strings) - ->ArgPair(1 << 0, 1 << 3) - ->ArgPair(1 << 10, 1 << 3) - ->ArgPair(1 << 13, 1 << 3) - ->ArgPair(1 << 0, 1 << 10) - ->ArgPair(1 << 10, 1 << 10) - ->ArgPair(1 << 13, 1 << 10) - ->ArgPair(1 << 0, 1 << 13) - ->ArgPair(1 << 10, 1 << 13) - ->ArgPair(1 << 13, 1 << 13); - -void BM_Join2_Ints(benchmark::State& state) { - const int num_ints = state.range(0); - const std::vector<int> v(num_ints, 42); - for (auto _ : state) { - std::string s = absl::StrJoin(v, "-"); - benchmark::DoNotOptimize(s); - } -} -BENCHMARK(BM_Join2_Ints)->Range(0, 1 << 13); - -void BM_Join2_KeysAndValues(benchmark::State& state) { - const int string_len = state.range(0); - const int num_pairs = state.range(1); - const std::string s(string_len, 'x'); - const std::vector<std::pair<std::string, int>> v(num_pairs, - std::make_pair(s, 42)); - for (auto _ : state) { - std::string s = absl::StrJoin(v, ",", absl::PairFormatter("=")); - benchmark::DoNotOptimize(s); - } -} -BENCHMARK(BM_Join2_KeysAndValues) - ->ArgPair(1 << 0, 1 << 3) - ->ArgPair(1 << 10, 1 << 3) - ->ArgPair(1 << 13, 1 << 3) - ->ArgPair(1 << 0, 1 << 10) - ->ArgPair(1 << 10, 1 << 10) - ->ArgPair(1 << 13, 1 << 10) - ->ArgPair(1 << 0, 1 << 13) - ->ArgPair(1 << 10, 1 << 13) - ->ArgPair(1 << 13, 1 << 13); - -void BM_JoinStreamable(benchmark::State& state) { - const int string_len = state.range(0); - const int num_strings = state.range(1); - const std::vector<std::string> v(num_strings, std::string(string_len, 'x')); - for (auto _ : state) { - std::string s = absl::StrJoin(v, "", absl::StreamFormatter()); - benchmark::DoNotOptimize(s); - } -} -BENCHMARK(BM_JoinStreamable) - ->ArgPair(0, 0) - ->ArgPair(16, 1) - ->ArgPair(256, 1) - ->ArgPair(16, 16) - ->ArgPair(256, 16) - ->ArgPair(16, 256) - ->ArgPair(256, 256); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_join_test.cc b/third_party/abseil_cpp/absl/strings/str_join_test.cc deleted file mode 100644 index 2be6256e43f7..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_join_test.cc +++ /dev/null @@ -1,474 +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. - -// Unit tests for all join.h functions - -#include "absl/strings/str_join.h" - -#include <cstddef> -#include <cstdint> -#include <cstdio> -#include <functional> -#include <initializer_list> -#include <map> -#include <memory> -#include <ostream> -#include <tuple> -#include <type_traits> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/macros.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_split.h" - -namespace { - -TEST(StrJoin, APIExamples) { - { - // Collection of strings - std::vector<std::string> v = {"foo", "bar", "baz"}; - EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-")); - } - - { - // Collection of absl::string_view - std::vector<absl::string_view> v = {"foo", "bar", "baz"}; - EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-")); - } - - { - // Collection of const char* - std::vector<const char*> v = {"foo", "bar", "baz"}; - EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-")); - } - - { - // Collection of non-const char* - std::string a = "foo", b = "bar", c = "baz"; - std::vector<char*> v = {&a[0], &b[0], &c[0]}; - EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-")); - } - - { - // Collection of ints - std::vector<int> v = {1, 2, 3, -4}; - EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-")); - } - - { - // Literals passed as a std::initializer_list - std::string s = absl::StrJoin({"a", "b", "c"}, "-"); - EXPECT_EQ("a-b-c", s); - } - { - // Join a std::tuple<T...>. - std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); - EXPECT_EQ("123-abc-0.456", s); - } - - { - // Collection of unique_ptrs - std::vector<std::unique_ptr<int>> v; - v.emplace_back(new int(1)); - v.emplace_back(new int(2)); - v.emplace_back(new int(3)); - EXPECT_EQ("1-2-3", absl::StrJoin(v, "-")); - } - - { - // Array of ints - const int a[] = {1, 2, 3, -4}; - EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-")); - } - - { - // Collection of pointers - int x = 1, y = 2, z = 3; - std::vector<int*> v = {&x, &y, &z}; - EXPECT_EQ("1-2-3", absl::StrJoin(v, "-")); - } - - { - // Collection of pointers to pointers - int x = 1, y = 2, z = 3; - int *px = &x, *py = &y, *pz = &z; - std::vector<int**> v = {&px, &py, &pz}; - EXPECT_EQ("1-2-3", absl::StrJoin(v, "-")); - } - - { - // Collection of pointers to std::string - std::string a("a"), b("b"); - std::vector<std::string*> v = {&a, &b}; - EXPECT_EQ("a-b", absl::StrJoin(v, "-")); - } - - { - // A std::map, which is a collection of std::pair<>s. - std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}}; - EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("="))); - } - - { - // Shows absl::StrSplit and absl::StrJoin working together. This example is - // equivalent to s/=/-/g. - const std::string s = "a=b=c=d"; - EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-")); - } - - // - // A few examples of edge cases - // - - { - // Empty range yields an empty string. - std::vector<std::string> v; - EXPECT_EQ("", absl::StrJoin(v, "-")); - } - - { - // A range of 1 element gives a string with that element but no - // separator. - std::vector<std::string> v = {"foo"}; - EXPECT_EQ("foo", absl::StrJoin(v, "-")); - } - - { - // A range with a single empty string element - std::vector<std::string> v = {""}; - EXPECT_EQ("", absl::StrJoin(v, "-")); - } - - { - // A range with 2 elements, one of which is an empty string - std::vector<std::string> v = {"a", ""}; - EXPECT_EQ("a-", absl::StrJoin(v, "-")); - } - - { - // A range with 2 empty elements. - std::vector<std::string> v = {"", ""}; - EXPECT_EQ("-", absl::StrJoin(v, "-")); - } - - { - // A std::vector of bool. - std::vector<bool> v = {true, false, true}; - EXPECT_EQ("1-0-1", absl::StrJoin(v, "-")); - } -} - -TEST(StrJoin, CustomFormatter) { - std::vector<std::string> v{"One", "Two", "Three"}; - { - std::string joined = - absl::StrJoin(v, "", [](std::string* out, const std::string& in) { - absl::StrAppend(out, "(", in, ")"); - }); - EXPECT_EQ("(One)(Two)(Three)", joined); - } - { - class ImmovableFormatter { - public: - void operator()(std::string* out, const std::string& in) { - absl::StrAppend(out, "(", in, ")"); - } - ImmovableFormatter() {} - ImmovableFormatter(const ImmovableFormatter&) = delete; - }; - EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter())); - } - { - class OverloadedFormatter { - public: - void operator()(std::string* out, const std::string& in) { - absl::StrAppend(out, "(", in, ")"); - } - void operator()(std::string* out, const std::string& in) const { - absl::StrAppend(out, "[", in, "]"); - } - }; - EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter())); - const OverloadedFormatter fmt = {}; - EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt)); - } -} - -// -// Tests the Formatters -// - -TEST(AlphaNumFormatter, FormatterAPI) { - // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test - // of what AlphaNum can convert. - auto f = absl::AlphaNumFormatter(); - std::string s; - f(&s, "Testing: "); - f(&s, static_cast<int>(1)); - f(&s, static_cast<int16_t>(2)); - f(&s, static_cast<int64_t>(3)); - f(&s, static_cast<float>(4)); - f(&s, static_cast<double>(5)); - f(&s, static_cast<unsigned>(6)); - f(&s, static_cast<size_t>(7)); - f(&s, absl::string_view(" OK")); - EXPECT_EQ("Testing: 1234567 OK", s); -} - -// Make sure people who are mistakenly using std::vector<bool> even though -// they're not memory-constrained can use absl::AlphaNumFormatter(). -TEST(AlphaNumFormatter, VectorOfBool) { - auto f = absl::AlphaNumFormatter(); - std::string s; - std::vector<bool> v = {true, false, true}; - f(&s, *v.cbegin()); - f(&s, *v.begin()); - f(&s, v[1]); - EXPECT_EQ("110", s); -} - -TEST(AlphaNumFormatter, AlphaNum) { - auto f = absl::AlphaNumFormatter(); - std::string s; - f(&s, absl::AlphaNum("hello")); - EXPECT_EQ("hello", s); -} - -struct StreamableType { - std::string contents; -}; -inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) { - os << "Streamable:" << t.contents; - return os; -} - -TEST(StreamFormatter, FormatterAPI) { - auto f = absl::StreamFormatter(); - std::string s; - f(&s, "Testing: "); - f(&s, static_cast<int>(1)); - f(&s, static_cast<int16_t>(2)); - f(&s, static_cast<int64_t>(3)); - f(&s, static_cast<float>(4)); - f(&s, static_cast<double>(5)); - f(&s, static_cast<unsigned>(6)); - f(&s, static_cast<size_t>(7)); - f(&s, absl::string_view(" OK ")); - StreamableType streamable = {"object"}; - f(&s, streamable); - EXPECT_EQ("Testing: 1234567 OK Streamable:object", s); -} - -// A dummy formatter that wraps each element in parens. Used in some tests -// below. -struct TestingParenFormatter { - template <typename T> - void operator()(std::string* s, const T& t) { - absl::StrAppend(s, "(", t, ")"); - } -}; - -TEST(PairFormatter, FormatterAPI) { - { - // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the - // 'first' and 'second' members. - const auto f = absl::PairFormatter("="); - std::string s; - f(&s, std::make_pair("a", "b")); - f(&s, std::make_pair(1, 2)); - EXPECT_EQ("a=b1=2", s); - } - - { - // Tests using a custom formatter for the 'first' and 'second' members. - auto f = absl::PairFormatter(TestingParenFormatter(), "=", - TestingParenFormatter()); - std::string s; - f(&s, std::make_pair("a", "b")); - f(&s, std::make_pair(1, 2)); - EXPECT_EQ("(a)=(b)(1)=(2)", s); - } -} - -TEST(DereferenceFormatter, FormatterAPI) { - { - // Tests wrapping the default AlphaNumFormatter. - const absl::strings_internal::DereferenceFormatterImpl< - absl::strings_internal::AlphaNumFormatterImpl> - f; - int x = 1, y = 2, z = 3; - std::string s; - f(&s, &x); - f(&s, &y); - f(&s, &z); - EXPECT_EQ("123", s); - } - - { - // Tests wrapping std::string's default formatter. - absl::strings_internal::DereferenceFormatterImpl< - absl::strings_internal::DefaultFormatter<std::string>::Type> - f; - - std::string x = "x"; - std::string y = "y"; - std::string z = "z"; - std::string s; - f(&s, &x); - f(&s, &y); - f(&s, &z); - EXPECT_EQ(s, "xyz"); - } - - { - // Tests wrapping a custom formatter. - auto f = absl::DereferenceFormatter(TestingParenFormatter()); - int x = 1, y = 2, z = 3; - std::string s; - f(&s, &x); - f(&s, &y); - f(&s, &z); - EXPECT_EQ("(1)(2)(3)", s); - } - - { - absl::strings_internal::DereferenceFormatterImpl< - absl::strings_internal::AlphaNumFormatterImpl> - f; - auto x = std::unique_ptr<int>(new int(1)); - auto y = std::unique_ptr<int>(new int(2)); - auto z = std::unique_ptr<int>(new int(3)); - std::string s; - f(&s, x); - f(&s, y); - f(&s, z); - EXPECT_EQ("123", s); - } -} - -// -// Tests the interfaces for the 4 public Join function overloads. The semantics -// of the algorithm is covered in the above APIExamples test. -// -TEST(StrJoin, PublicAPIOverloads) { - std::vector<std::string> v = {"a", "b", "c"}; - - // Iterators + formatter - EXPECT_EQ("a-b-c", - absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter())); - // Range + formatter - EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter())); - // Iterators, no formatter - EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-")); - // Range, no formatter - EXPECT_EQ("a-b-c", absl::StrJoin(v, "-")); -} - -TEST(StrJoin, Array) { - const absl::string_view a[] = {"a", "b", "c"}; - EXPECT_EQ("a-b-c", absl::StrJoin(a, "-")); -} - -TEST(StrJoin, InitializerList) { - { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); } - - { - auto a = {"a", "b", "c"}; - EXPECT_EQ("a-b-c", absl::StrJoin(a, "-")); - } - - { - std::initializer_list<const char*> a = {"a", "b", "c"}; - EXPECT_EQ("a-b-c", absl::StrJoin(a, "-")); - } - - { - std::initializer_list<std::string> a = {"a", "b", "c"}; - EXPECT_EQ("a-b-c", absl::StrJoin(a, "-")); - } - - { - std::initializer_list<absl::string_view> a = {"a", "b", "c"}; - EXPECT_EQ("a-b-c", absl::StrJoin(a, "-")); - } - - { - // Tests initializer_list with a non-default formatter - auto a = {"a", "b", "c"}; - TestingParenFormatter f; - EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f)); - } - - { - // initializer_list of ints - EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-")); - } - - { - // Tests initializer_list of ints with a non-default formatter - auto a = {1, 2, 3}; - TestingParenFormatter f; - EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f)); - } -} - -TEST(StrJoin, Tuple) { - EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-")); - EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-")); - - int x(10); - std::string y("hello"); - double z(3.14); - EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-")); - - // Faster! Faster!! - EXPECT_EQ("10-hello-3.14", - absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-")); - - struct TestFormatter { - char buffer[128]; - void operator()(std::string* out, int v) { - snprintf(buffer, sizeof(buffer), "%#.8x", v); - out->append(buffer); - } - void operator()(std::string* out, double v) { - snprintf(buffer, sizeof(buffer), "%#.0f", v); - out->append(buffer); - } - void operator()(std::string* out, const std::string& v) { - snprintf(buffer, sizeof(buffer), "%.4s", v.c_str()); - out->append(buffer); - } - }; - EXPECT_EQ("0x0000000a-hell-3.", - absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter())); - EXPECT_EQ( - "0x0000000a-hell-3.", - absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter())); - EXPECT_EQ("0x0000000a-hell-3.", - absl::StrJoin(std::make_tuple(&x, &y, &z), "-", - absl::DereferenceFormatter(TestFormatter()))); - EXPECT_EQ("0x0000000a-hell-3.", - absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), - absl::make_unique<std::string>(y), - absl::make_unique<double>(z)), - "-", absl::DereferenceFormatter(TestFormatter()))); - EXPECT_EQ("0x0000000a-hell-3.", - absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z), - "-", absl::DereferenceFormatter(TestFormatter()))); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_replace.cc b/third_party/abseil_cpp/absl/strings/str_replace.cc deleted file mode 100644 index 2bd5fa98218c..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_replace.cc +++ /dev/null @@ -1,82 +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/strings/str_replace.h" - -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -using FixedMapping = - std::initializer_list<std::pair<absl::string_view, absl::string_view>>; - -// Applies the ViableSubstitutions in subs_ptr to the absl::string_view s, and -// stores the result in *result_ptr. Returns the number of substitutions that -// occurred. -int ApplySubstitutions( - absl::string_view s, - std::vector<strings_internal::ViableSubstitution>* subs_ptr, - std::string* result_ptr) { - auto& subs = *subs_ptr; - int substitutions = 0; - size_t pos = 0; - while (!subs.empty()) { - auto& sub = subs.back(); - if (sub.offset >= pos) { - if (pos <= s.size()) { - StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement); - } - pos = sub.offset + sub.old.size(); - substitutions += 1; - } - sub.offset = s.find(sub.old, pos); - if (sub.offset == s.npos) { - subs.pop_back(); - } else { - // Insertion sort to ensure the last ViableSubstitution continues to be - // before all the others. - size_t index = subs.size(); - while (--index && subs[index - 1].OccursBefore(subs[index])) { - std::swap(subs[index], subs[index - 1]); - } - } - } - result_ptr->append(s.data() + pos, s.size() - pos); - return substitutions; -} - -} // namespace strings_internal - -// We can implement this in terms of the generic StrReplaceAll, but -// we must specify the template overload because C++ cannot deduce the type -// of an initializer_list parameter to a function, and also if we don't specify -// the type, we just call ourselves. -// -// Note that we implement them here, rather than in the header, so that they -// aren't inlined. - -std::string StrReplaceAll(absl::string_view s, - strings_internal::FixedMapping replacements) { - return StrReplaceAll<strings_internal::FixedMapping>(s, replacements); -} - -int StrReplaceAll(strings_internal::FixedMapping replacements, - std::string* target) { - return StrReplaceAll<strings_internal::FixedMapping>(replacements, target); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/str_replace.h b/third_party/abseil_cpp/absl/strings/str_replace.h deleted file mode 100644 index 273c7077353e..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_replace.h +++ /dev/null @@ -1,219 +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. -// -// ----------------------------------------------------------------------------- -// File: str_replace.h -// ----------------------------------------------------------------------------- -// -// This file defines `absl::StrReplaceAll()`, a general-purpose string -// replacement function designed for large, arbitrary text substitutions, -// especially on strings which you are receiving from some other system for -// further processing (e.g. processing regular expressions, escaping HTML -// entities, etc.). `StrReplaceAll` is designed to be efficient even when only -// one substitution is being performed, or when substitution is rare. -// -// If the string being modified is known at compile-time, and the substitutions -// vary, `absl::Substitute()` may be a better choice. -// -// Example: -// -// std::string html_escaped = absl::StrReplaceAll(user_input, { -// {"&", "&"}, -// {"<", "<"}, -// {">", ">"}, -// {"\"", """}, -// {"'", "'"}}); -#ifndef ABSL_STRINGS_STR_REPLACE_H_ -#define ABSL_STRINGS_STR_REPLACE_H_ - -#include <string> -#include <utility> -#include <vector> - -#include "absl/base/attributes.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// StrReplaceAll() -// -// Replaces character sequences within a given string with replacements provided -// within an initializer list of key/value pairs. Candidate replacements are -// considered in order as they occur within the string, with earlier matches -// taking precedence, and longer matches taking precedence for candidates -// starting at the same position in the string. Once a substitution is made, the -// replaced text is not considered for any further substitutions. -// -// Example: -// -// std::string s = absl::StrReplaceAll( -// "$who bought $count #Noun. Thanks $who!", -// {{"$count", absl::StrCat(5)}, -// {"$who", "Bob"}, -// {"#Noun", "Apples"}}); -// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -ABSL_MUST_USE_RESULT std::string StrReplaceAll( - absl::string_view s, - std::initializer_list<std::pair<absl::string_view, absl::string_view>> - replacements); - -// Overload of `StrReplaceAll()` to accept a container of key/value replacement -// pairs (typically either an associative map or a `std::vector` of `std::pair` -// elements). A vector of pairs is generally more efficient. -// -// Examples: -// -// std::map<const absl::string_view, const absl::string_view> replacements; -// replacements["$who"] = "Bob"; -// replacements["$count"] = "5"; -// replacements["#Noun"] = "Apples"; -// std::string s = absl::StrReplaceAll( -// "$who bought $count #Noun. Thanks $who!", -// replacements); -// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -// -// // A std::vector of std::pair elements can be more efficient. -// std::vector<std::pair<const absl::string_view, std::string>> replacements; -// replacements.push_back({"&", "&"}); -// replacements.push_back({"<", "<"}); -// replacements.push_back({">", ">"}); -// std::string s = absl::StrReplaceAll("if (ptr < &foo)", -// replacements); -// EXPECT_EQ("if (ptr < &foo)", s); -template <typename StrToStrMapping> -std::string StrReplaceAll(absl::string_view s, - const StrToStrMapping& replacements); - -// Overload of `StrReplaceAll()` to replace character sequences within a given -// output string *in place* with replacements provided within an initializer -// list of key/value pairs, returning the number of substitutions that occurred. -// -// Example: -// -// std::string s = std::string("$who bought $count #Noun. Thanks $who!"); -// int count; -// count = absl::StrReplaceAll({{"$count", absl::StrCat(5)}, -// {"$who", "Bob"}, -// {"#Noun", "Apples"}}, &s); -// EXPECT_EQ(count, 4); -// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -int StrReplaceAll( - std::initializer_list<std::pair<absl::string_view, absl::string_view>> - replacements, - std::string* target); - -// Overload of `StrReplaceAll()` to replace patterns within a given output -// string *in place* with replacements provided within a container of key/value -// pairs. -// -// Example: -// -// std::string s = std::string("if (ptr < &foo)"); -// int count = absl::StrReplaceAll({{"&", "&"}, -// {"<", "<"}, -// {">", ">"}}, &s); -// EXPECT_EQ(count, 2); -// EXPECT_EQ("if (ptr < &foo)", s); -template <typename StrToStrMapping> -int StrReplaceAll(const StrToStrMapping& replacements, std::string* target); - -// Implementation details only, past this point. -namespace strings_internal { - -struct ViableSubstitution { - absl::string_view old; - absl::string_view replacement; - size_t offset; - - ViableSubstitution(absl::string_view old_str, - absl::string_view replacement_str, size_t offset_val) - : old(old_str), replacement(replacement_str), offset(offset_val) {} - - // One substitution occurs "before" another (takes priority) if either - // it has the lowest offset, or it has the same offset but a larger size. - bool OccursBefore(const ViableSubstitution& y) const { - if (offset != y.offset) return offset < y.offset; - return old.size() > y.old.size(); - } -}; - -// Build a vector of ViableSubstitutions based on the given list of -// replacements. subs can be implemented as a priority_queue. However, it turns -// out that most callers have small enough a list of substitutions that the -// overhead of such a queue isn't worth it. -template <typename StrToStrMapping> -std::vector<ViableSubstitution> FindSubstitutions( - absl::string_view s, const StrToStrMapping& replacements) { - std::vector<ViableSubstitution> subs; - subs.reserve(replacements.size()); - - for (const auto& rep : replacements) { - using std::get; - absl::string_view old(get<0>(rep)); - - size_t pos = s.find(old); - if (pos == s.npos) continue; - - // Ignore attempts to replace "". This condition is almost never true, - // but above condition is frequently true. That's why we test for this - // now and not before. - if (old.empty()) continue; - - subs.emplace_back(old, get<1>(rep), pos); - - // Insertion sort to ensure the last ViableSubstitution comes before - // all the others. - size_t index = subs.size(); - while (--index && subs[index - 1].OccursBefore(subs[index])) { - std::swap(subs[index], subs[index - 1]); - } - } - return subs; -} - -int ApplySubstitutions(absl::string_view s, - std::vector<ViableSubstitution>* subs_ptr, - std::string* result_ptr); - -} // namespace strings_internal - -template <typename StrToStrMapping> -std::string StrReplaceAll(absl::string_view s, - const StrToStrMapping& replacements) { - auto subs = strings_internal::FindSubstitutions(s, replacements); - std::string result; - result.reserve(s.size()); - strings_internal::ApplySubstitutions(s, &subs, &result); - return result; -} - -template <typename StrToStrMapping> -int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) { - auto subs = strings_internal::FindSubstitutions(*target, replacements); - if (subs.empty()) return 0; - - std::string result; - result.reserve(target->size()); - int substitutions = - strings_internal::ApplySubstitutions(*target, &subs, &result); - target->swap(result); - return substitutions; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STR_REPLACE_H_ diff --git a/third_party/abseil_cpp/absl/strings/str_replace_benchmark.cc b/third_party/abseil_cpp/absl/strings/str_replace_benchmark.cc deleted file mode 100644 index 01331da29f6e..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_replace_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. - -#include "absl/strings/str_replace.h" - -#include <cstring> -#include <string> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" - -namespace { - -std::string* big_string; -std::string* after_replacing_the; -std::string* after_replacing_many; - -struct Replacement { - const char* needle; - const char* replacement; -} replacements[] = { - {"the", "box"}, // - {"brown", "quick"}, // - {"jumped", "liquored"}, // - {"dozen", "brown"}, // - {"lazy", "pack"}, // - {"liquor", "shakes"}, // -}; - -// Here, we set up a string for use in global-replace benchmarks. -// We started with a million blanks, and then deterministically insert -// 10,000 copies each of two pangrams. The result is a string that is -// 40% blank space and 60% these words. 'the' occurs 18,247 times and -// all the substitutions together occur 49,004 times. -// -// We then create "after_replacing_the" to be a string that is a result of -// replacing "the" with "box" in big_string. -// -// And then we create "after_replacing_many" to be a string that is result -// of preferring several substitutions. -void SetUpStrings() { - if (big_string == nullptr) { - size_t r = 0; - big_string = new std::string(1000 * 1000, ' '); - for (std::string phrase : {"the quick brown fox jumped over the lazy dogs", - "pack my box with the five dozen liquor jugs"}) { - for (int i = 0; i < 10 * 1000; ++i) { - r = r * 237 + 41; // not very random. - memcpy(&(*big_string)[r % (big_string->size() - phrase.size())], - phrase.data(), phrase.size()); - } - } - // big_string->resize(50); - // OK, we've set up the string, now let's set up expectations - first by - // just replacing "the" with "box" - after_replacing_the = new std::string(*big_string); - for (size_t pos = 0; - (pos = after_replacing_the->find("the", pos)) != std::string::npos;) { - memcpy(&(*after_replacing_the)[pos], "box", 3); - } - // And then with all the replacements. - after_replacing_many = new std::string(*big_string); - for (size_t pos = 0;;) { - size_t next_pos = static_cast<size_t>(-1); - const char* needle_string = nullptr; - const char* replacement_string = nullptr; - for (const auto& r : replacements) { - auto needlepos = after_replacing_many->find(r.needle, pos); - if (needlepos != std::string::npos && needlepos < next_pos) { - next_pos = needlepos; - needle_string = r.needle; - replacement_string = r.replacement; - } - } - if (next_pos > after_replacing_many->size()) break; - after_replacing_many->replace(next_pos, strlen(needle_string), - replacement_string); - next_pos += strlen(replacement_string); - pos = next_pos; - } - } -} - -void BM_StrReplaceAllOneReplacement(benchmark::State& state) { - SetUpStrings(); - std::string src = *big_string; - for (auto _ : state) { - std::string dest = absl::StrReplaceAll(src, {{"the", "box"}}); - ABSL_RAW_CHECK(dest == *after_replacing_the, - "not benchmarking intended behavior"); - } -} -BENCHMARK(BM_StrReplaceAllOneReplacement); - -void BM_StrReplaceAll(benchmark::State& state) { - SetUpStrings(); - std::string src = *big_string; - for (auto _ : state) { - std::string dest = absl::StrReplaceAll(src, {{"the", "box"}, - {"brown", "quick"}, - {"jumped", "liquored"}, - {"dozen", "brown"}, - {"lazy", "pack"}, - {"liquor", "shakes"}}); - ABSL_RAW_CHECK(dest == *after_replacing_many, - "not benchmarking intended behavior"); - } -} -BENCHMARK(BM_StrReplaceAll); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_replace_test.cc b/third_party/abseil_cpp/absl/strings/str_replace_test.cc deleted file mode 100644 index 9d8c7f75b57e..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_replace_test.cc +++ /dev/null @@ -1,341 +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/strings/str_replace.h" - -#include <list> -#include <map> -#include <tuple> - -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_split.h" - -TEST(StrReplaceAll, OneReplacement) { - std::string s; - - // Empty string. - s = absl::StrReplaceAll(s, {{"", ""}}); - EXPECT_EQ(s, ""); - s = absl::StrReplaceAll(s, {{"x", ""}}); - EXPECT_EQ(s, ""); - s = absl::StrReplaceAll(s, {{"", "y"}}); - EXPECT_EQ(s, ""); - s = absl::StrReplaceAll(s, {{"x", "y"}}); - EXPECT_EQ(s, ""); - - // Empty substring. - s = absl::StrReplaceAll("abc", {{"", ""}}); - EXPECT_EQ(s, "abc"); - s = absl::StrReplaceAll("abc", {{"", "y"}}); - EXPECT_EQ(s, "abc"); - s = absl::StrReplaceAll("abc", {{"x", ""}}); - EXPECT_EQ(s, "abc"); - - // Substring not found. - s = absl::StrReplaceAll("abc", {{"xyz", "123"}}); - EXPECT_EQ(s, "abc"); - - // Replace entire string. - s = absl::StrReplaceAll("abc", {{"abc", "xyz"}}); - EXPECT_EQ(s, "xyz"); - - // Replace once at the start. - s = absl::StrReplaceAll("abc", {{"a", "x"}}); - EXPECT_EQ(s, "xbc"); - - // Replace once in the middle. - s = absl::StrReplaceAll("abc", {{"b", "x"}}); - EXPECT_EQ(s, "axc"); - - // Replace once at the end. - s = absl::StrReplaceAll("abc", {{"c", "x"}}); - EXPECT_EQ(s, "abx"); - - // Replace multiple times with varying lengths of original/replacement. - s = absl::StrReplaceAll("ababa", {{"a", "xxx"}}); - EXPECT_EQ(s, "xxxbxxxbxxx"); - - s = absl::StrReplaceAll("ababa", {{"b", "xxx"}}); - EXPECT_EQ(s, "axxxaxxxa"); - - s = absl::StrReplaceAll("aaabaaabaaa", {{"aaa", "x"}}); - EXPECT_EQ(s, "xbxbx"); - - s = absl::StrReplaceAll("abbbabbba", {{"bbb", "x"}}); - EXPECT_EQ(s, "axaxa"); - - // Overlapping matches are replaced greedily. - s = absl::StrReplaceAll("aaa", {{"aa", "x"}}); - EXPECT_EQ(s, "xa"); - - // The replacements are not recursive. - s = absl::StrReplaceAll("aaa", {{"aa", "a"}}); - EXPECT_EQ(s, "aa"); -} - -TEST(StrReplaceAll, ManyReplacements) { - std::string s; - - // Empty string. - s = absl::StrReplaceAll("", {{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}); - EXPECT_EQ(s, ""); - - // Empty substring. - s = absl::StrReplaceAll("abc", {{"", ""}, {"", "y"}, {"x", ""}}); - EXPECT_EQ(s, "abc"); - - // Replace entire string, one char at a time - s = absl::StrReplaceAll("abc", {{"a", "x"}, {"b", "y"}, {"c", "z"}}); - EXPECT_EQ(s, "xyz"); - s = absl::StrReplaceAll("zxy", {{"z", "x"}, {"x", "y"}, {"y", "z"}}); - EXPECT_EQ(s, "xyz"); - - // Replace once at the start (longer matches take precedence) - s = absl::StrReplaceAll("abc", {{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}}); - EXPECT_EQ(s, "xyz"); - - // Replace once in the middle. - s = absl::StrReplaceAll( - "Abc!", {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}}); - EXPECT_EQ(s, "Ayz!"); - - // Replace once at the end. - s = absl::StrReplaceAll( - "Abc!", - {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}}); - EXPECT_EQ(s, "Ayz?"); - - // Replace multiple times with varying lengths of original/replacement. - s = absl::StrReplaceAll("ababa", {{"a", "xxx"}, {"b", "XXXX"}}); - EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx"); - - // Overlapping matches are replaced greedily. - s = absl::StrReplaceAll("aaa", {{"aa", "x"}, {"a", "X"}}); - EXPECT_EQ(s, "xX"); - s = absl::StrReplaceAll("aaa", {{"a", "X"}, {"aa", "x"}}); - EXPECT_EQ(s, "xX"); - - // Two well-known sentences - s = absl::StrReplaceAll("the quick brown fox jumped over the lazy dogs", - { - {"brown", "box"}, - {"dogs", "jugs"}, - {"fox", "with"}, - {"jumped", "five"}, - {"over", "dozen"}, - {"quick", "my"}, - {"the", "pack"}, - {"the lazy", "liquor"}, - }); - EXPECT_EQ(s, "pack my box with five dozen liquor jugs"); -} - -TEST(StrReplaceAll, ManyReplacementsInMap) { - std::map<const char *, const char *> replacements; - replacements["$who"] = "Bob"; - replacements["$count"] = "5"; - replacements["#Noun"] = "Apples"; - std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!", - replacements); - EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -} - -TEST(StrReplaceAll, ReplacementsInPlace) { - std::string s = std::string("$who bought $count #Noun. Thanks $who!"); - int count; - count = absl::StrReplaceAll({{"$count", absl::StrCat(5)}, - {"$who", "Bob"}, - {"#Noun", "Apples"}}, &s); - EXPECT_EQ(count, 4); - EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -} - -TEST(StrReplaceAll, ReplacementsInPlaceInMap) { - std::string s = std::string("$who bought $count #Noun. Thanks $who!"); - std::map<absl::string_view, absl::string_view> replacements; - replacements["$who"] = "Bob"; - replacements["$count"] = "5"; - replacements["#Noun"] = "Apples"; - int count; - count = absl::StrReplaceAll(replacements, &s); - EXPECT_EQ(count, 4); - EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s); -} - -struct Cont { - Cont() {} - explicit Cont(absl::string_view src) : data(src) {} - - absl::string_view data; -}; - -template <int index> -absl::string_view get(const Cont& c) { - auto splitter = absl::StrSplit(c.data, ':'); - auto it = splitter.begin(); - for (int i = 0; i < index; ++i) ++it; - - return *it; -} - -TEST(StrReplaceAll, VariableNumber) { - std::string s; - { - std::vector<std::pair<std::string, std::string>> replacements; - - s = "abc"; - EXPECT_EQ(0, absl::StrReplaceAll(replacements, &s)); - EXPECT_EQ("abc", s); - - s = "abc"; - replacements.push_back({"a", "A"}); - EXPECT_EQ(1, absl::StrReplaceAll(replacements, &s)); - EXPECT_EQ("Abc", s); - - s = "abc"; - replacements.push_back({"b", "B"}); - EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s)); - EXPECT_EQ("ABc", s); - - s = "abc"; - replacements.push_back({"d", "D"}); - EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s)); - EXPECT_EQ("ABc", s); - - EXPECT_EQ("ABcABc", absl::StrReplaceAll("abcabc", replacements)); - } - - { - std::map<const char*, const char*> replacements; - replacements["aa"] = "x"; - replacements["a"] = "X"; - s = "aaa"; - EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s)); - EXPECT_EQ("xX", s); - - EXPECT_EQ("xxX", absl::StrReplaceAll("aaaaa", replacements)); - } - - { - std::list<std::pair<absl::string_view, absl::string_view>> replacements = { - {"a", "x"}, {"b", "y"}, {"c", "z"}}; - - std::string s = absl::StrReplaceAll("abc", replacements); - EXPECT_EQ(s, "xyz"); - } - - { - using X = std::tuple<absl::string_view, std::string, int>; - std::vector<X> replacements(3); - replacements[0] = X{"a", "x", 1}; - replacements[1] = X{"b", "y", 0}; - replacements[2] = X{"c", "z", -1}; - - std::string s = absl::StrReplaceAll("abc", replacements); - EXPECT_EQ(s, "xyz"); - } - - { - std::vector<Cont> replacements(3); - replacements[0] = Cont{"a:x"}; - replacements[1] = Cont{"b:y"}; - replacements[2] = Cont{"c:z"}; - - std::string s = absl::StrReplaceAll("abc", replacements); - EXPECT_EQ(s, "xyz"); - } -} - -// Same as above, but using the in-place variant of absl::StrReplaceAll, -// that returns the # of replacements performed. -TEST(StrReplaceAll, Inplace) { - std::string s; - int reps; - - // Empty string. - s = ""; - reps = absl::StrReplaceAll({{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}, &s); - EXPECT_EQ(reps, 0); - EXPECT_EQ(s, ""); - - // Empty substring. - s = "abc"; - reps = absl::StrReplaceAll({{"", ""}, {"", "y"}, {"x", ""}}, &s); - EXPECT_EQ(reps, 0); - EXPECT_EQ(s, "abc"); - - // Replace entire string, one char at a time - s = "abc"; - reps = absl::StrReplaceAll({{"a", "x"}, {"b", "y"}, {"c", "z"}}, &s); - EXPECT_EQ(reps, 3); - EXPECT_EQ(s, "xyz"); - s = "zxy"; - reps = absl::StrReplaceAll({{"z", "x"}, {"x", "y"}, {"y", "z"}}, &s); - EXPECT_EQ(reps, 3); - EXPECT_EQ(s, "xyz"); - - // Replace once at the start (longer matches take precedence) - s = "abc"; - reps = absl::StrReplaceAll({{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}}, &s); - EXPECT_EQ(reps, 1); - EXPECT_EQ(s, "xyz"); - - // Replace once in the middle. - s = "Abc!"; - reps = absl::StrReplaceAll( - {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}}, &s); - EXPECT_EQ(reps, 1); - EXPECT_EQ(s, "Ayz!"); - - // Replace once at the end. - s = "Abc!"; - reps = absl::StrReplaceAll( - {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}}, &s); - EXPECT_EQ(reps, 1); - EXPECT_EQ(s, "Ayz?"); - - // Replace multiple times with varying lengths of original/replacement. - s = "ababa"; - reps = absl::StrReplaceAll({{"a", "xxx"}, {"b", "XXXX"}}, &s); - EXPECT_EQ(reps, 5); - EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx"); - - // Overlapping matches are replaced greedily. - s = "aaa"; - reps = absl::StrReplaceAll({{"aa", "x"}, {"a", "X"}}, &s); - EXPECT_EQ(reps, 2); - EXPECT_EQ(s, "xX"); - s = "aaa"; - reps = absl::StrReplaceAll({{"a", "X"}, {"aa", "x"}}, &s); - EXPECT_EQ(reps, 2); - EXPECT_EQ(s, "xX"); - - // Two well-known sentences - s = "the quick brown fox jumped over the lazy dogs"; - reps = absl::StrReplaceAll( - { - {"brown", "box"}, - {"dogs", "jugs"}, - {"fox", "with"}, - {"jumped", "five"}, - {"over", "dozen"}, - {"quick", "my"}, - {"the", "pack"}, - {"the lazy", "liquor"}, - }, - &s); - EXPECT_EQ(reps, 8); - EXPECT_EQ(s, "pack my box with five dozen liquor jugs"); -} diff --git a/third_party/abseil_cpp/absl/strings/str_split.cc b/third_party/abseil_cpp/absl/strings/str_split.cc deleted file mode 100644 index e08c26b6bbbe..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_split.cc +++ /dev/null @@ -1,139 +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/strings/str_split.h" - -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <cstdlib> -#include <cstring> -#include <iterator> -#include <limits> -#include <memory> - -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/ascii.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -// This GenericFind() template function encapsulates the finding algorithm -// shared between the ByString and ByAnyChar delimiters. The FindPolicy -// template parameter allows each delimiter to customize the actual find -// function to use and the length of the found delimiter. For example, the -// Literal delimiter will ultimately use absl::string_view::find(), and the -// AnyOf delimiter will use absl::string_view::find_first_of(). -template <typename FindPolicy> -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 - // absl::string_view referring to the item at position 1 past pos. - return absl::string_view(text.data() + pos + 1, 0); - } - size_t found_pos = absl::string_view::npos; - absl::string_view found(text.data() + text.size(), - 0); // By default, not found - found_pos = find_policy.Find(text, delimiter, pos); - if (found_pos != absl::string_view::npos) { - found = absl::string_view(text.data() + found_pos, - find_policy.Length(delimiter)); - } - return found; -} - -// Finds using absl::string_view::find(), therefore the length of the found -// delimiter is delimiter.length(). -struct LiteralPolicy { - size_t Find(absl::string_view text, absl::string_view delimiter, size_t pos) { - return text.find(delimiter, pos); - } - size_t Length(absl::string_view delimiter) { return delimiter.length(); } -}; - -// Finds using absl::string_view::find_first_of(), therefore the length of the -// found delimiter is 1. -struct AnyOfPolicy { - size_t Find(absl::string_view text, absl::string_view delimiter, size_t pos) { - return text.find_first_of(delimiter, pos); - } - size_t Length(absl::string_view /* delimiter */) { return 1; } -}; - -} // namespace - -// -// ByString -// - -ByString::ByString(absl::string_view sp) : delimiter_(sp) {} - -absl::string_view ByString::Find(absl::string_view text, size_t pos) const { - if (delimiter_.length() == 1) { - // Much faster to call find on a single character than on an - // absl::string_view. - size_t found_pos = text.find(delimiter_[0], pos); - if (found_pos == absl::string_view::npos) - return absl::string_view(text.data() + text.size(), 0); - return text.substr(found_pos, 1); - } - return GenericFind(text, delimiter_, pos, LiteralPolicy()); -} - -// -// ByChar -// - -absl::string_view ByChar::Find(absl::string_view text, size_t pos) const { - size_t found_pos = text.find(c_, pos); - if (found_pos == absl::string_view::npos) - return absl::string_view(text.data() + text.size(), 0); - return text.substr(found_pos, 1); -} - -// -// ByAnyChar -// - -ByAnyChar::ByAnyChar(absl::string_view sp) : delimiters_(sp) {} - -absl::string_view ByAnyChar::Find(absl::string_view text, size_t pos) const { - return GenericFind(text, delimiters_, pos, AnyOfPolicy()); -} - -// -// ByLength -// -ByLength::ByLength(ptrdiff_t length) : length_(length) { - ABSL_RAW_CHECK(length > 0, ""); -} - -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 - // "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); - - return absl::string_view(substr.data() + length_, 0); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/str_split.h b/third_party/abseil_cpp/absl/strings/str_split.h deleted file mode 100644 index bfbca422a8dc..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_split.h +++ /dev/null @@ -1,548 +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. -// -// ----------------------------------------------------------------------------- -// File: str_split.h -// ----------------------------------------------------------------------------- -// -// This file contains functions for splitting strings. It defines the main -// `StrSplit()` function, several delimiters for determining the boundaries on -// which to split the string, and predicates for filtering delimited results. -// `StrSplit()` adapts the returned collection to the type specified by the -// caller. -// -// Example: -// -// // Splits the given string on commas. Returns the results in a -// // vector of strings. -// std::vector<std::string> v = absl::StrSplit("a,b,c", ','); -// // Can also use "," -// // v[0] == "a", v[1] == "b", v[2] == "c" -// -// See StrSplit() below for more information. -#ifndef ABSL_STRINGS_STR_SPLIT_H_ -#define ABSL_STRINGS_STR_SPLIT_H_ - -#include <algorithm> -#include <cstddef> -#include <map> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/strings/internal/str_split_internal.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -//------------------------------------------------------------------------------ -// Delimiters -//------------------------------------------------------------------------------ -// -// `StrSplit()` uses delimiters to define the boundaries between elements in the -// provided input. Several `Delimiter` types are defined below. If a string -// (`const char*`, `std::string`, or `absl::string_view`) is passed in place of -// an explicit `Delimiter` object, `StrSplit()` treats it the same way as if it -// were passed a `ByString` delimiter. -// -// A `Delimiter` is an object with a `Find()` function that knows how to find -// the first occurrence of itself in a given `absl::string_view`. -// -// The following `Delimiter` types are available for use within `StrSplit()`: -// -// - `ByString` (default for string arguments) -// - `ByChar` (default for a char argument) -// - `ByAnyChar` -// - `ByLength` -// - `MaxSplits` -// -// A Delimiter's `Find()` member function will be passed an input `text` that is -// to be split and a position (`pos`) to begin searching for the next delimiter -// in `text`. The returned absl::string_view should refer to the next occurrence -// (after `pos`) of the represented delimiter; this returned absl::string_view -// represents the next location where the input `text` should be broken. -// -// The returned absl::string_view may be zero-length if the Delimiter does not -// represent a part of the string (e.g., a fixed-length delimiter). If no -// delimiter is found in the input `text`, a zero-length absl::string_view -// referring to `text.end()` should be returned (e.g., -// `text.substr(text.size())`). It is important that the returned -// absl::string_view always be within the bounds of the input `text` given as an -// argument--it must not refer to a string that is physically located outside of -// the given string. -// -// The following example is a simple Delimiter object that is created with a -// single char and will look for that char in the text passed to the `Find()` -// function: -// -// struct SimpleDelimiter { -// const char c_; -// explicit SimpleDelimiter(char c) : c_(c) {} -// absl::string_view Find(absl::string_view text, size_t pos) { -// auto found = text.find(c_, pos); -// if (found == absl::string_view::npos) -// return text.substr(text.size()); -// -// return text.substr(found, 1); -// } -// }; - -// ByString -// -// A sub-string delimiter. If `StrSplit()` is passed a string in place of a -// `Delimiter` object, the string will be implicitly converted into a -// `ByString` delimiter. -// -// Example: -// -// // Because a string literal is converted to an `absl::ByString`, -// // the following two splits are equivalent. -// -// std::vector<std::string> v1 = absl::StrSplit("a, b, c", ", "); -// -// using absl::ByString; -// std::vector<std::string> v2 = absl::StrSplit("a, b, c", -// ByString(", ")); -// // v[0] == "a", v[1] == "b", v[2] == "c" -class ByString { - public: - explicit ByString(absl::string_view sp); - absl::string_view Find(absl::string_view text, size_t pos) const; - - private: - const std::string delimiter_; -}; - -// ByChar -// -// A single character delimiter. `ByChar` is functionally equivalent to a -// 1-char string within a `ByString` delimiter, but slightly more efficient. -// -// Example: -// -// // Because a char literal is converted to a absl::ByChar, -// // the following two splits are equivalent. -// std::vector<std::string> v1 = absl::StrSplit("a,b,c", ','); -// using absl::ByChar; -// std::vector<std::string> v2 = absl::StrSplit("a,b,c", ByChar(',')); -// // v[0] == "a", v[1] == "b", v[2] == "c" -// -// `ByChar` is also the default delimiter if a single character is given -// as the delimiter to `StrSplit()`. For example, the following calls are -// equivalent: -// -// std::vector<std::string> v = absl::StrSplit("a-b", '-'); -// -// using absl::ByChar; -// std::vector<std::string> v = absl::StrSplit("a-b", ByChar('-')); -// -class ByChar { - public: - explicit ByChar(char c) : c_(c) {} - absl::string_view Find(absl::string_view text, size_t pos) const; - - private: - char c_; -}; - -// ByAnyChar -// -// A delimiter that will match any of the given byte-sized characters within -// its provided string. -// -// Note: this delimiter works with single-byte string data, but does not work -// with variable-width encodings, such as UTF-8. -// -// Example: -// -// using absl::ByAnyChar; -// std::vector<std::string> v = absl::StrSplit("a,b=c", ByAnyChar(",=")); -// // v[0] == "a", v[1] == "b", v[2] == "c" -// -// If `ByAnyChar` is given the empty string, it behaves exactly like -// `ByString` and matches each individual character in the input string. -// -class ByAnyChar { - public: - explicit ByAnyChar(absl::string_view sp); - absl::string_view Find(absl::string_view text, size_t pos) const; - - private: - const std::string delimiters_; -}; - -// ByLength -// -// A delimiter for splitting into equal-length strings. The length argument to -// the constructor must be greater than 0. -// -// Note: this delimiter works with single-byte string data, but does not work -// with variable-width encodings, such as UTF-8. -// -// Example: -// -// using absl::ByLength; -// std::vector<std::string> v = absl::StrSplit("123456789", ByLength(3)); - -// // v[0] == "123", v[1] == "456", v[2] == "789" -// -// Note that the string does not have to be a multiple of the fixed split -// length. In such a case, the last substring will be shorter. -// -// using absl::ByLength; -// std::vector<std::string> v = absl::StrSplit("12345", ByLength(2)); -// -// // v[0] == "12", v[1] == "34", v[2] == "5" -class ByLength { - public: - explicit ByLength(ptrdiff_t length); - absl::string_view Find(absl::string_view text, size_t pos) const; - - private: - const ptrdiff_t length_; -}; - -namespace strings_internal { - -// A traits-like metafunction for selecting the default Delimiter object type -// for a particular Delimiter type. The base case simply exposes type Delimiter -// itself as the delimiter's Type. However, there are specializations for -// string-like objects that map them to the ByString delimiter object. -// This allows functions like absl::StrSplit() and absl::MaxSplits() to accept -// string-like objects (e.g., ',') as delimiter arguments but they will be -// treated as if a ByString delimiter was given. -template <typename Delimiter> -struct SelectDelimiter { - using type = Delimiter; -}; - -template <> -struct SelectDelimiter<char> { - using type = ByChar; -}; -template <> -struct SelectDelimiter<char*> { - using type = ByString; -}; -template <> -struct SelectDelimiter<const char*> { - using type = ByString; -}; -template <> -struct SelectDelimiter<absl::string_view> { - using type = ByString; -}; -template <> -struct SelectDelimiter<std::string> { - using type = ByString; -}; - -// Wraps another delimiter and sets a max number of matches for that delimiter. -template <typename Delimiter> -class MaxSplitsImpl { - public: - MaxSplitsImpl(Delimiter delimiter, int limit) - : delimiter_(delimiter), limit_(limit), count_(0) {} - absl::string_view Find(absl::string_view text, size_t pos) { - if (count_++ == limit_) { - return absl::string_view(text.data() + text.size(), - 0); // No more matches. - } - return delimiter_.Find(text, pos); - } - - private: - Delimiter delimiter_; - const int limit_; - int count_; -}; - -} // namespace strings_internal - -// MaxSplits() -// -// A delimiter that limits the number of matches which can occur to the passed -// `limit`. The last element in the returned collection will contain all -// remaining unsplit pieces, which may contain instances of the delimiter. -// The collection will contain at most `limit` + 1 elements. -// Example: -// -// using absl::MaxSplits; -// std::vector<std::string> v = absl::StrSplit("a,b,c", MaxSplits(',', 1)); -// -// // v[0] == "a", v[1] == "b,c" -template <typename Delimiter> -inline strings_internal::MaxSplitsImpl< - typename strings_internal::SelectDelimiter<Delimiter>::type> -MaxSplits(Delimiter delimiter, int limit) { - typedef - typename strings_internal::SelectDelimiter<Delimiter>::type DelimiterType; - return strings_internal::MaxSplitsImpl<DelimiterType>( - DelimiterType(delimiter), limit); -} - -//------------------------------------------------------------------------------ -// Predicates -//------------------------------------------------------------------------------ -// -// Predicates filter the results of a `StrSplit()` by determining whether or not -// a resultant element is included in the result set. A predicate may be passed -// as an optional third argument to the `StrSplit()` function. -// -// Predicates are unary functions (or functors) that take a single -// `absl::string_view` argument and return a bool indicating whether the -// argument should be included (`true`) or excluded (`false`). -// -// Predicates are useful when filtering out empty substrings. By default, empty -// substrings may be returned by `StrSplit()`, which is similar to the way split -// functions work in other programming languages. - -// AllowEmpty() -// -// Always returns `true`, indicating that all strings--including empty -// strings--should be included in the split output. This predicate is not -// strictly needed because this is the default behavior of `StrSplit()`; -// however, it might be useful at some call sites to make the intent explicit. -// -// Example: -// -// std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', AllowEmpty()); -// -// // v[0] == " a ", v[1] == " ", v[2] == "", v[3] = "b", v[4] == "" -struct AllowEmpty { - bool operator()(absl::string_view) const { return true; } -}; - -// SkipEmpty() -// -// Returns `false` if the given `absl::string_view` is empty, indicating that -// `StrSplit()` should omit the empty string. -// -// Example: -// -// std::vector<std::string> v = absl::StrSplit(",a,,b,", ',', SkipEmpty()); -// -// // v[0] == "a", v[1] == "b" -// -// Note: `SkipEmpty()` does not consider a string containing only whitespace -// to be empty. To skip such whitespace as well, use the `SkipWhitespace()` -// predicate. -struct SkipEmpty { - bool operator()(absl::string_view sp) const { return !sp.empty(); } -}; - -// SkipWhitespace() -// -// Returns `false` if the given `absl::string_view` is empty *or* contains only -// whitespace, indicating that `StrSplit()` should omit the string. -// -// Example: -// -// std::vector<std::string> v = absl::StrSplit(" a , ,,b,", -// ',', SkipWhitespace()); -// // v[0] == " a ", v[1] == "b" -// -// // SkipEmpty() would return whitespace elements -// std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipEmpty()); -// // v[0] == " a ", v[1] == " ", v[2] == "b" -struct SkipWhitespace { - bool operator()(absl::string_view sp) const { - sp = absl::StripAsciiWhitespace(sp); - return !sp.empty(); - } -}; - -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() -//------------------------------------------------------------------------------ - -// StrSplit() -// -// Splits a given string based on the provided `Delimiter` object, returning the -// elements within the type specified by the caller. Optionally, you may pass a -// `Predicate` to `StrSplit()` indicating whether to include or exclude the -// resulting element within the final result set. (See the overviews for -// Delimiters and Predicates above.) -// -// Example: -// -// std::vector<std::string> v = absl::StrSplit("a,b,c,d", ','); -// // v[0] == "a", v[1] == "b", v[2] == "c", v[3] == "d" -// -// You can also provide an explicit `Delimiter` object: -// -// Example: -// -// using absl::ByAnyChar; -// std::vector<std::string> v = absl::StrSplit("a,b=c", ByAnyChar(",=")); -// // v[0] == "a", v[1] == "b", v[2] == "c" -// -// See above for more information on delimiters. -// -// By default, empty strings are included in the result set. You can optionally -// include a third `Predicate` argument to apply a test for whether the -// resultant element should be included in the result set: -// -// Example: -// -// std::vector<std::string> v = absl::StrSplit(" a , ,,b,", -// ',', SkipWhitespace()); -// // v[0] == " a ", v[1] == "b" -// -// See above for more information on predicates. -// -//------------------------------------------------------------------------------ -// StrSplit() Return Types -//------------------------------------------------------------------------------ -// -// The `StrSplit()` function adapts the returned collection to the collection -// specified by the caller (e.g. `std::vector` above). The returned collections -// may contain `std::string`, `absl::string_view` (in which case the original -// string being split must ensure that it outlives the collection), or any -// object that can be explicitly created from an `absl::string_view`. This -// behavior works for: -// -// 1) All standard STL containers including `std::vector`, `std::list`, -// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap` -// 2) `std::pair` (which is not actually a container). See below. -// -// Example: -// -// // The results are returned as `absl::string_view` objects. Note that we -// // have to ensure that the input string outlives any results. -// std::vector<absl::string_view> v = absl::StrSplit("a,b,c", ','); -// -// // Stores results in a std::set<std::string>, which also performs -// // de-duplication and orders the elements in ascending order. -// std::set<std::string> a = absl::StrSplit("b,a,c,a,b", ','); -// // v[0] == "a", v[1] == "b", v[2] = "c" -// -// // `StrSplit()` can be used within a range-based for loop, in which case -// // each element will be of type `absl::string_view`. -// std::vector<std::string> v; -// for (const auto sv : absl::StrSplit("a,b,c", ',')) { -// if (sv != "b") v.emplace_back(sv); -// } -// // v[0] == "a", v[1] == "c" -// -// // Stores results in a map. The map implementation assumes that the input -// // is provided as a series of key/value pairs. For example, the 0th element -// // resulting from the split will be stored as a key to the 1st element. If -// // an odd number of elements are resolved, the last element is paired with -// // a default-constructed value (e.g., empty string). -// std::map<std::string, std::string> m = absl::StrSplit("a,b,c", ','); -// // m["a"] == "b", m["c"] == "" // last component value equals "" -// -// Splitting to `std::pair` is an interesting case because it can hold only two -// elements and is not a collection type. When splitting to a `std::pair` the -// first two split strings become the `std::pair` `.first` and `.second` -// members, respectively. The remaining split substrings are discarded. If there -// are less than two split substrings, the empty string is used for the -// corresponding -// `std::pair` member. -// -// Example: -// -// // Stores first two split strings as the members in a std::pair. -// std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ','); -// // p.first == "a", p.second == "b" // "c" is omitted. -// -// The `StrSplit()` function can be used multiple times to perform more -// complicated splitting logic, such as intelligently parsing key-value pairs. -// -// Example: -// -// // The input string "a=b=c,d=e,f=,g" becomes -// // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" } -// std::map<std::string, std::string> m; -// for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) { -// m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1))); -// } -// EXPECT_EQ("b=c", m.find("a")->second); -// EXPECT_EQ("e", m.find("d")->second); -// EXPECT_EQ("", m.find("f")->second); -// EXPECT_EQ("", m.find("g")->second); -// -// WARNING: Due to a legacy bug that is maintained for backward compatibility, -// splitting the following empty string_views produces different results: -// -// absl::StrSplit(absl::string_view(""), '-'); // {""} -// absl::StrSplit(absl::string_view(), '-'); // {}, but should be {""} -// -// 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> -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>( - std::move(text), DelimiterType(d), AllowEmpty()); -} - -template <typename Delimiter, typename Predicate> -strings_internal::Splitter< - typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate, - absl::string_view> -StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d, - Predicate p) { - using DelimiterType = - typename strings_internal::SelectDelimiter<Delimiter>::type; - return strings_internal::Splitter<DelimiterType, Predicate, - absl::string_view>( - text.value(), DelimiterType(d), std::move(p)); -} - -template <typename Delimiter, typename Predicate, typename StringType, - EnableSplitIfString<StringType> = 0> -strings_internal::Splitter< - typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate, - std::string> -StrSplit(StringType&& text, Delimiter d, Predicate p) { - using DelimiterType = - typename strings_internal::SelectDelimiter<Delimiter>::type; - return strings_internal::Splitter<DelimiterType, Predicate, std::string>( - std::move(text), DelimiterType(d), std::move(p)); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STR_SPLIT_H_ diff --git a/third_party/abseil_cpp/absl/strings/str_split_benchmark.cc b/third_party/abseil_cpp/absl/strings/str_split_benchmark.cc deleted file mode 100644 index f38dfcfe5af7..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_split_benchmark.cc +++ /dev/null @@ -1,180 +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/strings/str_split.h" - -#include <iterator> -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/string_view.h" - -namespace { - -std::string MakeTestString(int desired_length) { - static const int kAverageValueLen = 25; - std::string test(desired_length * kAverageValueLen, 'x'); - for (int i = 1; i < test.size(); i += kAverageValueLen) { - test[i] = ';'; - } - return test; -} - -void BM_Split2StringView(benchmark::State& state) { - std::string test = MakeTestString(state.range(0)); - for (auto _ : state) { - std::vector<absl::string_view> result = absl::StrSplit(test, ';'); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20); - -static const absl::string_view kDelimiters = ";:,."; - -std::string MakeMultiDelimiterTestString(int desired_length) { - static const int kAverageValueLen = 25; - std::string test(desired_length * kAverageValueLen, 'x'); - for (int i = 0; i * kAverageValueLen < test.size(); ++i) { - // Cycle through a variety of delimiters. - test[i * kAverageValueLen] = kDelimiters[i % kDelimiters.size()]; - } - return test; -} - -// Measure StrSplit with ByAnyChar with four delimiters to choose from. -void BM_Split2StringViewByAnyChar(benchmark::State& state) { - std::string test = MakeMultiDelimiterTestString(state.range(0)); - for (auto _ : state) { - std::vector<absl::string_view> result = - absl::StrSplit(test, absl::ByAnyChar(kDelimiters)); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_Split2StringViewByAnyChar, 0, 1 << 20); - -void BM_Split2StringViewLifted(benchmark::State& state) { - std::string test = MakeTestString(state.range(0)); - std::vector<absl::string_view> result; - for (auto _ : state) { - result = absl::StrSplit(test, ';'); - } - benchmark::DoNotOptimize(result); -} -BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20); - -void BM_Split2String(benchmark::State& state) { - std::string test = MakeTestString(state.range(0)); - for (auto _ : state) { - std::vector<std::string> result = absl::StrSplit(test, ';'); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20); - -// This benchmark is for comparing Split2 to Split1 (SplitStringUsing). In -// particular, this benchmark uses SkipEmpty() to match SplitStringUsing's -// behavior. -void BM_Split2SplitStringUsing(benchmark::State& state) { - std::string test = MakeTestString(state.range(0)); - for (auto _ : state) { - std::vector<std::string> result = - absl::StrSplit(test, ';', absl::SkipEmpty()); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_Split2SplitStringUsing, 0, 1 << 20); - -void BM_SplitStringToUnorderedSet(benchmark::State& state) { - const int len = state.range(0); - std::string test(len, 'x'); - for (int i = 1; i < len; i += 2) { - test[i] = ';'; - } - for (auto _ : state) { - std::unordered_set<std::string> result = - absl::StrSplit(test, ':', absl::SkipEmpty()); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_SplitStringToUnorderedSet, 0, 1 << 20); - -void BM_SplitStringToUnorderedMap(benchmark::State& state) { - const int len = state.range(0); - std::string test(len, 'x'); - for (int i = 1; i < len; i += 2) { - test[i] = ';'; - } - for (auto _ : state) { - std::unordered_map<std::string, std::string> result = - absl::StrSplit(test, ':', absl::SkipEmpty()); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_SplitStringToUnorderedMap, 0, 1 << 20); - -void BM_SplitStringAllowEmpty(benchmark::State& state) { - const int len = state.range(0); - std::string test(len, 'x'); - for (int i = 1; i < len; i += 2) { - test[i] = ';'; - } - for (auto _ : state) { - std::vector<std::string> result = absl::StrSplit(test, ';'); - benchmark::DoNotOptimize(result); - } -} -BENCHMARK_RANGE(BM_SplitStringAllowEmpty, 0, 1 << 20); - -struct OneCharLiteral { - char operator()() const { return 'X'; } -}; - -struct OneCharStringLiteral { - const char* operator()() const { return "X"; } -}; - -template <typename DelimiterFactory> -void BM_SplitStringWithOneChar(benchmark::State& state) { - const auto delimiter = DelimiterFactory()(); - std::vector<absl::string_view> pieces; - size_t v = 0; - for (auto _ : state) { - pieces = absl::StrSplit("The quick brown fox jumps over the lazy dog", - delimiter); - v += pieces.size(); - } - ABSL_RAW_CHECK(v == state.iterations(), ""); -} -BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharLiteral); -BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharStringLiteral); - -template <typename DelimiterFactory> -void BM_SplitStringWithOneCharNoVector(benchmark::State& state) { - const auto delimiter = DelimiterFactory()(); - size_t v = 0; - for (auto _ : state) { - auto splitter = absl::StrSplit( - "The quick brown fox jumps over the lazy dog", delimiter); - v += std::distance(splitter.begin(), splitter.end()); - } - ABSL_RAW_CHECK(v == state.iterations(), ""); -} -BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral); -BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/str_split_test.cc b/third_party/abseil_cpp/absl/strings/str_split_test.cc deleted file mode 100644 index 7f7c097faee2..000000000000 --- a/third_party/abseil_cpp/absl/strings/str_split_test.cc +++ /dev/null @@ -1,953 +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/strings/str_split.h" - -#include <deque> -#include <initializer_list> -#include <list> -#include <map> -#include <memory> -#include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/dynamic_annotations.h" -#include "absl/base/macros.h" -#include "absl/container/flat_hash_map.h" -#include "absl/container/node_hash_map.h" -#include "absl/strings/numbers.h" - -namespace { - -using ::testing::ElementsAre; -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -TEST(Split, TraitsTest) { - static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value, - ""); - static_assert( - !absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, ""); - static_assert(absl::strings_internal::SplitterIsConvertibleTo< - std::vector<std::string>>::value, - ""); - static_assert( - !absl::strings_internal::SplitterIsConvertibleTo<std::vector<int>>::value, - ""); - static_assert(absl::strings_internal::SplitterIsConvertibleTo< - std::vector<absl::string_view>>::value, - ""); - static_assert(absl::strings_internal::SplitterIsConvertibleTo< - std::map<std::string, std::string>>::value, - ""); - static_assert(absl::strings_internal::SplitterIsConvertibleTo< - std::map<absl::string_view, absl::string_view>>::value, - ""); - static_assert(!absl::strings_internal::SplitterIsConvertibleTo< - std::map<int, std::string>>::value, - ""); - static_assert(!absl::strings_internal::SplitterIsConvertibleTo< - std::map<std::string, int>>::value, - ""); -} - -// This tests the overall split API, which is made up of the absl::StrSplit() -// function and the Delimiter objects in the absl:: namespace. -// This TEST macro is outside of any namespace to require full specification of -// namespaces just like callers will need to use. -TEST(Split, APIExamples) { - { - // Passes string delimiter. Assumes the default of ByString. - std::vector<std::string> v = absl::StrSplit("a,b,c", ","); // NOLINT - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - - // Equivalent to... - using absl::ByString; - v = absl::StrSplit("a,b,c", ByString(",")); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - - // Equivalent to... - EXPECT_THAT(absl::StrSplit("a,b,c", ByString(",")), - ElementsAre("a", "b", "c")); - } - - { - // Same as above, but using a single character as the delimiter. - std::vector<std::string> v = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - - // Equivalent to... - using absl::ByChar; - v = absl::StrSplit("a,b,c", ByChar(',')); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Uses the Literal string "=>" as the delimiter. - const std::vector<std::string> v = absl::StrSplit("a=>b=>c", "=>"); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // The substrings are returned as string_views, eliminating copying. - std::vector<absl::string_view> v = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Leading and trailing empty substrings. - std::vector<std::string> v = absl::StrSplit(",a,b,c,", ','); - EXPECT_THAT(v, ElementsAre("", "a", "b", "c", "")); - } - - { - // Splits on a delimiter that is not found. - std::vector<std::string> v = absl::StrSplit("abc", ','); - EXPECT_THAT(v, ElementsAre("abc")); - } - - { - // Splits the input string into individual characters by using an empty - // string as the delimiter. - std::vector<std::string> v = absl::StrSplit("abc", ""); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Splits 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 - // delimiter. - std::string embedded_nulls("a\0b\0c", 5); - std::string null_delim("\0", 1); - std::vector<std::string> v = absl::StrSplit(embedded_nulls, null_delim); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Stores first two split strings as the members in a std::pair. - std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ','); - EXPECT_EQ("a", p.first); - EXPECT_EQ("b", p.second); - // "c" is omitted because std::pair can hold only two elements. - } - - { - // Results stored in std::set<std::string> - std::set<std::string> v = absl::StrSplit("a,b,c,a,b,c,a,b,c", ','); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Uses a non-const char* delimiter. - char a[] = ","; - char* d = a + 0; - std::vector<std::string> v = absl::StrSplit("a,b,c", d); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Results split using either of , or ; - using absl::ByAnyChar; - std::vector<std::string> v = absl::StrSplit("a,b;c", ByAnyChar(",;")); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Uses the SkipWhitespace predicate. - using absl::SkipWhitespace; - std::vector<std::string> v = - absl::StrSplit(" a , ,,b,", ',', SkipWhitespace()); - EXPECT_THAT(v, ElementsAre(" a ", "b")); - } - - { - // Uses the ByLength delimiter. - using absl::ByLength; - std::vector<std::string> v = absl::StrSplit("abcdefg", ByLength(3)); - EXPECT_THAT(v, ElementsAre("abc", "def", "g")); - } - - { - // Different forms of initialization / conversion. - std::vector<std::string> v1 = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v1, ElementsAre("a", "b", "c")); - std::vector<std::string> v2(absl::StrSplit("a,b,c", ',')); - EXPECT_THAT(v2, ElementsAre("a", "b", "c")); - auto v3 = std::vector<std::string>(absl::StrSplit("a,b,c", ',')); - EXPECT_THAT(v3, ElementsAre("a", "b", "c")); - v3 = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v3, ElementsAre("a", "b", "c")); - } - - { - // Results stored in a std::map. - std::map<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ','); - EXPECT_EQ(2, m.size()); - EXPECT_EQ("3", m["a"]); - EXPECT_EQ("2", m["b"]); - } - - { - // Results stored in a std::multimap. - std::multimap<std::string, std::string> m = - absl::StrSplit("a,1,b,2,a,3", ','); - EXPECT_EQ(3, m.size()); - auto it = m.find("a"); - EXPECT_EQ("1", it->second); - ++it; - EXPECT_EQ("3", it->second); - it = m.find("b"); - EXPECT_EQ("2", it->second); - } - - { - // Demonstrates use in a range-based for loop in C++11. - std::string s = "x,x,x,x,x,x,x"; - for (absl::string_view sp : absl::StrSplit(s, ',')) { - EXPECT_EQ("x", sp); - } - } - - { - // Demonstrates use with a Predicate in a range-based for loop. - using absl::SkipWhitespace; - std::string s = " ,x,,x,,x,x,x,,"; - for (absl::string_view sp : absl::StrSplit(s, ',', SkipWhitespace())) { - EXPECT_EQ("x", sp); - } - } - - { - // Demonstrates a "smart" split to std::map using two separate calls to - // absl::StrSplit. One call to split the records, and another call to split - // the keys and values. This also uses the Limit delimiter so that the - // std::string "a=b=c" will split to "a" -> "b=c". - std::map<std::string, std::string> m; - for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) { - m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1))); - } - EXPECT_EQ("b=c", m.find("a")->second); - EXPECT_EQ("e", m.find("d")->second); - EXPECT_EQ("", m.find("f")->second); - EXPECT_EQ("", m.find("g")->second); - } -} - -// -// Tests for SplitIterator -// - -TEST(SplitIterator, Basics) { - auto splitter = absl::StrSplit("a,b", ','); - auto it = splitter.begin(); - auto end = splitter.end(); - - EXPECT_NE(it, end); - EXPECT_EQ("a", *it); // tests dereference - ++it; // tests preincrement - EXPECT_NE(it, end); - EXPECT_EQ("b", - std::string(it->data(), it->size())); // tests dereference as ptr - it++; // tests postincrement - EXPECT_EQ(it, end); -} - -// Simple Predicate to skip a particular string. -class Skip { - public: - explicit Skip(const std::string& s) : s_(s) {} - bool operator()(absl::string_view sp) { return sp != s_; } - - private: - std::string s_; -}; - -TEST(SplitIterator, Predicate) { - auto splitter = absl::StrSplit("a,b,c", ',', Skip("b")); - auto it = splitter.begin(); - auto end = splitter.end(); - - EXPECT_NE(it, end); - EXPECT_EQ("a", *it); // tests dereference - ++it; // tests preincrement -- "b" should be skipped here. - EXPECT_NE(it, end); - EXPECT_EQ("c", - std::string(it->data(), it->size())); // tests dereference as ptr - it++; // tests postincrement - EXPECT_EQ(it, end); -} - -TEST(SplitIterator, EdgeCases) { - // Expected input and output, assuming a delimiter of ',' - struct { - std::string in; - std::vector<std::string> expect; - } specs[] = { - {"", {""}}, - {"foo", {"foo"}}, - {",", {"", ""}}, - {",foo", {"", "foo"}}, - {"foo,", {"foo", ""}}, - {",foo,", {"", "foo", ""}}, - {"foo,bar", {"foo", "bar"}}, - }; - - for (const auto& spec : specs) { - SCOPED_TRACE(spec.in); - auto splitter = absl::StrSplit(spec.in, ','); - auto it = splitter.begin(); - auto end = splitter.end(); - for (const auto& expected : spec.expect) { - EXPECT_NE(it, end); - EXPECT_EQ(expected, *it++); - } - EXPECT_EQ(it, end); - } -} - -TEST(Splitter, Const) { - const auto splitter = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(splitter, ElementsAre("a", "b", "c")); -} - -TEST(Split, EmptyAndNull) { - // Attention: Splitting a null absl::string_view is different than splitting - // an empty absl::string_view even though both string_views are considered - // equal. This behavior is likely surprising and undesirable. However, to - // maintain backward compatibility, there is a small "hack" in - // str_split_internal.h that preserves this behavior. If that behavior is ever - // changed/fixed, this test will need to be updated. - EXPECT_THAT(absl::StrSplit(absl::string_view(""), '-'), ElementsAre("")); - EXPECT_THAT(absl::StrSplit(absl::string_view(), '-'), ElementsAre()); -} - -TEST(SplitIterator, EqualityAsEndCondition) { - auto splitter = absl::StrSplit("a,b,c", ','); - auto it = splitter.begin(); - auto it2 = it; - - // Increments it2 twice to point to "c" in the input text. - ++it2; - ++it2; - EXPECT_EQ("c", *it2); - - // This test uses a non-end SplitIterator as the terminating condition in a - // for loop. This relies on SplitIterator equality for non-end SplitIterators - // working correctly. At this point it2 points to "c", and we use that as the - // "end" condition in this test. - std::vector<absl::string_view> v; - for (; it != it2; ++it) { - v.push_back(*it); - } - EXPECT_THAT(v, ElementsAre("a", "b")); -} - -// -// Tests for Splitter -// - -TEST(Splitter, RangeIterators) { - auto splitter = absl::StrSplit("a,b,c", ','); - std::vector<absl::string_view> output; - for (const absl::string_view& p : splitter) { - output.push_back(p); - } - EXPECT_THAT(output, ElementsAre("a", "b", "c")); -} - -// Some template functions for use in testing conversion operators -template <typename ContainerType, typename Splitter> -void TestConversionOperator(const Splitter& splitter) { - ContainerType output = splitter; - EXPECT_THAT(output, UnorderedElementsAre("a", "b", "c", "d")); -} - -template <typename MapType, typename Splitter> -void TestMapConversionOperator(const Splitter& splitter) { - MapType m = splitter; - EXPECT_THAT(m, UnorderedElementsAre(Pair("a", "b"), Pair("c", "d"))); -} - -template <typename FirstType, typename SecondType, typename Splitter> -void TestPairConversionOperator(const Splitter& splitter) { - std::pair<FirstType, SecondType> p = splitter; - EXPECT_EQ(p, (std::pair<FirstType, SecondType>("a", "b"))); -} - -TEST(Splitter, ConversionOperator) { - auto splitter = absl::StrSplit("a,b,c,d", ','); - - TestConversionOperator<std::vector<absl::string_view>>(splitter); - TestConversionOperator<std::vector<std::string>>(splitter); - TestConversionOperator<std::list<absl::string_view>>(splitter); - TestConversionOperator<std::list<std::string>>(splitter); - TestConversionOperator<std::deque<absl::string_view>>(splitter); - TestConversionOperator<std::deque<std::string>>(splitter); - TestConversionOperator<std::set<absl::string_view>>(splitter); - TestConversionOperator<std::set<std::string>>(splitter); - TestConversionOperator<std::multiset<absl::string_view>>(splitter); - TestConversionOperator<std::multiset<std::string>>(splitter); - TestConversionOperator<std::unordered_set<std::string>>(splitter); - - // Tests conversion to map-like objects. - - TestMapConversionOperator<std::map<absl::string_view, absl::string_view>>( - splitter); - TestMapConversionOperator<std::map<absl::string_view, std::string>>(splitter); - TestMapConversionOperator<std::map<std::string, absl::string_view>>(splitter); - TestMapConversionOperator<std::map<std::string, std::string>>(splitter); - TestMapConversionOperator< - std::multimap<absl::string_view, absl::string_view>>(splitter); - TestMapConversionOperator<std::multimap<absl::string_view, std::string>>( - splitter); - TestMapConversionOperator<std::multimap<std::string, absl::string_view>>( - splitter); - TestMapConversionOperator<std::multimap<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 - - TestPairConversionOperator<absl::string_view, absl::string_view>(splitter); - TestPairConversionOperator<absl::string_view, std::string>(splitter); - TestPairConversionOperator<std::string, absl::string_view>(splitter); - TestPairConversionOperator<std::string, std::string>(splitter); -} - -// A few additional tests for conversion to std::pair. This conversion is -// different from others because a std::pair always has exactly two elements: -// .first and .second. The split has to work even when the split has -// less-than, equal-to, and more-than 2 strings. -TEST(Splitter, ToPair) { - { - // Empty string - std::pair<std::string, std::string> p = absl::StrSplit("", ','); - EXPECT_EQ("", p.first); - EXPECT_EQ("", p.second); - } - - { - // Only first - std::pair<std::string, std::string> p = absl::StrSplit("a", ','); - EXPECT_EQ("a", p.first); - EXPECT_EQ("", p.second); - } - - { - // Only second - std::pair<std::string, std::string> p = absl::StrSplit(",b", ','); - EXPECT_EQ("", p.first); - EXPECT_EQ("b", p.second); - } - - { - // First and second. - std::pair<std::string, std::string> p = absl::StrSplit("a,b", ','); - EXPECT_EQ("a", p.first); - EXPECT_EQ("b", p.second); - } - - { - // First and second and then more stuff that will be ignored. - std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ','); - EXPECT_EQ("a", p.first); - EXPECT_EQ("b", p.second); - // "c" is omitted. - } -} - -TEST(Splitter, Predicates) { - static const char kTestChars[] = ",a, ,b,"; - using absl::AllowEmpty; - using absl::SkipEmpty; - using absl::SkipWhitespace; - - { - // No predicate. Does not skip empties. - auto splitter = absl::StrSplit(kTestChars, ','); - std::vector<std::string> v = splitter; - EXPECT_THAT(v, ElementsAre("", "a", " ", "b", "")); - } - - { - // Allows empty strings. Same behavior as no predicate at all. - auto splitter = absl::StrSplit(kTestChars, ',', AllowEmpty()); - std::vector<std::string> v_allowempty = splitter; - EXPECT_THAT(v_allowempty, ElementsAre("", "a", " ", "b", "")); - - // Ensures AllowEmpty equals the behavior with no predicate. - auto splitter_nopredicate = absl::StrSplit(kTestChars, ','); - std::vector<std::string> v_nopredicate = splitter_nopredicate; - EXPECT_EQ(v_allowempty, v_nopredicate); - } - - { - // Skips empty strings. - auto splitter = absl::StrSplit(kTestChars, ',', SkipEmpty()); - std::vector<std::string> v = splitter; - EXPECT_THAT(v, ElementsAre("a", " ", "b")); - } - - { - // Skips empty and all-whitespace strings. - auto splitter = absl::StrSplit(kTestChars, ',', SkipWhitespace()); - std::vector<std::string> v = splitter; - EXPECT_THAT(v, ElementsAre("a", "b")); - } -} - -// -// Tests for StrSplit() -// - -TEST(Split, Basics) { - { - // Doesn't really do anything useful because the return value is ignored, - // but it should work. - absl::StrSplit("a,b,c", ','); - } - - { - std::vector<absl::string_view> v = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - std::vector<std::string> v = absl::StrSplit("a,b,c", ','); - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - } - - { - // Ensures that assignment works. This requires a little extra work with - // C++11 because of overloads with initializer_list. - std::vector<std::string> v; - v = absl::StrSplit("a,b,c", ','); - - EXPECT_THAT(v, ElementsAre("a", "b", "c")); - std::map<std::string, std::string> m; - m = absl::StrSplit("a,b,c", ','); - EXPECT_EQ(2, m.size()); - std::unordered_map<std::string, std::string> hm; - hm = absl::StrSplit("a,b,c", ','); - EXPECT_EQ(2, hm.size()); - } -} - -absl::string_view ReturnStringView() { return "Hello World"; } -const char* ReturnConstCharP() { return "Hello World"; } -char* ReturnCharP() { return const_cast<char*>("Hello World"); } - -TEST(Split, AcceptsCertainTemporaries) { - std::vector<std::string> v; - v = absl::StrSplit(ReturnStringView(), ' '); - EXPECT_THAT(v, ElementsAre("Hello", "World")); - v = absl::StrSplit(ReturnConstCharP(), ' '); - EXPECT_THAT(v, ElementsAre("Hello", "World")); - v = absl::StrSplit(ReturnCharP(), ' '); - EXPECT_THAT(v, ElementsAre("Hello", "World")); -} - -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, - // it'll reference freed memory instead of just dead on-stack memory. - const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u"; - EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input)) - << "Input should be larger than fits on the stack."; - - // This happens more often in C++11 as part of a range-based for loop. - auto splitter = absl::StrSplit(std::string(input), ','); - std::string expected = "a"; - for (absl::string_view letter : splitter) { - EXPECT_EQ(expected, letter); - ++expected[0]; - } - EXPECT_EQ("v", expected); - - // This happens more often in C++11 as part of a range-based for loop. - auto std_splitter = absl::StrSplit(std::string(input), ','); - expected = "a"; - for (absl::string_view letter : std_splitter) { - EXPECT_EQ(expected, letter); - ++expected[0]; - } - EXPECT_EQ("v", expected); -} - -template <typename T> -static std::unique_ptr<T> CopyToHeap(const T& value) { - return std::unique_ptr<T>(new T(value)); -} - -TEST(Split, LvalueCaptureIsCopyable) { - std::string input = "a,b"; - auto heap_splitter = CopyToHeap(absl::StrSplit(input, ',')); - auto stack_splitter = *heap_splitter; - heap_splitter.reset(); - std::vector<std::string> result = stack_splitter; - EXPECT_THAT(result, testing::ElementsAre("a", "b")); -} - -TEST(Split, TemporaryCaptureIsCopyable) { - auto heap_splitter = CopyToHeap(absl::StrSplit(std::string("a,b"), ',')); - auto stack_splitter = *heap_splitter; - heap_splitter.reset(); - std::vector<std::string> result = stack_splitter; - EXPECT_THAT(result, testing::ElementsAre("a", "b")); -} - -TEST(Split, SplitterIsCopyableAndMoveable) { - auto a = absl::StrSplit("foo", '-'); - - // Ensures that the following expressions compile. - auto b = a; // Copy construct - auto c = std::move(a); // Move construct - b = c; // Copy assign - c = std::move(b); // Move assign - - EXPECT_THAT(c, ElementsAre("foo")); -} - -TEST(Split, StringDelimiter) { - { - std::vector<absl::string_view> v = absl::StrSplit("a,b", ','); - EXPECT_THAT(v, ElementsAre("a", "b")); - } - - { - std::vector<absl::string_view> v = absl::StrSplit("a,b", std::string(",")); - EXPECT_THAT(v, ElementsAre("a", "b")); - } - - { - std::vector<absl::string_view> v = - absl::StrSplit("a,b", absl::string_view(",")); - EXPECT_THAT(v, ElementsAre("a", "b")); - } -} - -#if !defined(__cpp_char8_t) -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++2a-compat" -#endif -TEST(Split, UTF8) { - // Tests splitting utf8 strings and utf8 delimiters. - std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5"; - { - // A utf8 input 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. - std::string to_split = "a," + utf8_string + ",b"; - std::string unicode_delimiter = "," + utf8_string + ","; - std::vector<absl::string_view> v = - absl::StrSplit(to_split, unicode_delimiter); - EXPECT_THAT(v, ElementsAre("a", "b")); - } - - { - // A utf8 input string and ByAnyChar with ascii chars. - std::vector<absl::string_view> v = - absl::StrSplit(u8"Foo h\u00E4llo th\u4E1Ere", absl::ByAnyChar(" \t")); - EXPECT_THAT(v, ElementsAre("Foo", u8"h\u00E4llo", u8"th\u4E1Ere")); - } -} -#if defined(__clang__) -#pragma clang diagnostic pop -#endif -#endif // !defined(__cpp_char8_t) - -TEST(Split, EmptyStringDelimiter) { - { - std::vector<std::string> v = absl::StrSplit("", ""); - EXPECT_THAT(v, ElementsAre("")); - } - - { - std::vector<std::string> v = absl::StrSplit("a", ""); - EXPECT_THAT(v, ElementsAre("a")); - } - - { - std::vector<std::string> v = absl::StrSplit("ab", ""); - EXPECT_THAT(v, ElementsAre("a", "b")); - } - - { - std::vector<std::string> v = absl::StrSplit("a b", ""); - EXPECT_THAT(v, ElementsAre("a", " ", "b")); - } -} - -TEST(Split, SubstrDelimiter) { - std::vector<absl::string_view> results; - absl::string_view delim("//"); - - results = absl::StrSplit("", delim); - EXPECT_THAT(results, ElementsAre("")); - - results = absl::StrSplit("//", delim); - EXPECT_THAT(results, ElementsAre("", "")); - - results = absl::StrSplit("ab", delim); - EXPECT_THAT(results, ElementsAre("ab")); - - results = absl::StrSplit("ab//", delim); - EXPECT_THAT(results, ElementsAre("ab", "")); - - results = absl::StrSplit("ab/", delim); - EXPECT_THAT(results, ElementsAre("ab/")); - - results = absl::StrSplit("a/b", delim); - EXPECT_THAT(results, ElementsAre("a/b")); - - results = absl::StrSplit("a//b", delim); - EXPECT_THAT(results, ElementsAre("a", "b")); - - results = absl::StrSplit("a///b", delim); - EXPECT_THAT(results, ElementsAre("a", "/b")); - - results = absl::StrSplit("a////b", delim); - EXPECT_THAT(results, ElementsAre("a", "", "b")); -} - -TEST(Split, EmptyResults) { - std::vector<absl::string_view> results; - - results = absl::StrSplit("", '#'); - EXPECT_THAT(results, ElementsAre("")); - - results = absl::StrSplit("#", '#'); - EXPECT_THAT(results, ElementsAre("", "")); - - results = absl::StrSplit("#cd", '#'); - EXPECT_THAT(results, ElementsAre("", "cd")); - - results = absl::StrSplit("ab#cd#", '#'); - EXPECT_THAT(results, ElementsAre("ab", "cd", "")); - - results = absl::StrSplit("ab##cd", '#'); - EXPECT_THAT(results, ElementsAre("ab", "", "cd")); - - results = absl::StrSplit("ab##", '#'); - EXPECT_THAT(results, ElementsAre("ab", "", "")); - - results = absl::StrSplit("ab#ab#", '#'); - EXPECT_THAT(results, ElementsAre("ab", "ab", "")); - - results = absl::StrSplit("aaaa", 'a'); - EXPECT_THAT(results, ElementsAre("", "", "", "", "")); - - results = absl::StrSplit("", '#', absl::SkipEmpty()); - EXPECT_THAT(results, ElementsAre()); -} - -template <typename Delimiter> -static bool IsFoundAtStartingPos(absl::string_view text, Delimiter d, - size_t starting_pos, int expected_pos) { - absl::string_view found = d.Find(text, starting_pos); - return found.data() != text.data() + text.size() && - expected_pos == found.data() - text.data(); -} - -// Helper function for testing Delimiter objects. Returns true if the given -// Delimiter is found in the given string at the given position. This function -// tests two cases: -// 1. The actual text given, staring at position 0 -// 2. The text given with leading padding that should be ignored -template <typename Delimiter> -static bool IsFoundAt(absl::string_view text, Delimiter d, int expected_pos) { - const std::string leading_text = ",x,y,z,"; - return IsFoundAtStartingPos(text, d, 0, expected_pos) && - IsFoundAtStartingPos(leading_text + std::string(text), d, - leading_text.length(), - expected_pos + leading_text.length()); -} - -// -// Tests for ByString -// - -// Tests using any delimiter that represents a single comma. -template <typename Delimiter> -void TestComma(Delimiter d) { - EXPECT_TRUE(IsFoundAt(",", d, 0)); - EXPECT_TRUE(IsFoundAt("a,", d, 1)); - EXPECT_TRUE(IsFoundAt(",b", d, 0)); - EXPECT_TRUE(IsFoundAt("a,b", d, 1)); - EXPECT_TRUE(IsFoundAt("a,b,", d, 1)); - EXPECT_TRUE(IsFoundAt("a,b,c", d, 1)); - EXPECT_FALSE(IsFoundAt("", d, -1)); - EXPECT_FALSE(IsFoundAt(" ", d, -1)); - EXPECT_FALSE(IsFoundAt("a", d, -1)); - EXPECT_FALSE(IsFoundAt("a b c", d, -1)); - EXPECT_FALSE(IsFoundAt("a;b;c", d, -1)); - EXPECT_FALSE(IsFoundAt(";", d, -1)); -} - -TEST(Delimiter, ByString) { - using absl::ByString; - TestComma(ByString(",")); - - // Works as named variable. - ByString comma_string(","); - TestComma(comma_string); - - // The first occurrence of empty string ("") in a string is at position 0. - // There is a test below that demonstrates this for absl::string_view::find(). - // If the ByString delimiter returned position 0 for this, there would - // be an infinite loop in the SplitIterator code. To avoid this, empty 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 - ByString empty(""); - EXPECT_FALSE(IsFoundAt("", empty, 0)); - EXPECT_FALSE(IsFoundAt("a", empty, 0)); - EXPECT_TRUE(IsFoundAt("ab", empty, 1)); - EXPECT_TRUE(IsFoundAt("abc", empty, 1)); -} - -TEST(Split, ByChar) { - using absl::ByChar; - TestComma(ByChar(',')); - - // Works as named variable. - ByChar comma_char(','); - TestComma(comma_char); -} - -// -// Tests for ByAnyChar -// - -TEST(Delimiter, ByAnyChar) { - using absl::ByAnyChar; - ByAnyChar one_delim(","); - // Found - EXPECT_TRUE(IsFoundAt(",", one_delim, 0)); - EXPECT_TRUE(IsFoundAt("a,", one_delim, 1)); - EXPECT_TRUE(IsFoundAt("a,b", one_delim, 1)); - EXPECT_TRUE(IsFoundAt(",b", one_delim, 0)); - // Not found - EXPECT_FALSE(IsFoundAt("", one_delim, -1)); - EXPECT_FALSE(IsFoundAt(" ", one_delim, -1)); - EXPECT_FALSE(IsFoundAt("a", one_delim, -1)); - EXPECT_FALSE(IsFoundAt("a;b;c", one_delim, -1)); - EXPECT_FALSE(IsFoundAt(";", one_delim, -1)); - - ByAnyChar two_delims(",;"); - // Found - EXPECT_TRUE(IsFoundAt(",", two_delims, 0)); - EXPECT_TRUE(IsFoundAt(";", two_delims, 0)); - EXPECT_TRUE(IsFoundAt(",;", two_delims, 0)); - EXPECT_TRUE(IsFoundAt(";,", two_delims, 0)); - EXPECT_TRUE(IsFoundAt(",;b", two_delims, 0)); - EXPECT_TRUE(IsFoundAt(";,b", two_delims, 0)); - EXPECT_TRUE(IsFoundAt("a;,", two_delims, 1)); - EXPECT_TRUE(IsFoundAt("a,;", two_delims, 1)); - EXPECT_TRUE(IsFoundAt("a;,b", two_delims, 1)); - EXPECT_TRUE(IsFoundAt("a,;b", two_delims, 1)); - // Not found - EXPECT_FALSE(IsFoundAt("", two_delims, -1)); - EXPECT_FALSE(IsFoundAt(" ", two_delims, -1)); - EXPECT_FALSE(IsFoundAt("a", two_delims, -1)); - EXPECT_FALSE(IsFoundAt("a=b=c", two_delims, -1)); - 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 - // referring to the item at position 1, not position 0. - ByAnyChar empty(""); - EXPECT_FALSE(IsFoundAt("", empty, 0)); - EXPECT_FALSE(IsFoundAt("a", empty, 0)); - EXPECT_TRUE(IsFoundAt("ab", empty, 1)); - EXPECT_TRUE(IsFoundAt("abc", empty, 1)); -} - -// -// Tests for ByLength -// - -TEST(Delimiter, ByLength) { - using absl::ByLength; - - ByLength four_char_delim(4); - - // Found - EXPECT_TRUE(IsFoundAt("abcde", four_char_delim, 4)); - EXPECT_TRUE(IsFoundAt("abcdefghijklmnopqrstuvwxyz", four_char_delim, 4)); - EXPECT_TRUE(IsFoundAt("a b,c\nd", four_char_delim, 4)); - // Not found - EXPECT_FALSE(IsFoundAt("", four_char_delim, 0)); - EXPECT_FALSE(IsFoundAt("a", four_char_delim, 0)); - EXPECT_FALSE(IsFoundAt("ab", four_char_delim, 0)); - EXPECT_FALSE(IsFoundAt("abc", four_char_delim, 0)); - EXPECT_FALSE(IsFoundAt("abcd", four_char_delim, 0)); -} - -TEST(Split, WorksWithLargeStrings) { - if (sizeof(size_t) > 4) { - 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. - EXPECT_EQ('x', v[0][0]); - EXPECT_EQ('x', v[0][1]); - EXPECT_EQ('x', v[0][3]); - EXPECT_EQ("", v[1]); - } -} - -TEST(SplitInternalTest, TypeTraits) { - EXPECT_FALSE(absl::strings_internal::HasMappedType<int>::value); - EXPECT_TRUE( - (absl::strings_internal::HasMappedType<std::map<int, int>>::value)); - EXPECT_FALSE(absl::strings_internal::HasValueType<int>::value); - EXPECT_TRUE( - (absl::strings_internal::HasValueType<std::map<int, int>>::value)); - EXPECT_FALSE(absl::strings_internal::HasConstIterator<int>::value); - EXPECT_TRUE( - (absl::strings_internal::HasConstIterator<std::map<int, int>>::value)); - EXPECT_FALSE(absl::strings_internal::IsInitializerList<int>::value); - EXPECT_TRUE((absl::strings_internal::IsInitializerList< - std::initializer_list<int>>::value)); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/string_view.cc b/third_party/abseil_cpp/absl/strings/string_view.cc deleted file mode 100644 index c5f5de936deb..000000000000 --- a/third_party/abseil_cpp/absl/strings/string_view.cc +++ /dev/null @@ -1,235 +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/strings/string_view.h" - -#ifndef ABSL_USES_STD_STRING_VIEW - -#include <algorithm> -#include <climits> -#include <cstring> -#include <ostream> - -#include "absl/strings/internal/memutil.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { -void WritePadding(std::ostream& o, size_t pad) { - char fill_buf[32]; - memset(fill_buf, o.fill(), sizeof(fill_buf)); - while (pad) { - size_t n = std::min(pad, sizeof(fill_buf)); - o.write(fill_buf, n); - pad -= n; - } -} - -class LookupTable { - public: - // For each character in wanted, sets the index corresponding - // to the ASCII code of that character. This is used by - // the find_.*_of methods below to tell whether or not a character is in - // the lookup table in constant time. - explicit LookupTable(string_view wanted) { - for (char c : wanted) { - table_[Index(c)] = true; - } - } - bool operator[](char c) const { return table_[Index(c)]; } - - private: - static unsigned char Index(char c) { return static_cast<unsigned char>(c); } - bool table_[UCHAR_MAX + 1] = {}; -}; - -} // namespace - -std::ostream& operator<<(std::ostream& o, string_view piece) { - std::ostream::sentry sentry(o); - if (sentry) { - size_t lpad = 0; - size_t rpad = 0; - if (static_cast<size_t>(o.width()) > piece.size()) { - size_t pad = o.width() - piece.size(); - if ((o.flags() & o.adjustfield) == o.left) { - rpad = pad; - } else { - lpad = pad; - } - } - if (lpad) WritePadding(o, lpad); - o.write(piece.data(), piece.size()); - if (rpad) WritePadding(o, rpad); - o.width(0); - } - return o; -} - -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; - } - const char* result = - strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_); - return result ? result - ptr_ : npos; -} - -string_view::size_type string_view::find(char c, size_type pos) const noexcept { - if (empty() || pos >= length_) { - return npos; - } - const char* result = - static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos)); - return result != nullptr ? result - ptr_ : npos; -} - -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_; - const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); - return result != last ? result - ptr_ : npos; -} - -// 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 { - // Note: memrchr() is not available on Windows. - if (empty()) return npos; - for (size_type i = std::min(pos, length_ - 1);; --i) { - if (ptr_[i] == c) { - return i; - } - if (i == 0) break; - } - return npos; -} - -string_view::size_type string_view::find_first_of(string_view s, - size_type pos) const - noexcept { - if (empty() || s.empty()) { - return npos; - } - // Avoid the cost of LookupTable() for a single-character search. - if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); - LookupTable tbl(s); - for (size_type i = pos; i < length_; ++i) { - if (tbl[ptr_[i]]) { - return i; - } - } - return npos; -} - -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); - LookupTable tbl(s); - for (size_type i = pos; i < length_; ++i) { - if (!tbl[ptr_[i]]) { - return i; - } - } - return npos; -} - -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) { - return pos; - } - } - return npos; -} - -string_view::size_type string_view::find_last_of(string_view s, - size_type pos) const noexcept { - if (empty() || s.empty()) return npos; - // Avoid the cost of LookupTable() for a single-character search. - if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); - LookupTable tbl(s); - for (size_type i = std::min(pos, length_ - 1);; --i) { - if (tbl[ptr_[i]]) { - return i; - } - if (i == 0) break; - } - return npos; -} - -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; - // Avoid the cost of LookupTable() for a single-character search. - if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); - LookupTable tbl(s); - for (;; --i) { - if (!tbl[ptr_[i]]) { - return i; - } - if (i == 0) break; - } - return npos; -} - -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) { - if (ptr_[i] != c) { - return i; - } - if (i == 0) break; - } - return npos; -} - -// MSVC has non-standard behavior that implicitly creates definitions for static -// const members. These implicit definitions conflict with explicit out-of-class -// member definitions that are required by the C++ standard, resulting in -// LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks -// MSVC to choose only one definition for the symbol it decorates. See details -// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx -#ifdef _MSC_VER -#define ABSL_STRING_VIEW_SELECTANY __declspec(selectany) -#else -#define ABSL_STRING_VIEW_SELECTANY -#endif - -ABSL_STRING_VIEW_SELECTANY -constexpr string_view::size_type string_view::npos; -ABSL_STRING_VIEW_SELECTANY -constexpr string_view::size_type string_view::kMaxSize; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_STRING_VIEW diff --git a/third_party/abseil_cpp/absl/strings/string_view.h b/third_party/abseil_cpp/absl/strings/string_view.h deleted file mode 100644 index 5260b5b73f47..000000000000 --- a/third_party/abseil_cpp/absl/strings/string_view.h +++ /dev/null @@ -1,629 +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. -// -// ----------------------------------------------------------------------------- -// File: string_view.h -// ----------------------------------------------------------------------------- -// -// This file contains the definition of the `absl::string_view` class. A -// `string_view` points to a contiguous span of characters, often part or all of -// another `std::string`, double-quoted string literal, character array, or even -// another `string_view`. -// -// This `absl::string_view` abstraction is designed to be a drop-in -// replacement for the C++17 `std::string_view` abstraction. -#ifndef ABSL_STRINGS_STRING_VIEW_H_ -#define ABSL_STRINGS_STRING_VIEW_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstring> -#include <iosfwd> -#include <iterator> -#include <limits> -#include <string> - -#include "absl/base/config.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" - -#ifdef ABSL_USES_STD_STRING_VIEW - -#include <string_view> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using string_view = std::string_view; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_STRING_VIEW - -#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp -#else // ABSL_HAVE_BUILTIN(__builtin_memcmp) -#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp -#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::string_view -// -// A `string_view` provides a lightweight view into the string data provided by -// a `std::string`, double-quoted string literal, character array, or even -// another `string_view`. A `string_view` does *not* own the string to which it -// points, and that data cannot be modified through the view. -// -// You can use `string_view` as a function or method parameter anywhere a -// parameter can receive a double-quoted string literal, `const char*`, -// `std::string`, or another `absl::string_view` argument with no need to copy -// the string data. Systematic use of `string_view` within function arguments -// reduces data copies and `strlen()` calls. -// -// Because of its small size, prefer passing `string_view` by value: -// -// void MyFunction(absl::string_view arg); -// -// If circumstances require, you may also pass one by const reference: -// -// void MyFunction(const absl::string_view& arg); // not preferred -// -// Passing by value generates slightly smaller code for many architectures. -// -// In either case, the source data of the `string_view` must outlive the -// `string_view` itself. -// -// A `string_view` is also suitable for local variables if you know that the -// lifetime of the underlying object is longer than the lifetime of your -// `string_view` variable. However, beware of binding a `string_view` to a -// temporary value: -// -// // BAD use of string_view: lifetime problem -// absl::string_view sv = obj.ReturnAString(); -// -// // GOOD use of string_view: str outlives sv -// std::string str = obj.ReturnAString(); -// absl::string_view sv = str; -// -// Due to lifetime issues, a `string_view` is sometimes a poor choice for a -// return value and usually a poor choice for a data member. If you do use a -// `string_view` this way, it is your responsibility to ensure that the object -// pointed to by the `string_view` outlives the `string_view`. -// -// A `string_view` may represent a whole string or just part of a string. For -// example, when splitting a string, `std::vector<absl::string_view>` is a -// natural data type for the output. -// -// For another example, a Cord is a non-contiguous, potentially very -// long string-like object. The Cord class has an interface that iteratively -// provides string_view objects that point to the successive pieces of a Cord -// object. -// -// When constructed from a source which is NUL-terminated, the `string_view` -// itself will not include the NUL-terminator unless a specific size (including -// the NUL) is passed to the constructor. As a result, common idioms that work -// on NUL-terminated strings do not work on `string_view` objects. If you write -// code that scans a `string_view`, you must check its length rather than test -// for nul, for example. Note, however, that nuls may still be embedded within -// a `string_view` explicitly. -// -// You may create a null `string_view` in two ways: -// -// absl::string_view sv; -// absl::string_view sv(nullptr, 0); -// -// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and -// `sv.empty() == true`. Also, if you create a `string_view` with a non-null -// pointer then `sv.data() != nullptr`. Thus, you can use `string_view()` to -// signal an undefined value that is different from other `string_view` values -// in a similar fashion to how `const char* p1 = nullptr;` is different from -// `const char* p2 = "";`. However, in practice, it is not recommended to rely -// on this behavior. -// -// Be careful not to confuse a null `string_view` with an empty one. A null -// `string_view` is an empty `string_view`, but some empty `string_view`s are -// not null. Prefer checking for emptiness over checking for null. -// -// There are many ways to create an empty string_view: -// -// const char* nullcp = nullptr; -// // string_view.size() will return 0 in all cases. -// absl::string_view(); -// absl::string_view(nullcp, 0); -// absl::string_view(""); -// absl::string_view("", 0); -// absl::string_view("abcdef", 0); -// absl::string_view("abcdef" + 6, 0); -// -// All empty `string_view` objects whether null or not, are equal: -// -// absl::string_view() == absl::string_view("", 0) -// absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0) -class string_view { - public: - using traits_type = std::char_traits<char>; - using value_type = char; - using pointer = char*; - using const_pointer = const char*; - using reference = char&; - using const_reference = const char&; - using const_iterator = const char*; - using iterator = const_iterator; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = std::ptrdiff_t; - - static constexpr size_type npos = static_cast<size_type>(-1); - - // Null `string_view` constructor - constexpr string_view() noexcept : ptr_(nullptr), length_(0) {} - - // Implicit constructors - - template <typename Allocator> - string_view( // NOLINT(runtime/explicit) - 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. - : 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). - constexpr string_view(const char* str) // NOLINT(runtime/explicit) - : 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) - : ptr_(data), length_(CheckLengthInternal(len)) {} - - // NOTE: Harmlessly omitted to work around gdb bug. - // constexpr string_view(const string_view&) noexcept = default; - // string_view& operator=(const string_view&) noexcept = default; - - // Iterators - - // string_view::begin() - // - // Returns an iterator pointing to the first character at the beginning of the - // `string_view`, or `end()` if the `string_view` is empty. - constexpr const_iterator begin() const noexcept { return ptr_; } - - // string_view::end() - // - // Returns an iterator pointing just beyond the last character at the end of - // the `string_view`. This iterator acts as a placeholder; attempting to - // access it results in undefined behavior. - constexpr const_iterator end() const noexcept { return ptr_ + length_; } - - // string_view::cbegin() - // - // Returns a const iterator pointing to the first character at the beginning - // of the `string_view`, or `end()` if the `string_view` is empty. - constexpr const_iterator cbegin() const noexcept { return begin(); } - - // string_view::cend() - // - // Returns a const iterator pointing just beyond the last character at the end - // of the `string_view`. This pointer acts as a placeholder; attempting to - // access its element results in undefined behavior. - constexpr const_iterator cend() const noexcept { return end(); } - - // string_view::rbegin() - // - // Returns a reverse iterator pointing to the last character at the end of the - // `string_view`, or `rend()` if the `string_view` is empty. - const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end()); - } - - // string_view::rend() - // - // Returns a reverse iterator pointing just before the first character at the - // beginning of the `string_view`. This pointer acts as a placeholder; - // attempting to access its element results in undefined behavior. - const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin()); - } - - // string_view::crbegin() - // - // Returns a const reverse iterator pointing to the last character at the end - // of the `string_view`, or `crend()` if the `string_view` is empty. - const_reverse_iterator crbegin() const noexcept { return rbegin(); } - - // string_view::crend() - // - // Returns a const reverse iterator pointing just before the first character - // at the beginning of the `string_view`. This pointer acts as a placeholder; - // attempting to access its element results in undefined behavior. - const_reverse_iterator crend() const noexcept { return rend(); } - - // Capacity Utilities - - // string_view::size() - // - // Returns the number of characters in the `string_view`. - constexpr size_type size() const noexcept { - return length_; - } - - // string_view::length() - // - // Returns the number of characters in the `string_view`. Alias for `size()`. - constexpr size_type length() const noexcept { return size(); } - - // string_view::max_size() - // - // Returns the maximum number of characters the `string_view` can hold. - constexpr size_type max_size() const noexcept { return kMaxSize; } - - // string_view::empty() - // - // Checks if the `string_view` is empty (refers to no characters). - constexpr bool empty() const noexcept { return length_ == 0; } - - // string_view::operator[] - // - // Returns the ith element of the `string_view` using the array operator. - // Note that this operator does not perform any bounds checking. - constexpr const_reference operator[](size_type i) const { - return ABSL_HARDENING_ASSERT(i < size()), ptr_[i]; - } - - // string_view::at() - // - // Returns the ith element of the `string_view`. Bounds checking is performed, - // and an exception of type `std::out_of_range` will be thrown on invalid - // access. - constexpr const_reference at(size_type i) const { - return ABSL_PREDICT_TRUE(i < size()) - ? ptr_[i] - : ((void)base_internal::ThrowStdOutOfRange( - "absl::string_view::at"), - ptr_[i]); - } - - // string_view::front() - // - // Returns the first element of a `string_view`. - constexpr const_reference front() const { - return ABSL_HARDENING_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]; - } - - // string_view::data() - // - // Returns a pointer to the underlying character array (which is of course - // stored elsewhere). Note that `string_view::data()` may contain embedded nul - // characters, but the returned buffer may or may not be NUL-terminated; - // therefore, do not pass `data()` to a routine that expects a NUL-terminated - // string. - constexpr const_pointer data() const noexcept { return ptr_; } - - // Modifiers - - // string_view::remove_prefix() - // - // Removes the first `n` characters from the `string_view`. Note that the - // underlying string is not changed, only the view. - void remove_prefix(size_type n) { - ABSL_HARDENING_ASSERT(n <= length_); - ptr_ += n; - length_ -= n; - } - - // string_view::remove_suffix() - // - // Removes the last `n` characters from the `string_view`. Note that the - // underlying string is not changed, only the view. - void remove_suffix(size_type n) { - ABSL_HARDENING_ASSERT(n <= length_); - length_ -= n; - } - - // string_view::swap() - // - // Swaps this `string_view` with another `string_view`. - void swap(string_view& s) noexcept { - auto t = *this; - *this = s; - s = t; - } - - // Explicit conversion operators - - // Converts to `std::basic_string`. - template <typename A> - explicit operator std::basic_string<char, traits_type, A>() const { - if (!data()) return {}; - return std::basic_string<char, traits_type, A>(data(), size()); - } - - // string_view::copy() - // - // Copies the contents of the `string_view` at offset `pos` and length `n` - // into `buf`. - size_type copy(char* buf, size_type n, size_type pos = 0) const { - if (ABSL_PREDICT_FALSE(pos > length_)) { - base_internal::ThrowStdOutOfRange("absl::string_view::copy"); - } - size_type rlen = (std::min)(length_ - pos, n); - if (rlen > 0) { - const char* start = ptr_ + pos; - traits_type::copy(buf, start, rlen); - } - return rlen; - } - - // string_view::substr() - // - // Returns a "substring" of the `string_view` (at offset `pos` and length - // `n`) as another string_view. This function throws `std::out_of_bounds` if - // `pos > size`. - // Use absl::ClippedSubstr if you need a truncating substr operation. - constexpr string_view substr(size_type pos, size_type n = npos) const { - return ABSL_PREDICT_FALSE(pos > length_) - ? (base_internal::ThrowStdOutOfRange( - "absl::string_view::substr"), - string_view()) - : string_view(ptr_ + pos, Min(n, length_ - pos)); - } - - // string_view::compare() - // - // Performs a lexicographical comparison between the `string_view` and - // another `absl::string_view`, returning -1 if `this` is less than, 0 if - // `this` is equal to, and 1 if `this` is greater than the passed 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 - ? 0 - : ABSL_INTERNAL_STRING_VIEW_MEMCMP( - ptr_, x.ptr_, Min(length_, x.length_))); - } - - // Overload of `string_view::compare()` for comparing a substring of the - // 'string_view` and another `absl::string_view`. - 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`. - 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`. - 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`. - 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`. - int compare(size_type pos1, size_type count1, const char* s, - size_type count2) const { - return substr(pos1, count1).compare(string_view(s, count2)); - } - - // Find Utilities - - // string_view::find() - // - // Finds the first occurrence of the substring `s` within the `string_view`, - // returning the position of the first character's match, or `npos` if no - // match was found. - size_type find(string_view s, size_type pos = 0) const noexcept; - - // Overload of `string_view::find()` for finding the given character `c` - // within the `string_view`. - size_type find(char c, size_type pos = 0) const noexcept; - - // 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; - - // 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; - - // 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; - - // 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 { - return find(c, 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; - - // 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 { - return rfind(c, pos); - } - - // string_view::find_first_not_of() - // - // Finds the first occurrence of any of the characters not in `s` within the - // `string_view`, returning the start position of the first non-match, or - // `npos` if no non-match was found. - size_type find_first_not_of(string_view s, size_type pos = 0) const noexcept; - - // Overload of `string_view::find_first_not_of()` for finding a character - // that is not `c` within the `string_view`. - size_type find_first_not_of(char c, size_type pos = 0) const noexcept; - - // 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; - - // 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; - - private: - 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; - } - - static constexpr size_type StrlenInternal(const char* str) { -#if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__) - // MSVC 2017+ can evaluate this at compile-time. - const char* begin = str; - while (*str != '\0') ++str; - return str - begin; -#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \ - (defined(__GNUC__) && !defined(__clang__)) - // GCC has __builtin_strlen according to - // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but - // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above. - // __builtin_strlen is constexpr. - return __builtin_strlen(str); -#else - return str ? strlen(str) : 0; -#endif - } - - static constexpr size_t Min(size_type length_a, size_type length_b) { - return length_a < length_b ? length_a : length_b; - } - - static constexpr int CompareImpl(size_type length_a, size_type length_b, - int compare_result) { - return compare_result == 0 ? static_cast<int>(length_a > length_b) - - static_cast<int>(length_a < length_b) - : (compare_result < 0 ? -1 : 1); - } - - const char* ptr_; - size_type length_; -}; - -// This large function is defined inline so that in a fairly common case where -// one of the arguments is a literal, the compiler can elide a lot of the -// following comparisons. -constexpr bool operator==(string_view x, string_view y) noexcept { - return x.size() == y.size() && - (x.empty() || - ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0); -} - -constexpr bool operator!=(string_view x, string_view y) noexcept { - return !(x == y); -} - -constexpr bool operator<(string_view x, string_view y) noexcept { - return x.compare(y) < 0; -} - -constexpr bool operator>(string_view x, string_view y) noexcept { - return y < x; -} - -constexpr bool operator<=(string_view x, string_view y) noexcept { - return !(y < x); -} - -constexpr bool operator>=(string_view x, string_view y) noexcept { - return !(x < y); -} - -// IO Insertion Operator -std::ostream& operator<<(std::ostream& o, string_view piece); - -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP - -#endif // ABSL_USES_STD_STRING_VIEW - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ClippedSubstr() -// -// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`. -// Provided because std::string_view::substr throws if `pos > size()` -inline string_view ClippedSubstr(string_view s, size_t pos, - size_t n = string_view::npos) { - pos = (std::min)(pos, static_cast<size_t>(s.size())); - return s.substr(pos, n); -} - -// NullSafeStringView() -// -// Creates an `absl::string_view` from a pointer `p` even if it's null-valued. -// This function should be used where an `absl::string_view` can be created from -// a possibly-null pointer. -constexpr string_view NullSafeStringView(const char* p) { - return p ? string_view(p) : string_view(); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STRING_VIEW_H_ diff --git a/third_party/abseil_cpp/absl/strings/string_view_benchmark.cc b/third_party/abseil_cpp/absl/strings/string_view_benchmark.cc deleted file mode 100644 index 0d74e23e2fc9..000000000000 --- a/third_party/abseil_cpp/absl/strings/string_view_benchmark.cc +++ /dev/null @@ -1,381 +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/strings/string_view.h" - -#include <algorithm> -#include <cstdint> -#include <map> -#include <random> -#include <string> -#include <unordered_set> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/attributes.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" -#include "absl/strings/str_cat.h" - -namespace { - -void BM_StringViewFromString(benchmark::State& state) { - std::string s(state.range(0), 'x'); - std::string* ps = &s; - struct SV { - SV() = default; - explicit SV(const std::string& s) : sv(s) {} - absl::string_view sv; - } sv; - SV* psv = &sv; - benchmark::DoNotOptimize(ps); - benchmark::DoNotOptimize(psv); - for (auto _ : state) { - new (psv) SV(*ps); - benchmark::DoNotOptimize(sv); - } -} -BENCHMARK(BM_StringViewFromString)->Arg(12)->Arg(128); - -// Provide a forcibly out-of-line wrapper for operator== that can be used in -// benchmarks to measure the impact of inlining. -ABSL_ATTRIBUTE_NOINLINE -bool NonInlinedEq(absl::string_view a, absl::string_view b) { return a == b; } - -// We use functions that cannot be inlined to perform the comparison loops so -// that inlining of the operator== can't optimize away *everything*. -ABSL_ATTRIBUTE_NOINLINE -void DoEqualityComparisons(benchmark::State& state, absl::string_view a, - absl::string_view b) { - for (auto _ : state) { - benchmark::DoNotOptimize(a == b); - } -} - -void BM_EqualIdentical(benchmark::State& state) { - std::string x(state.range(0), 'a'); - DoEqualityComparisons(state, x, x); -} -BENCHMARK(BM_EqualIdentical)->DenseRange(0, 3)->Range(4, 1 << 10); - -void BM_EqualSame(benchmark::State& state) { - std::string x(state.range(0), 'a'); - std::string y = x; - DoEqualityComparisons(state, x, y); -} -BENCHMARK(BM_EqualSame) - ->DenseRange(0, 10) - ->Arg(20) - ->Arg(40) - ->Arg(70) - ->Arg(110) - ->Range(160, 4096); - -void BM_EqualDifferent(benchmark::State& state) { - const int len = state.range(0); - std::string x(len, 'a'); - std::string y = x; - if (len > 0) { - y[len - 1] = 'b'; - } - DoEqualityComparisons(state, x, y); -} -BENCHMARK(BM_EqualDifferent)->DenseRange(0, 3)->Range(4, 1 << 10); - -// This benchmark is intended to check that important simplifications can be -// made with absl::string_view comparisons against constant strings. The idea is -// that if constant strings cause redundant components of the comparison, the -// compiler should detect and eliminate them. Here we use 8 different strings, -// each with the same size. Provided our comparison makes the implementation -// inline-able by the compiler, it should fold all of these away into a single -// size check once per loop iteration. -ABSL_ATTRIBUTE_NOINLINE -void DoConstantSizeInlinedEqualityComparisons(benchmark::State& state, - absl::string_view a) { - for (auto _ : state) { - benchmark::DoNotOptimize(a == "aaa"); - benchmark::DoNotOptimize(a == "bbb"); - benchmark::DoNotOptimize(a == "ccc"); - benchmark::DoNotOptimize(a == "ddd"); - benchmark::DoNotOptimize(a == "eee"); - benchmark::DoNotOptimize(a == "fff"); - benchmark::DoNotOptimize(a == "ggg"); - benchmark::DoNotOptimize(a == "hhh"); - } -} -void BM_EqualConstantSizeInlined(benchmark::State& state) { - std::string x(state.range(0), 'a'); - DoConstantSizeInlinedEqualityComparisons(state, x); -} -// We only need to check for size of 3, and <> 3 as this benchmark only has to -// do with size differences. -BENCHMARK(BM_EqualConstantSizeInlined)->DenseRange(2, 4); - -// This benchmark exists purely to give context to the above timings: this is -// what they would look like if the compiler is completely unable to simplify -// between two comparisons when they are comparing against constant strings. -ABSL_ATTRIBUTE_NOINLINE -void DoConstantSizeNonInlinedEqualityComparisons(benchmark::State& state, - absl::string_view a) { - for (auto _ : state) { - // Force these out-of-line to compare with the above function. - benchmark::DoNotOptimize(NonInlinedEq(a, "aaa")); - benchmark::DoNotOptimize(NonInlinedEq(a, "bbb")); - benchmark::DoNotOptimize(NonInlinedEq(a, "ccc")); - benchmark::DoNotOptimize(NonInlinedEq(a, "ddd")); - benchmark::DoNotOptimize(NonInlinedEq(a, "eee")); - benchmark::DoNotOptimize(NonInlinedEq(a, "fff")); - benchmark::DoNotOptimize(NonInlinedEq(a, "ggg")); - benchmark::DoNotOptimize(NonInlinedEq(a, "hhh")); - } -} - -void BM_EqualConstantSizeNonInlined(benchmark::State& state) { - std::string x(state.range(0), 'a'); - DoConstantSizeNonInlinedEqualityComparisons(state, x); -} -// We only need to check for size of 3, and <> 3 as this benchmark only has to -// do with size differences. -BENCHMARK(BM_EqualConstantSizeNonInlined)->DenseRange(2, 4); - -void BM_CompareSame(benchmark::State& state) { - const int len = state.range(0); - std::string x; - for (int i = 0; i < len; i++) { - x += 'a'; - } - std::string y = x; - absl::string_view a = x; - absl::string_view b = y; - - for (auto _ : state) { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - benchmark::DoNotOptimize(a.compare(b)); - } -} -BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10); - -void BM_CompareFirstOneLess(benchmark::State& state) { - const int len = state.range(0); - std::string x(len, 'a'); - std::string y = x; - y.back() = 'b'; - absl::string_view a = x; - absl::string_view b = y; - - for (auto _ : state) { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - benchmark::DoNotOptimize(a.compare(b)); - } -} -BENCHMARK(BM_CompareFirstOneLess)->DenseRange(1, 3)->Range(4, 1 << 10); - -void BM_CompareSecondOneLess(benchmark::State& state) { - const int len = state.range(0); - std::string x(len, 'a'); - std::string y = x; - x.back() = 'b'; - absl::string_view a = x; - absl::string_view b = y; - - for (auto _ : state) { - benchmark::DoNotOptimize(a); - benchmark::DoNotOptimize(b); - benchmark::DoNotOptimize(a.compare(b)); - } -} -BENCHMARK(BM_CompareSecondOneLess)->DenseRange(1, 3)->Range(4, 1 << 10); - -void BM_find_string_view_len_one(benchmark::State& state) { - std::string haystack(state.range(0), '0'); - absl::string_view s(haystack); - for (auto _ : state) { - benchmark::DoNotOptimize(s.find("x")); // not present; length 1 - } -} -BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20); - -void BM_find_string_view_len_two(benchmark::State& state) { - std::string haystack(state.range(0), '0'); - absl::string_view s(haystack); - for (auto _ : state) { - benchmark::DoNotOptimize(s.find("xx")); // not present; length 2 - } -} -BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20); - -void BM_find_one_char(benchmark::State& state) { - std::string haystack(state.range(0), '0'); - absl::string_view s(haystack); - for (auto _ : state) { - benchmark::DoNotOptimize(s.find('x')); // not present - } -} -BENCHMARK(BM_find_one_char)->Range(1, 1 << 20); - -void BM_rfind_one_char(benchmark::State& state) { - std::string haystack(state.range(0), '0'); - absl::string_view s(haystack); - for (auto _ : state) { - benchmark::DoNotOptimize(s.rfind('x')); // not present - } -} -BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20); - -void BM_worst_case_find_first_of(benchmark::State& state, int haystack_len) { - const int needle_len = state.range(0); - std::string needle; - for (int i = 0; i < needle_len; ++i) { - needle += 'a' + i; - } - std::string haystack(haystack_len, '0'); // 1000 zeros. - - absl::string_view s(haystack); - for (auto _ : state) { - benchmark::DoNotOptimize(s.find_first_of(needle)); - } -} - -void BM_find_first_of_short(benchmark::State& state) { - BM_worst_case_find_first_of(state, 10); -} - -void BM_find_first_of_medium(benchmark::State& state) { - BM_worst_case_find_first_of(state, 100); -} - -void BM_find_first_of_long(benchmark::State& state) { - BM_worst_case_find_first_of(state, 1000); -} - -BENCHMARK(BM_find_first_of_short)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); -BENCHMARK(BM_find_first_of_medium)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); -BENCHMARK(BM_find_first_of_long)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); - -struct EasyMap : public std::map<absl::string_view, uint64_t> { - explicit EasyMap(size_t) {} -}; - -// This templated benchmark helper function is intended to stress operator== or -// operator< in a realistic test. It surely isn't entirely realistic, but it's -// a start. The test creates a map of type Map, a template arg, and populates -// it with table_size key/value pairs. Each key has WordsPerKey words. After -// creating the map, a number of lookups are done in random order. Some keys -// are used much more frequently than others in this phase of the test. -template <typename Map, int WordsPerKey> -void StringViewMapBenchmark(benchmark::State& state) { - const int table_size = state.range(0); - const double kFractionOfKeysThatAreHot = 0.2; - const int kNumLookupsOfHotKeys = 20; - const int kNumLookupsOfColdKeys = 1; - const char* words[] = {"the", "quick", "brown", "fox", "jumped", - "over", "the", "lazy", "dog", "and", - "found", "a", "large", "mushroom", "and", - "a", "couple", "crickets", "eating", "pie"}; - // Create some keys that consist of words in random order. - std::random_device r; - std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); - std::mt19937 rng(seed); - std::vector<std::string> keys(table_size); - std::vector<int> all_indices; - const int kBlockSize = 1 << 12; - std::unordered_set<std::string> t(kBlockSize); - std::uniform_int_distribution<int> uniform(0, ABSL_ARRAYSIZE(words) - 1); - for (int i = 0; i < table_size; i++) { - all_indices.push_back(i); - do { - keys[i].clear(); - for (int j = 0; j < WordsPerKey; j++) { - absl::StrAppend(&keys[i], j > 0 ? " " : "", words[uniform(rng)]); - } - } while (!t.insert(keys[i]).second); - } - - // Create a list of strings to lookup: a permutation of the array of - // keys we just created, with repeats. "Hot" keys get repeated more. - std::shuffle(all_indices.begin(), all_indices.end(), rng); - const int num_hot = table_size * kFractionOfKeysThatAreHot; - const int num_cold = table_size - num_hot; - std::vector<int> hot_indices(all_indices.begin(), - all_indices.begin() + num_hot); - std::vector<int> indices; - for (int i = 0; i < kNumLookupsOfColdKeys; i++) { - indices.insert(indices.end(), all_indices.begin(), all_indices.end()); - } - for (int i = 0; i < kNumLookupsOfHotKeys - kNumLookupsOfColdKeys; i++) { - indices.insert(indices.end(), hot_indices.begin(), hot_indices.end()); - } - std::shuffle(indices.begin(), indices.end(), rng); - ABSL_RAW_CHECK( - num_cold * kNumLookupsOfColdKeys + num_hot * kNumLookupsOfHotKeys == - indices.size(), - ""); - // After constructing the array we probe it with absl::string_views built from - // test_strings. This means operator== won't see equal pointers, so - // it'll have to check for equal lengths and equal characters. - std::vector<std::string> test_strings(indices.size()); - for (int i = 0; i < indices.size(); i++) { - test_strings[i] = keys[indices[i]]; - } - - // Run the benchmark. It includes map construction but is mostly - // map lookups. - for (auto _ : state) { - Map h(table_size); - for (int i = 0; i < table_size; i++) { - h[keys[i]] = i * 2; - } - ABSL_RAW_CHECK(h.size() == table_size, ""); - uint64_t sum = 0; - for (int i = 0; i < indices.size(); i++) { - sum += h[test_strings[i]]; - } - benchmark::DoNotOptimize(sum); - } -} - -void BM_StdMap_4(benchmark::State& state) { - StringViewMapBenchmark<EasyMap, 4>(state); -} -BENCHMARK(BM_StdMap_4)->Range(1 << 10, 1 << 16); - -void BM_StdMap_8(benchmark::State& state) { - StringViewMapBenchmark<EasyMap, 8>(state); -} -BENCHMARK(BM_StdMap_8)->Range(1 << 10, 1 << 16); - -void BM_CopyToStringNative(benchmark::State& state) { - std::string src(state.range(0), 'x'); - absl::string_view sv(src); - std::string dst; - for (auto _ : state) { - dst.assign(sv.begin(), sv.end()); - } -} -BENCHMARK(BM_CopyToStringNative)->Range(1 << 3, 1 << 12); - -void BM_AppendToStringNative(benchmark::State& state) { - std::string src(state.range(0), 'x'); - absl::string_view sv(src); - std::string dst; - for (auto _ : state) { - dst.clear(); - dst.insert(dst.end(), sv.begin(), sv.end()); - } -} -BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12); - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/string_view_test.cc b/third_party/abseil_cpp/absl/strings/string_view_test.cc deleted file mode 100644 index dcebb1500100..000000000000 --- a/third_party/abseil_cpp/absl/strings/string_view_test.cc +++ /dev/null @@ -1,1264 +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/strings/string_view.h" - -#include <stdlib.h> -#include <iomanip> -#include <iterator> -#include <limits> -#include <map> -#include <sstream> -#include <stdexcept> -#include <string> -#include <type_traits> -#include <utility> - -#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. -// Android assert messages only go to system log, so death tests cannot inspect -// the message for matching. -#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - EXPECT_DEATH_IF_SUPPORTED(statement, ".*") -#else -#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - EXPECT_DEATH_IF_SUPPORTED(statement, regex) -#endif - -namespace { - -// A minimal allocator that uses malloc(). -template <typename T> -struct Mallocator { - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - size_type max_size() const { - return size_t(std::numeric_limits<size_type>::max()) / sizeof(value_type); - } - template <typename U> - struct rebind { - typedef Mallocator<U> other; - }; - Mallocator() = default; - template <class U> - Mallocator(const Mallocator<U>&) {} // NOLINT(runtime/explicit) - - T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); } - void deallocate(T* p, size_t) { std::free(p); } -}; -template <typename T, typename U> -bool operator==(const Mallocator<T>&, const Mallocator<U>&) { - return true; -} -template <typename T, typename U> -bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { - return false; -} - -TEST(StringViewTest, Ctor) { - { - // Null. - absl::string_view s10; - EXPECT_TRUE(s10.data() == nullptr); - EXPECT_EQ(0, s10.length()); - } - - { - // const char* without length. - const char* hello = "hello"; - absl::string_view s20(hello); - EXPECT_TRUE(s20.data() == hello); - EXPECT_EQ(5, s20.length()); - - // const char* with length. - absl::string_view s21(hello, 4); - EXPECT_TRUE(s21.data() == hello); - EXPECT_EQ(4, s21.length()); - - // Not recommended, but valid C++ - absl::string_view s22(hello, 6); - EXPECT_TRUE(s22.data() == hello); - EXPECT_EQ(6, s22.length()); - } - - { - // std::string. - std::string hola = "hola"; - absl::string_view s30(hola); - EXPECT_TRUE(s30.data() == hola.data()); - EXPECT_EQ(4, s30.length()); - - // std::string with embedded '\0'. - hola.push_back('\0'); - hola.append("h2"); - hola.push_back('\0'); - absl::string_view s31(hola); - EXPECT_TRUE(s31.data() == hola.data()); - EXPECT_EQ(8, s31.length()); - } - - { - using mstring = - std::basic_string<char, std::char_traits<char>, Mallocator<char>>; - mstring str1("BUNGIE-JUMPING!"); - const mstring str2("SLEEPING!"); - - absl::string_view s1(str1); - s1.remove_prefix(strlen("BUNGIE-JUM")); - - absl::string_view s2(str2); - s2.remove_prefix(strlen("SLEE")); - - EXPECT_EQ(s1, s2); - EXPECT_EQ(s1, "PING!"); - } - - // TODO(mec): absl::string_view(const absl::string_view&); -} - -TEST(StringViewTest, Swap) { - absl::string_view a("a"); - absl::string_view b("bbb"); - EXPECT_TRUE(noexcept(a.swap(b))); - a.swap(b); - EXPECT_EQ(a, "bbb"); - EXPECT_EQ(b, "a"); - a.swap(b); - EXPECT_EQ(a, "a"); - EXPECT_EQ(b, "bbb"); -} - -TEST(StringViewTest, STLComparator) { - std::string s1("foo"); - std::string s2("bar"); - std::string s3("baz"); - - absl::string_view p1(s1); - absl::string_view p2(s2); - absl::string_view p3(s3); - - typedef std::map<absl::string_view, int> TestMap; - TestMap map; - - map.insert(std::make_pair(p1, 0)); - map.insert(std::make_pair(p2, 1)); - map.insert(std::make_pair(p3, 2)); - EXPECT_EQ(map.size(), 3); - - TestMap::const_iterator iter = map.begin(); - EXPECT_EQ(iter->second, 1); - ++iter; - EXPECT_EQ(iter->second, 2); - ++iter; - EXPECT_EQ(iter->second, 0); - ++iter; - EXPECT_TRUE(iter == map.end()); - - TestMap::iterator new_iter = map.find("zot"); - EXPECT_TRUE(new_iter == map.end()); - - new_iter = map.find("bar"); - EXPECT_TRUE(new_iter != map.end()); - - map.erase(new_iter); - EXPECT_EQ(map.size(), 2); - - iter = map.begin(); - EXPECT_EQ(iter->second, 2); - ++iter; - EXPECT_EQ(iter->second, 0); - ++iter; - EXPECT_TRUE(iter == map.end()); -} - -#define COMPARE(result, op, x, y) \ - EXPECT_EQ(result, absl::string_view((x)) op absl::string_view((y))); \ - EXPECT_EQ(result, absl::string_view((x)).compare(absl::string_view((y))) op 0) - -TEST(StringViewTest, ComparisonOperators) { - COMPARE(true, ==, "", ""); - COMPARE(true, ==, "", absl::string_view()); - COMPARE(true, ==, absl::string_view(), ""); - COMPARE(true, ==, "a", "a"); - COMPARE(true, ==, "aa", "aa"); - COMPARE(false, ==, "a", ""); - COMPARE(false, ==, "", "a"); - COMPARE(false, ==, "a", "b"); - COMPARE(false, ==, "a", "aa"); - COMPARE(false, ==, "aa", "a"); - - COMPARE(false, !=, "", ""); - COMPARE(false, !=, "a", "a"); - COMPARE(false, !=, "aa", "aa"); - COMPARE(true, !=, "a", ""); - COMPARE(true, !=, "", "a"); - COMPARE(true, !=, "a", "b"); - COMPARE(true, !=, "a", "aa"); - COMPARE(true, !=, "aa", "a"); - - COMPARE(true, <, "a", "b"); - COMPARE(true, <, "a", "aa"); - COMPARE(true, <, "aa", "b"); - COMPARE(true, <, "aa", "bb"); - COMPARE(false, <, "a", "a"); - COMPARE(false, <, "b", "a"); - COMPARE(false, <, "aa", "a"); - COMPARE(false, <, "b", "aa"); - COMPARE(false, <, "bb", "aa"); - - COMPARE(true, <=, "a", "a"); - COMPARE(true, <=, "a", "b"); - COMPARE(true, <=, "a", "aa"); - COMPARE(true, <=, "aa", "b"); - COMPARE(true, <=, "aa", "bb"); - COMPARE(false, <=, "b", "a"); - COMPARE(false, <=, "aa", "a"); - COMPARE(false, <=, "b", "aa"); - COMPARE(false, <=, "bb", "aa"); - - COMPARE(false, >=, "a", "b"); - COMPARE(false, >=, "a", "aa"); - COMPARE(false, >=, "aa", "b"); - COMPARE(false, >=, "aa", "bb"); - COMPARE(true, >=, "a", "a"); - COMPARE(true, >=, "b", "a"); - COMPARE(true, >=, "aa", "a"); - COMPARE(true, >=, "b", "aa"); - COMPARE(true, >=, "bb", "aa"); - - COMPARE(false, >, "a", "a"); - COMPARE(false, >, "a", "b"); - COMPARE(false, >, "a", "aa"); - COMPARE(false, >, "aa", "b"); - COMPARE(false, >, "aa", "bb"); - COMPARE(true, >, "b", "a"); - COMPARE(true, >, "aa", "a"); - COMPARE(true, >, "b", "aa"); - COMPARE(true, >, "bb", "aa"); -} - -TEST(StringViewTest, ComparisonOperatorsByCharacterPosition) { - std::string x; - for (int i = 0; i < 256; i++) { - x += 'a'; - std::string y = x; - COMPARE(true, ==, x, y); - for (int j = 0; j < i; j++) { - std::string z = x; - z[j] = 'b'; // Differs in position 'j' - COMPARE(false, ==, x, z); - COMPARE(true, <, x, z); - COMPARE(true, >, z, x); - if (j + 1 < i) { - z[j + 1] = 'A'; // Differs in position 'j+1' as well - COMPARE(false, ==, x, z); - COMPARE(true, <, x, z); - COMPARE(true, >, z, x); - z[j + 1] = 'z'; // Differs in position 'j+1' as well - COMPARE(false, ==, x, z); - COMPARE(true, <, x, z); - COMPARE(true, >, z, x); - } - } - } -} -#undef COMPARE - -// Sadly, our users often confuse std::string::npos with -// absl::string_view::npos; So much so that we test here that they are the same. -// They need to both be unsigned, and both be the maximum-valued integer of -// their type. - -template <typename T> -struct is_type { - template <typename U> - static bool same(U) { - return false; - } - static bool same(T) { return true; } -}; - -TEST(StringViewTest, NposMatchesStdStringView) { - EXPECT_EQ(absl::string_view::npos, std::string::npos); - - EXPECT_TRUE(is_type<size_t>::same(absl::string_view::npos)); - EXPECT_FALSE(is_type<size_t>::same("")); - - // Make sure absl::string_view::npos continues to be a header constant. - char test[absl::string_view::npos & 1] = {0}; - EXPECT_EQ(0, test[0]); -} - -TEST(StringViewTest, STL1) { - const absl::string_view a("abcdefghijklmnopqrstuvwxyz"); - const absl::string_view b("abc"); - const absl::string_view c("xyz"); - const absl::string_view d("foobar"); - const absl::string_view e; - std::string temp("123"); - temp += '\0'; - temp += "456"; - const absl::string_view f(temp); - - EXPECT_EQ(a[6], 'g'); - EXPECT_EQ(b[0], 'a'); - EXPECT_EQ(c[2], 'z'); - EXPECT_EQ(f[3], '\0'); - EXPECT_EQ(f[5], '5'); - - EXPECT_EQ(*d.data(), 'f'); - EXPECT_EQ(d.data()[5], 'r'); - EXPECT_TRUE(e.data() == nullptr); - - EXPECT_EQ(*a.begin(), 'a'); - EXPECT_EQ(*(b.begin() + 2), 'c'); - EXPECT_EQ(*(c.end() - 1), 'z'); - - EXPECT_EQ(*a.rbegin(), 'z'); - EXPECT_EQ(*(b.rbegin() + 2), 'a'); - EXPECT_EQ(*(c.rend() - 1), 'x'); - EXPECT_TRUE(a.rbegin() + 26 == a.rend()); - - EXPECT_EQ(a.size(), 26); - EXPECT_EQ(b.size(), 3); - EXPECT_EQ(c.size(), 3); - EXPECT_EQ(d.size(), 6); - EXPECT_EQ(e.size(), 0); - EXPECT_EQ(f.size(), 7); - - EXPECT_TRUE(!d.empty()); - EXPECT_TRUE(d.begin() != d.end()); - EXPECT_TRUE(d.begin() + 6 == d.end()); - - EXPECT_TRUE(e.empty()); - EXPECT_TRUE(e.begin() == e.end()); - - char buf[4] = { '%', '%', '%', '%' }; - EXPECT_EQ(a.copy(buf, 4), 4); - EXPECT_EQ(buf[0], a[0]); - EXPECT_EQ(buf[1], a[1]); - EXPECT_EQ(buf[2], a[2]); - EXPECT_EQ(buf[3], a[3]); - EXPECT_EQ(a.copy(buf, 3, 7), 3); - EXPECT_EQ(buf[0], a[7]); - EXPECT_EQ(buf[1], a[8]); - EXPECT_EQ(buf[2], a[9]); - EXPECT_EQ(buf[3], a[3]); - EXPECT_EQ(c.copy(buf, 99), 3); - EXPECT_EQ(buf[0], c[0]); - EXPECT_EQ(buf[1], c[1]); - EXPECT_EQ(buf[2], c[2]); - EXPECT_EQ(buf[3], a[3]); -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(a.copy(buf, 1, 27), std::out_of_range); -#else - ABSL_EXPECT_DEATH_IF_SUPPORTED(a.copy(buf, 1, 27), "absl::string_view::copy"); -#endif -} - -// Separated from STL1() because some compilers produce an overly -// large stack frame for the combined function. -TEST(StringViewTest, STL2) { - const absl::string_view a("abcdefghijklmnopqrstuvwxyz"); - const absl::string_view b("abc"); - const absl::string_view c("xyz"); - absl::string_view d("foobar"); - const absl::string_view e; - const absl::string_view f( - "123" - "\0" - "456", - 7); - - d = absl::string_view(); - EXPECT_EQ(d.size(), 0); - EXPECT_TRUE(d.empty()); - EXPECT_TRUE(d.data() == nullptr); - EXPECT_TRUE(d.begin() == d.end()); - - EXPECT_EQ(a.find(b), 0); - EXPECT_EQ(a.find(b, 1), absl::string_view::npos); - EXPECT_EQ(a.find(c), 23); - EXPECT_EQ(a.find(c, 9), 23); - EXPECT_EQ(a.find(c, absl::string_view::npos), absl::string_view::npos); - EXPECT_EQ(b.find(c), absl::string_view::npos); - EXPECT_EQ(b.find(c, absl::string_view::npos), absl::string_view::npos); - EXPECT_EQ(a.find(d), 0); - EXPECT_EQ(a.find(e), 0); - EXPECT_EQ(a.find(d, 12), 12); - 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 - 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); - EXPECT_EQ(e.find(b, 7), absl::string_view::npos); - - size_t empty_search_pos = std::string().find(std::string()); - EXPECT_EQ(d.find(d), empty_search_pos); - EXPECT_EQ(d.find(e), empty_search_pos); - EXPECT_EQ(e.find(d), empty_search_pos); - EXPECT_EQ(e.find(e), empty_search_pos); - EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4)); - EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4)); - EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4)); - EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4)); - - EXPECT_EQ(a.find('a'), 0); - EXPECT_EQ(a.find('c'), 2); - EXPECT_EQ(a.find('z'), 25); - EXPECT_EQ(a.find('$'), absl::string_view::npos); - EXPECT_EQ(a.find('\0'), absl::string_view::npos); - EXPECT_EQ(f.find('\0'), 3); - EXPECT_EQ(f.find('3'), 2); - EXPECT_EQ(f.find('5'), 5); - EXPECT_EQ(g.find('o'), 4); - 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 - 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); - EXPECT_EQ(e.find('\0', 7), absl::string_view::npos); - EXPECT_EQ(d.find('x'), absl::string_view::npos); - EXPECT_EQ(e.find('x'), absl::string_view::npos); - EXPECT_EQ(d.find('x', 4), absl::string_view::npos); - EXPECT_EQ(e.find('x', 7), absl::string_view::npos); - - EXPECT_EQ(a.rfind(b), 0); - EXPECT_EQ(a.rfind(b, 1), 0); - EXPECT_EQ(a.rfind(c), 23); - EXPECT_EQ(a.rfind(c, 22), absl::string_view::npos); - EXPECT_EQ(a.rfind(c, 1), absl::string_view::npos); - EXPECT_EQ(a.rfind(c, 0), absl::string_view::npos); - EXPECT_EQ(b.rfind(c), absl::string_view::npos); - EXPECT_EQ(b.rfind(c, 0), absl::string_view::npos); - EXPECT_EQ(a.rfind(d), std::string(a).rfind(std::string())); - EXPECT_EQ(a.rfind(e), std::string(a).rfind(std::string())); - EXPECT_EQ(a.rfind(d, 12), 12); - EXPECT_EQ(a.rfind(e, 17), 17); - EXPECT_EQ(a.rfind(g), absl::string_view::npos); - EXPECT_EQ(d.rfind(b), absl::string_view::npos); - 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 - 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())); - EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string())); - EXPECT_EQ(d.rfind(d), std::string().rfind(std::string())); - EXPECT_EQ(e.rfind(d), std::string().rfind(std::string())); - EXPECT_EQ(d.rfind(e), std::string().rfind(std::string())); - EXPECT_EQ(e.rfind(e), std::string().rfind(std::string())); - - EXPECT_EQ(g.rfind('o'), 8); - EXPECT_EQ(g.rfind('q'), absl::string_view::npos); - EXPECT_EQ(g.rfind('o', 8), 8); - EXPECT_EQ(g.rfind('o', 7), 4); - EXPECT_EQ(g.rfind('o', 3), absl::string_view::npos); - EXPECT_EQ(f.rfind('\0'), 3); - EXPECT_EQ(f.rfind('\0', 12), 3); - EXPECT_EQ(f.rfind('3'), 2); - EXPECT_EQ(f.rfind('5'), 5); - // empty string nonsense - EXPECT_EQ(d.rfind('o'), absl::string_view::npos); - EXPECT_EQ(e.rfind('o'), absl::string_view::npos); - EXPECT_EQ(d.rfind('o', 4), absl::string_view::npos); - EXPECT_EQ(e.rfind('o', 7), absl::string_view::npos); -} - -// Continued from STL2 -TEST(StringViewTest, STL2FindFirst) { - const absl::string_view a("abcdefghijklmnopqrstuvwxyz"); - const absl::string_view b("abc"); - const absl::string_view c("xyz"); - absl::string_view d("foobar"); - const absl::string_view e; - const absl::string_view f( - "123" - "\0" - "456", - 7); - absl::string_view g("xx not found bb"); - - d = absl::string_view(); - EXPECT_EQ(a.find_first_of(b), 0); - EXPECT_EQ(a.find_first_of(b, 0), 0); - EXPECT_EQ(a.find_first_of(b, 1), 1); - EXPECT_EQ(a.find_first_of(b, 2), 2); - EXPECT_EQ(a.find_first_of(b, 3), absl::string_view::npos); - EXPECT_EQ(a.find_first_of(c), 23); - EXPECT_EQ(a.find_first_of(c, 23), 23); - EXPECT_EQ(a.find_first_of(c, 24), 24); - EXPECT_EQ(a.find_first_of(c, 25), 25); - EXPECT_EQ(a.find_first_of(c, 26), absl::string_view::npos); - EXPECT_EQ(g.find_first_of(b), 13); - 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 - 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); - EXPECT_EQ(e.find_first_of(b), absl::string_view::npos); - EXPECT_EQ(d.find_first_of(d), absl::string_view::npos); - EXPECT_EQ(e.find_first_of(d), absl::string_view::npos); - EXPECT_EQ(d.find_first_of(e), absl::string_view::npos); - EXPECT_EQ(e.find_first_of(e), absl::string_view::npos); - - EXPECT_EQ(a.find_first_not_of(b), 3); - EXPECT_EQ(a.find_first_not_of(c), 0); - EXPECT_EQ(b.find_first_not_of(a), absl::string_view::npos); - EXPECT_EQ(c.find_first_not_of(a), absl::string_view::npos); - EXPECT_EQ(f.find_first_not_of(a), 0); - 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 - 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); - EXPECT_EQ(a.find_first_not_of(e, 1), 1); - EXPECT_EQ(a.find_first_not_of(d, a.size() - 1), a.size() - 1); - EXPECT_EQ(a.find_first_not_of(e, a.size() - 1), a.size() - 1); - EXPECT_EQ(a.find_first_not_of(d, a.size()), absl::string_view::npos); - EXPECT_EQ(a.find_first_not_of(e, a.size()), absl::string_view::npos); - EXPECT_EQ(a.find_first_not_of(d, absl::string_view::npos), - absl::string_view::npos); - EXPECT_EQ(a.find_first_not_of(e, absl::string_view::npos), - absl::string_view::npos); - EXPECT_EQ(d.find_first_not_of(a), absl::string_view::npos); - EXPECT_EQ(e.find_first_not_of(a), absl::string_view::npos); - EXPECT_EQ(d.find_first_not_of(d), absl::string_view::npos); - EXPECT_EQ(e.find_first_not_of(d), absl::string_view::npos); - EXPECT_EQ(d.find_first_not_of(e), absl::string_view::npos); - EXPECT_EQ(e.find_first_not_of(e), absl::string_view::npos); - - absl::string_view h("===="); - EXPECT_EQ(h.find_first_not_of('='), absl::string_view::npos); - EXPECT_EQ(h.find_first_not_of('=', 3), absl::string_view::npos); - EXPECT_EQ(h.find_first_not_of('\0'), 0); - EXPECT_EQ(g.find_first_not_of('x'), 2); - 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 - 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); - EXPECT_EQ(e.find_first_not_of('\0'), absl::string_view::npos); -} - -// Continued from STL2 -TEST(StringViewTest, STL2FindLast) { - const absl::string_view a("abcdefghijklmnopqrstuvwxyz"); - const absl::string_view b("abc"); - const absl::string_view c("xyz"); - absl::string_view d("foobar"); - const absl::string_view e; - const absl::string_view f( - "123" - "\0" - "456", - 7); - absl::string_view g("xx not found bb"); - absl::string_view h("===="); - absl::string_view i("56"); - - d = absl::string_view(); - EXPECT_EQ(h.find_last_of(a), absl::string_view::npos); - EXPECT_EQ(g.find_last_of(a), g.size()-1); - EXPECT_EQ(a.find_last_of(b), 2); - EXPECT_EQ(a.find_last_of(c), a.size()-1); - EXPECT_EQ(f.find_last_of(i), 6); - EXPECT_EQ(a.find_last_of('a'), 0); - EXPECT_EQ(a.find_last_of('b'), 1); - EXPECT_EQ(a.find_last_of('z'), 25); - EXPECT_EQ(a.find_last_of('a', 5), 0); - EXPECT_EQ(a.find_last_of('b', 5), 1); - EXPECT_EQ(a.find_last_of('b', 0), absl::string_view::npos); - EXPECT_EQ(a.find_last_of('z', 25), 25); - EXPECT_EQ(a.find_last_of('z', 24), absl::string_view::npos); - 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 - 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); - EXPECT_EQ(f.find_last_of(e, 4), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(d), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(e), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(d), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(e), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(f), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(f), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(d, 4), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(e, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(d, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(e, 4), absl::string_view::npos); - EXPECT_EQ(d.find_last_of(f, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_of(f, 4), absl::string_view::npos); - - EXPECT_EQ(a.find_last_not_of(b), a.size()-1); - EXPECT_EQ(a.find_last_not_of(c), 22); - EXPECT_EQ(b.find_last_not_of(a), absl::string_view::npos); - EXPECT_EQ(b.find_last_not_of(b), absl::string_view::npos); - EXPECT_EQ(f.find_last_not_of(i), 4); - 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 - 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); - EXPECT_EQ(f.find_last_not_of(e, 4), 4); - EXPECT_EQ(d.find_last_not_of(d), absl::string_view::npos); - EXPECT_EQ(d.find_last_not_of(e), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(d), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(e), absl::string_view::npos); - EXPECT_EQ(d.find_last_not_of(f), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(f), absl::string_view::npos); - EXPECT_EQ(d.find_last_not_of(d, 4), absl::string_view::npos); - EXPECT_EQ(d.find_last_not_of(e, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(d, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(e, 4), absl::string_view::npos); - EXPECT_EQ(d.find_last_not_of(f, 4), absl::string_view::npos); - EXPECT_EQ(e.find_last_not_of(f, 4), absl::string_view::npos); - - EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1); - EXPECT_EQ(h.find_last_not_of('='), absl::string_view::npos); - EXPECT_EQ(b.find_last_not_of('c'), 1); - 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 - 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); - EXPECT_EQ(e.find_last_not_of('\0'), absl::string_view::npos); -} - -// Continued from STL2 -TEST(StringViewTest, STL2Substr) { - const absl::string_view a("abcdefghijklmnopqrstuvwxyz"); - const absl::string_view b("abc"); - const absl::string_view c("xyz"); - absl::string_view d("foobar"); - const absl::string_view e; - - d = absl::string_view(); - EXPECT_EQ(a.substr(0, 3), b); - EXPECT_EQ(a.substr(23), c); - EXPECT_EQ(a.substr(23, 3), c); - EXPECT_EQ(a.substr(23, 99), c); - EXPECT_EQ(a.substr(0), a); - EXPECT_EQ(a.substr(3, 2), "de"); - // empty string nonsense - EXPECT_EQ(d.substr(0, 99), e); - // use of npos - EXPECT_EQ(a.substr(0, absl::string_view::npos), a); - EXPECT_EQ(a.substr(23, absl::string_view::npos), c); - // throw exception -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW((void)a.substr(99, 2), std::out_of_range); -#else - ABSL_EXPECT_DEATH_IF_SUPPORTED((void)a.substr(99, 2), - "absl::string_view::substr"); -#endif -} - -TEST(StringViewTest, TruncSubstr) { - const absl::string_view hi("hi"); - EXPECT_EQ("", absl::ClippedSubstr(hi, 0, 0)); - EXPECT_EQ("h", absl::ClippedSubstr(hi, 0, 1)); - EXPECT_EQ("hi", absl::ClippedSubstr(hi, 0)); - EXPECT_EQ("i", absl::ClippedSubstr(hi, 1)); - EXPECT_EQ("", absl::ClippedSubstr(hi, 2)); - EXPECT_EQ("", absl::ClippedSubstr(hi, 3)); // truncation - EXPECT_EQ("", absl::ClippedSubstr(hi, 3, 2)); // truncation -} - -TEST(StringViewTest, UTF8) { - std::string utf8 = "\u00E1"; - std::string utf8_twice = utf8 + " " + utf8; - int utf8_len = strlen(utf8.data()); - EXPECT_EQ(utf8_len, absl::string_view(utf8_twice).find_first_of(" ")); - EXPECT_EQ(utf8_len, absl::string_view(utf8_twice).find_first_of(" \t")); -} - -TEST(StringViewTest, FindConformance) { - struct { - std::string haystack; - std::string needle; - } specs[] = { - {"", ""}, - {"", "a"}, - {"a", ""}, - {"a", "a"}, - {"a", "b"}, - {"aa", ""}, - {"aa", "a"}, - {"aa", "b"}, - {"ab", "a"}, - {"ab", "b"}, - {"abcd", ""}, - {"abcd", "a"}, - {"abcd", "d"}, - {"abcd", "ab"}, - {"abcd", "bc"}, - {"abcd", "cd"}, - {"abcd", "abcd"}, - }; - for (const auto& s : specs) { - SCOPED_TRACE(s.haystack); - SCOPED_TRACE(s.needle); - std::string st = s.haystack; - absl::string_view sp = s.haystack; - for (size_t i = 0; i <= sp.size(); ++i) { - size_t pos = (i == sp.size()) ? absl::string_view::npos : i; - SCOPED_TRACE(pos); - EXPECT_EQ(sp.find(s.needle, pos), - st.find(s.needle, pos)); - EXPECT_EQ(sp.rfind(s.needle, pos), - st.rfind(s.needle, pos)); - EXPECT_EQ(sp.find_first_of(s.needle, pos), - st.find_first_of(s.needle, pos)); - EXPECT_EQ(sp.find_first_not_of(s.needle, pos), - st.find_first_not_of(s.needle, pos)); - EXPECT_EQ(sp.find_last_of(s.needle, pos), - st.find_last_of(s.needle, pos)); - EXPECT_EQ(sp.find_last_not_of(s.needle, pos), - st.find_last_not_of(s.needle, pos)); - } - } -} - -TEST(StringViewTest, Remove) { - absl::string_view a("foobar"); - std::string s1("123"); - s1 += '\0'; - s1 += "456"; - absl::string_view e; - std::string s2; - - // remove_prefix - absl::string_view c(a); - c.remove_prefix(3); - EXPECT_EQ(c, "bar"); - c = a; - c.remove_prefix(0); - EXPECT_EQ(c, a); - c.remove_prefix(c.size()); - EXPECT_EQ(c, e); - - // remove_suffix - c = a; - c.remove_suffix(3); - EXPECT_EQ(c, "foo"); - c = a; - c.remove_suffix(0); - EXPECT_EQ(c, a); - c.remove_suffix(c.size()); - EXPECT_EQ(c, e); -} - -TEST(StringViewTest, Set) { - absl::string_view a("foobar"); - absl::string_view empty; - absl::string_view b; - - // set - b = absl::string_view("foobar", 6); - EXPECT_EQ(b, a); - b = absl::string_view("foobar", 0); - EXPECT_EQ(b, empty); - b = absl::string_view("foobar", 7); - EXPECT_NE(b, a); - - b = absl::string_view("foobar"); - EXPECT_EQ(b, a); -} - -TEST(StringViewTest, FrontBack) { - static const char arr[] = "abcd"; - const absl::string_view csp(arr, 4); - EXPECT_EQ(&arr[0], &csp.front()); - EXPECT_EQ(&arr[3], &csp.back()); -} - -TEST(StringViewTest, FrontBackSingleChar) { - static const char c = 'a'; - const absl::string_view csp(&c, 1); - EXPECT_EQ(&c, &csp.front()); - EXPECT_EQ(&c, &csp.back()); -} - -TEST(StringViewTest, FrontBackEmpty) { -#ifndef ABSL_USES_STD_STRING_VIEW -#if !defined(NDEBUG) || ABSL_OPTION_HARDENED - // Abseil's string_view implementation has debug assertions that check that - // front() and back() are not called on an empty string_view. - absl::string_view sv; - ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.front(), ""); - ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.back(), ""); -#endif -#endif -} - -// `std::string_view::string_view(const char*)` calls -// `std::char_traits<char>::length(const char*)` to get the string length. In -// libc++, it doesn't allow `nullptr` in the constexpr context, with the error -// "read of dereferenced null pointer is not allowed in a constant expression". -// At run time, the behavior of `std::char_traits::length()` on `nullptr` is -// undefined by the standard and usually results in crash with libc++. -// GCC also started rejected this in libstdc++ starting in GCC9. -// In MSVC, creating a constexpr string_view from nullptr also triggers an -// "unevaluable pointer value" error. This compiler implementation conforms -// to the standard, but `absl::string_view` implements a different -// behavior for historical reasons. We work around tests that construct -// `string_view` from `nullptr` when using libc++. -#if !defined(ABSL_USES_STD_STRING_VIEW) || \ - (!(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9) && \ - !defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) -#define ABSL_HAVE_STRING_VIEW_FROM_NULLPTR 1 -#endif - -TEST(StringViewTest, NULLInput) { - absl::string_view s; - EXPECT_EQ(s.data(), nullptr); - EXPECT_EQ(s.size(), 0); - -#ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR - s = absl::string_view(nullptr); - EXPECT_EQ(s.data(), nullptr); - EXPECT_EQ(s.size(), 0); - - // .ToString() on a absl::string_view with nullptr should produce the empty - // string. - EXPECT_EQ("", std::string(s)); -#endif // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR -} - -TEST(StringViewTest, Comparisons2) { - // The `compare` member has 6 overloads (v: string_view, s: const char*): - // (1) compare(v) - // (2) compare(pos1, count1, v) - // (3) compare(pos1, count1, v, pos2, count2) - // (4) compare(s) - // (5) compare(pos1, count1, s) - // (6) compare(pos1, count1, s, count2) - - absl::string_view abc("abcdefghijklmnopqrstuvwxyz"); - - // check comparison operations on strings longer than 4 bytes. - EXPECT_EQ(abc, absl::string_view("abcdefghijklmnopqrstuvwxyz")); - EXPECT_EQ(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxyz")), 0); - - EXPECT_LT(abc, absl::string_view("abcdefghijklmnopqrstuvwxzz")); - EXPECT_LT(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxzz")), 0); - - EXPECT_GT(abc, absl::string_view("abcdefghijklmnopqrstuvwxyy")); - EXPECT_GT(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxyy")), 0); - - // The "substr" variants of `compare`. - absl::string_view digits("0123456789"); - auto npos = absl::string_view::npos; - - // Taking string_view - EXPECT_EQ(digits.compare(3, npos, absl::string_view("3456789")), 0); // 2 - EXPECT_EQ(digits.compare(3, 4, absl::string_view("3456")), 0); // 2 - EXPECT_EQ(digits.compare(10, 0, absl::string_view()), 0); // 2 - EXPECT_EQ(digits.compare(3, 4, absl::string_view("0123456789"), 3, 4), - 0); // 3 - EXPECT_LT(digits.compare(3, 4, absl::string_view("0123456789"), 3, 5), - 0); // 3 - EXPECT_LT(digits.compare(0, npos, absl::string_view("0123456789"), 3, 5), - 0); // 3 - // Taking const char* - EXPECT_EQ(digits.compare(3, 4, "3456"), 0); // 5 - EXPECT_EQ(digits.compare(3, npos, "3456789"), 0); // 5 - EXPECT_EQ(digits.compare(10, 0, ""), 0); // 5 - EXPECT_EQ(digits.compare(3, 4, "0123456789", 3, 4), 0); // 6 - EXPECT_LT(digits.compare(3, 4, "0123456789", 3, 5), 0); // 6 - EXPECT_LT(digits.compare(0, npos, "0123456789", 3, 5), 0); // 6 -} - -TEST(StringViewTest, At) { - absl::string_view abc = "abc"; - EXPECT_EQ(abc.at(0), 'a'); - EXPECT_EQ(abc.at(1), 'b'); - EXPECT_EQ(abc.at(2), 'c'); -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(abc.at(3), std::out_of_range); -#else - ABSL_EXPECT_DEATH_IF_SUPPORTED(abc.at(3), "absl::string_view::at"); -#endif -} - -struct MyCharAlloc : std::allocator<char> {}; - -TEST(StringViewTest, ExplicitConversionOperator) { - absl::string_view sp = "hi"; - EXPECT_EQ(sp, std::string(sp)); -} - -TEST(StringViewTest, NullSafeStringView) { - { - absl::string_view s = absl::NullSafeStringView(nullptr); - EXPECT_EQ(nullptr, s.data()); - EXPECT_EQ(0, s.size()); - EXPECT_EQ(absl::string_view(), s); - } - { - static const char kHi[] = "hi"; - absl::string_view s = absl::NullSafeStringView(kHi); - EXPECT_EQ(kHi, s.data()); - EXPECT_EQ(strlen(kHi), s.size()); - EXPECT_EQ(absl::string_view("hi"), s); - } -} - -TEST(StringViewTest, ConstexprNullSafeStringView) { - { - constexpr absl::string_view s = absl::NullSafeStringView(nullptr); - EXPECT_EQ(nullptr, s.data()); - EXPECT_EQ(0, s.size()); - EXPECT_EQ(absl::string_view(), s); - } -#if !defined(_MSC_VER) || _MSC_VER >= 1910 - // MSVC 2017+ is required for good constexpr string_view support. - // See the implementation of `absl::string_view::StrlenInternal()`. - { - static constexpr char kHi[] = "hi"; - absl::string_view s = absl::NullSafeStringView(kHi); - EXPECT_EQ(kHi, s.data()); - EXPECT_EQ(strlen(kHi), s.size()); - EXPECT_EQ(absl::string_view("hi"), s); - } - { - constexpr absl::string_view s = absl::NullSafeStringView("hello"); - EXPECT_EQ(s.size(), 5); - EXPECT_EQ("hello", s); - } -#endif -} - -TEST(StringViewTest, ConstexprCompiles) { - constexpr absl::string_view sp; -#ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR - constexpr absl::string_view cstr(nullptr); -#endif - constexpr absl::string_view cstr_len("cstr", 4); - -#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 - // 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 - // resolved 2017-06-02. See - // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2232 - // TODO(zhangxy): Update the condition when libstdc++ adopts the constexpr - // length(). -#if !defined(__GLIBCXX__) -#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1 -#endif // !__GLIBCXX__ - -#else // ABSL_USES_STD_STRING_VIEW - -// This duplicates the check for __builtin_strlen in the header. -#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1 -#elif defined(__GNUC__) // GCC or clang -#error GCC/clang should have constexpr string_view. -#endif - -// MSVC 2017+ should be able to construct a constexpr string_view from a cstr. -#if defined(_MSC_VER) && _MSC_VER >= 1910 -#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1 -#endif - -#endif // ABSL_USES_STD_STRING_VIEW - -#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR - constexpr absl::string_view cstr_strlen("foo"); - EXPECT_EQ(cstr_strlen.length(), 3); - constexpr absl::string_view cstr_strlen2 = "bar"; - EXPECT_EQ(cstr_strlen2, "bar"); - -#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \ - (defined(__GNUC__) && !defined(__clang__)) -#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON 1 -#endif -#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON - constexpr absl::string_view foo = "foo"; - constexpr absl::string_view bar = "bar"; - constexpr bool foo_eq_bar = foo == bar; - constexpr bool foo_ne_bar = foo != bar; - constexpr bool foo_lt_bar = foo < bar; - constexpr bool foo_le_bar = foo <= bar; - constexpr bool foo_gt_bar = foo > bar; - constexpr bool foo_ge_bar = foo >= bar; - constexpr int foo_compare_bar = foo.compare(bar); - EXPECT_FALSE(foo_eq_bar); - EXPECT_TRUE(foo_ne_bar); - EXPECT_FALSE(foo_lt_bar); - EXPECT_FALSE(foo_le_bar); - EXPECT_TRUE(foo_gt_bar); - EXPECT_TRUE(foo_ge_bar); - EXPECT_GT(foo_compare_bar, 0); -#endif -#endif - -#if !defined(__clang__) || 3 < __clang_major__ || \ - (3 == __clang_major__ && 4 < __clang_minor__) - // older clang versions (< 3.5) complain that: - // "cannot perform pointer arithmetic on null pointer" - constexpr absl::string_view::iterator const_begin_empty = sp.begin(); - constexpr absl::string_view::iterator const_end_empty = sp.end(); - EXPECT_EQ(const_begin_empty, const_end_empty); - -#ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR - constexpr absl::string_view::iterator const_begin_nullptr = cstr.begin(); - constexpr absl::string_view::iterator const_end_nullptr = cstr.end(); - EXPECT_EQ(const_begin_nullptr, const_end_nullptr); -#endif // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR -#endif // !defined(__clang__) || ... - - constexpr absl::string_view::iterator const_begin = cstr_len.begin(); - constexpr absl::string_view::iterator const_end = cstr_len.end(); - constexpr absl::string_view::size_type const_size = cstr_len.size(); - constexpr absl::string_view::size_type const_length = cstr_len.length(); - static_assert(const_begin + const_size == const_end, - "pointer arithmetic check"); - static_assert(const_begin + const_length == const_end, - "pointer arithmetic check"); -#ifndef _MSC_VER - // MSVC has bugs doing constexpr pointer arithmetic. - // https://developercommunity.visualstudio.com/content/problem/482192/bad-pointer-arithmetic-in-constepxr-2019-rc1-svc1.html - EXPECT_EQ(const_begin + const_size, const_end); - EXPECT_EQ(const_begin + const_length, const_end); -#endif - - constexpr bool isempty = sp.empty(); - EXPECT_TRUE(isempty); - - constexpr const char c = cstr_len[2]; - EXPECT_EQ(c, 't'); - - constexpr const char cfront = cstr_len.front(); - constexpr const char cback = cstr_len.back(); - EXPECT_EQ(cfront, 'c'); - EXPECT_EQ(cback, 'r'); - - constexpr const char* np = sp.data(); - constexpr const char* cstr_ptr = cstr_len.data(); - EXPECT_EQ(np, nullptr); - EXPECT_NE(cstr_ptr, nullptr); - - constexpr size_t sp_npos = sp.npos; - EXPECT_EQ(sp_npos, -1); -} - -TEST(StringViewTest, ConstexprSubstr) { - constexpr absl::string_view foobar("foobar", 6); - constexpr absl::string_view foo = foobar.substr(0, 3); - constexpr absl::string_view bar = foobar.substr(3); - EXPECT_EQ(foo, "foo"); - EXPECT_EQ(bar, "bar"); -} - -TEST(StringViewTest, Noexcept) { - EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view, - const std::string&>::value)); - EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view, - const std::string&>::value)); - EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value); - constexpr absl::string_view sp; - EXPECT_TRUE(noexcept(sp.begin())); - EXPECT_TRUE(noexcept(sp.end())); - EXPECT_TRUE(noexcept(sp.cbegin())); - EXPECT_TRUE(noexcept(sp.cend())); - EXPECT_TRUE(noexcept(sp.rbegin())); - EXPECT_TRUE(noexcept(sp.rend())); - EXPECT_TRUE(noexcept(sp.crbegin())); - EXPECT_TRUE(noexcept(sp.crend())); - EXPECT_TRUE(noexcept(sp.size())); - EXPECT_TRUE(noexcept(sp.length())); - EXPECT_TRUE(noexcept(sp.empty())); - EXPECT_TRUE(noexcept(sp.data())); - EXPECT_TRUE(noexcept(sp.compare(sp))); - EXPECT_TRUE(noexcept(sp.find(sp))); - EXPECT_TRUE(noexcept(sp.find('f'))); - EXPECT_TRUE(noexcept(sp.rfind(sp))); - EXPECT_TRUE(noexcept(sp.rfind('f'))); - EXPECT_TRUE(noexcept(sp.find_first_of(sp))); - EXPECT_TRUE(noexcept(sp.find_first_of('f'))); - EXPECT_TRUE(noexcept(sp.find_last_of(sp))); - EXPECT_TRUE(noexcept(sp.find_last_of('f'))); - EXPECT_TRUE(noexcept(sp.find_first_not_of(sp))); - EXPECT_TRUE(noexcept(sp.find_first_not_of('f'))); - EXPECT_TRUE(noexcept(sp.find_last_not_of(sp))); - EXPECT_TRUE(noexcept(sp.find_last_not_of('f'))); -} - -TEST(StringViewTest, BoundsCheck) { -#ifndef ABSL_USES_STD_STRING_VIEW -#if !defined(NDEBUG) || ABSL_OPTION_HARDENED - // Abseil's string_view implementation has bounds-checking in debug mode. - absl::string_view h = "hello"; - ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], ""); - ABSL_EXPECT_DEATH_IF_SUPPORTED(h[-1], ""); -#endif -#endif -} - -TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { - EXPECT_EQ("hello", std::string("hello")); - EXPECT_LT("hello", std::string("world")); -} - -TEST(ComparisonOpsTest, HeterogenousStringViewEquals) { - EXPECT_EQ(absl::string_view("hello"), std::string("hello")); - EXPECT_EQ("hello", absl::string_view("hello")); -} - -TEST(FindOneCharTest, EdgeCases) { - absl::string_view a("xxyyyxx"); - - // Set a = "xyyyx". - a.remove_prefix(1); - a.remove_suffix(1); - - EXPECT_EQ(0, a.find('x')); - EXPECT_EQ(0, a.find('x', 0)); - EXPECT_EQ(4, a.find('x', 1)); - EXPECT_EQ(4, a.find('x', 4)); - EXPECT_EQ(absl::string_view::npos, a.find('x', 5)); - - EXPECT_EQ(4, a.rfind('x')); - EXPECT_EQ(4, a.rfind('x', 5)); - EXPECT_EQ(4, a.rfind('x', 4)); - EXPECT_EQ(0, a.rfind('x', 3)); - EXPECT_EQ(0, a.rfind('x', 0)); - - // Set a = "yyy". - a.remove_prefix(1); - a.remove_suffix(1); - - EXPECT_EQ(absl::string_view::npos, a.find('x')); - EXPECT_EQ(absl::string_view::npos, a.rfind('x')); -} - -#ifndef ABSL_HAVE_THREAD_SANITIZER // Allocates too much memory for tsan. -TEST(HugeStringView, TwoPointTwoGB) { - if (sizeof(size_t) <= 4) - return; - // Try a huge string piece. - const size_t size = size_t{2200} * 1000 * 1000; - std::string s(size, 'a'); - absl::string_view sp(s); - EXPECT_EQ(size, sp.length()); - sp.remove_prefix(1); - EXPECT_EQ(size - 1, sp.length()); - sp.remove_suffix(2); - EXPECT_EQ(size - 1 - 2, sp.length()); -} -#endif // ABSL_HAVE_THREAD_SANITIZER - -#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW) -TEST(NonNegativeLenTest, NonNegativeLen) { - ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("xyz", -1), - "len <= kMaxSize"); -} - -TEST(LenExceedsMaxSizeTest, LenExceedsMaxSize) { - auto max_size = absl::string_view().max_size(); - - // This should construct ok (although the view itself is obviously invalid). - absl::string_view ok_view("", max_size); - - // Adding one to the max should trigger an assertion. - ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("", max_size + 1), - "len <= kMaxSize"); -} -#endif // !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW) - -class StringViewStreamTest : public ::testing::Test { - public: - // Set negative 'width' for right justification. - template <typename T> - std::string Pad(const T& s, int width, char fill = 0) { - std::ostringstream oss; - if (fill != 0) { - oss << std::setfill(fill); - } - if (width < 0) { - width = -width; - oss << std::right; - } - oss << std::setw(width) << s; - return oss.str(); - } -}; - -TEST_F(StringViewStreamTest, Padding) { - std::string s("hello"); - absl::string_view sp(s); - for (int w = -64; w < 64; ++w) { - SCOPED_TRACE(w); - EXPECT_EQ(Pad(s, w), Pad(sp, w)); - } - for (int w = -64; w < 64; ++w) { - SCOPED_TRACE(w); - EXPECT_EQ(Pad(s, w, '#'), Pad(sp, w, '#')); - } -} - -TEST_F(StringViewStreamTest, ResetsWidth) { - // Width should reset after one formatted write. - // If we weren't resetting width after formatting the string_view, - // we'd have width=5 carrying over to the printing of the "]", - // creating "[###hi####]". - std::string s = "hi"; - absl::string_view sp = s; - { - std::ostringstream oss; - oss << "[" << std::setfill('#') << std::setw(5) << s << "]"; - ASSERT_EQ("[###hi]", oss.str()); - } - { - std::ostringstream oss; - oss << "[" << std::setfill('#') << std::setw(5) << sp << "]"; - EXPECT_EQ("[###hi]", oss.str()); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/strip.h b/third_party/abseil_cpp/absl/strings/strip.h deleted file mode 100644 index 111872ca54ba..000000000000 --- a/third_party/abseil_cpp/absl/strings/strip.h +++ /dev/null @@ -1,91 +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. -// -// ----------------------------------------------------------------------------- -// File: strip.h -// ----------------------------------------------------------------------------- -// -// This file contains various functions for stripping substrings from a string. -#ifndef ABSL_STRINGS_STRIP_H_ -#define ABSL_STRINGS_STRIP_H_ - -#include <cstddef> -#include <string> - -#include "absl/base/macros.h" -#include "absl/strings/ascii.h" -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ConsumePrefix() -// -// Strips the `expected` prefix from the start of the given string, returning -// `true` if the strip operation succeeded or false otherwise. -// -// Example: -// -// absl::string_view input("abc"); -// EXPECT_TRUE(absl::ConsumePrefix(&input, "a")); -// EXPECT_EQ(input, "bc"); -inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) { - if (!absl::StartsWith(*str, expected)) return false; - str->remove_prefix(expected.size()); - return true; -} -// ConsumeSuffix() -// -// Strips the `expected` suffix from the end of the given string, returning -// `true` if the strip operation succeeded or false otherwise. -// -// Example: -// -// absl::string_view input("abcdef"); -// EXPECT_TRUE(absl::ConsumeSuffix(&input, "def")); -// EXPECT_EQ(input, "abc"); -inline bool ConsumeSuffix(absl::string_view* str, absl::string_view expected) { - if (!absl::EndsWith(*str, expected)) return false; - str->remove_suffix(expected.size()); - return true; -} - -// StripPrefix() -// -// Returns a view into the input string 'str' with the given 'prefix' removed, -// but leaving the original string intact. If the prefix does not match at the -// start of the string, returns the original string instead. -ABSL_MUST_USE_RESULT inline absl::string_view StripPrefix( - absl::string_view str, absl::string_view prefix) { - if (absl::StartsWith(str, prefix)) str.remove_prefix(prefix.size()); - return str; -} - -// StripSuffix() -// -// Returns a view into the input string 'str' with the given 'suffix' removed, -// but leaving the original string intact. If the suffix does not match at the -// end of the string, returns the original string instead. -ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix( - absl::string_view str, absl::string_view suffix) { - if (absl::EndsWith(str, suffix)) str.remove_suffix(suffix.size()); - return str; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_STRIP_H_ diff --git a/third_party/abseil_cpp/absl/strings/strip_test.cc b/third_party/abseil_cpp/absl/strings/strip_test.cc deleted file mode 100644 index e4e00cb66ebc..000000000000 --- a/third_party/abseil_cpp/absl/strings/strip_test.cc +++ /dev/null @@ -1,198 +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 contains functions that remove a defined part from the string, -// i.e., strip the string. - -#include "absl/strings/strip.h" - -#include <cassert> -#include <cstdio> -#include <cstring> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" - -namespace { - -TEST(Strip, ConsumePrefixOneChar) { - absl::string_view input("abc"); - EXPECT_TRUE(absl::ConsumePrefix(&input, "a")); - EXPECT_EQ(input, "bc"); - - EXPECT_FALSE(absl::ConsumePrefix(&input, "x")); - EXPECT_EQ(input, "bc"); - - EXPECT_TRUE(absl::ConsumePrefix(&input, "b")); - EXPECT_EQ(input, "c"); - - EXPECT_TRUE(absl::ConsumePrefix(&input, "c")); - EXPECT_EQ(input, ""); - - EXPECT_FALSE(absl::ConsumePrefix(&input, "a")); - EXPECT_EQ(input, ""); -} - -TEST(Strip, ConsumePrefix) { - absl::string_view input("abcdef"); - EXPECT_FALSE(absl::ConsumePrefix(&input, "abcdefg")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_FALSE(absl::ConsumePrefix(&input, "abce")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_TRUE(absl::ConsumePrefix(&input, "")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_FALSE(absl::ConsumePrefix(&input, "abcdeg")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_TRUE(absl::ConsumePrefix(&input, "abcdef")); - EXPECT_EQ(input, ""); - - input = "abcdef"; - EXPECT_TRUE(absl::ConsumePrefix(&input, "abcde")); - EXPECT_EQ(input, "f"); -} - -TEST(Strip, ConsumeSuffix) { - absl::string_view input("abcdef"); - EXPECT_FALSE(absl::ConsumeSuffix(&input, "abcdefg")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_TRUE(absl::ConsumeSuffix(&input, "")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_TRUE(absl::ConsumeSuffix(&input, "def")); - EXPECT_EQ(input, "abc"); - - input = "abcdef"; - EXPECT_FALSE(absl::ConsumeSuffix(&input, "abcdeg")); - EXPECT_EQ(input, "abcdef"); - - EXPECT_TRUE(absl::ConsumeSuffix(&input, "f")); - EXPECT_EQ(input, "abcde"); - - EXPECT_TRUE(absl::ConsumeSuffix(&input, "abcde")); - EXPECT_EQ(input, ""); -} - -TEST(Strip, StripPrefix) { - const absl::string_view null_str; - - EXPECT_EQ(absl::StripPrefix("foobar", "foo"), "bar"); - EXPECT_EQ(absl::StripPrefix("foobar", ""), "foobar"); - EXPECT_EQ(absl::StripPrefix("foobar", null_str), "foobar"); - EXPECT_EQ(absl::StripPrefix("foobar", "foobar"), ""); - EXPECT_EQ(absl::StripPrefix("foobar", "bar"), "foobar"); - EXPECT_EQ(absl::StripPrefix("foobar", "foobarr"), "foobar"); - EXPECT_EQ(absl::StripPrefix("", ""), ""); -} - -TEST(Strip, StripSuffix) { - const absl::string_view null_str; - - EXPECT_EQ(absl::StripSuffix("foobar", "bar"), "foo"); - EXPECT_EQ(absl::StripSuffix("foobar", ""), "foobar"); - EXPECT_EQ(absl::StripSuffix("foobar", null_str), "foobar"); - EXPECT_EQ(absl::StripSuffix("foobar", "foobar"), ""); - EXPECT_EQ(absl::StripSuffix("foobar", "foo"), "foobar"); - EXPECT_EQ(absl::StripSuffix("foobar", "ffoobar"), "foobar"); - EXPECT_EQ(absl::StripSuffix("", ""), ""); -} - -TEST(Strip, RemoveExtraAsciiWhitespace) { - const char* inputs[] = { - "No extra space", - " Leading whitespace", - "Trailing whitespace ", - " Leading and trailing ", - " Whitespace \t in\v middle ", - "'Eeeeep! \n Newlines!\n", - "nospaces", - }; - const char* outputs[] = { - "No extra space", - "Leading whitespace", - "Trailing whitespace", - "Leading and trailing", - "Whitespace in middle", - "'Eeeeep! Newlines!", - "nospaces", - }; - int NUM_TESTS = 7; - - for (int i = 0; i < NUM_TESTS; i++) { - std::string s(inputs[i]); - absl::RemoveExtraAsciiWhitespace(&s); - EXPECT_STREQ(outputs[i], s.c_str()); - } - - // Test that absl::RemoveExtraAsciiWhitespace returns immediately for empty - // strings (It was adding the \0 character to the C++ std::string, which broke - // tests involving empty()) - std::string zero_string = ""; - assert(zero_string.empty()); - absl::RemoveExtraAsciiWhitespace(&zero_string); - EXPECT_EQ(zero_string.size(), 0); - EXPECT_TRUE(zero_string.empty()); -} - -TEST(Strip, StripTrailingAsciiWhitespace) { - std::string test = "foo "; - absl::StripTrailingAsciiWhitespace(&test); - EXPECT_EQ(test, "foo"); - - test = " "; - absl::StripTrailingAsciiWhitespace(&test); - EXPECT_EQ(test, ""); - - test = ""; - absl::StripTrailingAsciiWhitespace(&test); - EXPECT_EQ(test, ""); - - test = " abc\t"; - absl::StripTrailingAsciiWhitespace(&test); - EXPECT_EQ(test, " abc"); -} - -TEST(String, StripLeadingAsciiWhitespace) { - absl::string_view orig = "\t \n\f\r\n\vfoo"; - EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace(orig)); - orig = "\t \n\f\r\v\n\t \n\f\r\v\n"; - EXPECT_EQ(absl::string_view(), absl::StripLeadingAsciiWhitespace(orig)); -} - -TEST(Strip, StripAsciiWhitespace) { - std::string test2 = "\t \f\r\n\vfoo \t\f\r\v\n"; - absl::StripAsciiWhitespace(&test2); - EXPECT_EQ(test2, "foo"); - std::string test3 = "bar"; - absl::StripAsciiWhitespace(&test3); - EXPECT_EQ(test3, "bar"); - std::string test4 = "\t \f\r\n\vfoo"; - absl::StripAsciiWhitespace(&test4); - EXPECT_EQ(test4, "foo"); - std::string test5 = "foo \t\f\r\v\n"; - absl::StripAsciiWhitespace(&test5); - EXPECT_EQ(test5, "foo"); - absl::string_view test6("\t \f\r\n\vfoo \t\f\r\v\n"); - test6 = absl::StripAsciiWhitespace(test6); - EXPECT_EQ(test6, "foo"); - test6 = absl::StripAsciiWhitespace(test6); - EXPECT_EQ(test6, "foo"); // already stripped -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/strings/substitute.cc b/third_party/abseil_cpp/absl/strings/substitute.cc deleted file mode 100644 index 1f3c7409abb6..000000000000 --- a/third_party/abseil_cpp/absl/strings/substitute.cc +++ /dev/null @@ -1,171 +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/strings/substitute.h" - -#include <algorithm> - -#include "absl/base/internal/raw_logging.h" -#include "absl/strings/ascii.h" -#include "absl/strings/escaping.h" -#include "absl/strings/internal/resize_uninitialized.h" -#include "absl/strings/string_view.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace substitute_internal { - -void SubstituteAndAppendArray(std::string* output, absl::string_view format, - const absl::string_view* args_array, - size_t num_args) { - // Determine total size needed. - size_t size = 0; - for (size_t i = 0; i < format.size(); i++) { - if (format[i] == '$') { - if (i + 1 >= format.size()) { -#ifndef NDEBUG - ABSL_RAW_LOG(FATAL, - "Invalid absl::Substitute() format string: \"%s\".", - absl::CEscape(format).c_str()); -#endif - return; - } else if (absl::ascii_isdigit(format[i + 1])) { - int index = format[i + 1] - '0'; - if (static_cast<size_t>(index) >= num_args) { -#ifndef NDEBUG - ABSL_RAW_LOG( - FATAL, - "Invalid absl::Substitute() format string: asked for \"$" - "%d\", but only %d args were given. Full format string was: " - "\"%s\".", - index, static_cast<int>(num_args), absl::CEscape(format).c_str()); -#endif - return; - } - size += args_array[index].size(); - ++i; // Skip next char. - } else if (format[i + 1] == '$') { - ++size; - ++i; // Skip next char. - } else { -#ifndef NDEBUG - ABSL_RAW_LOG(FATAL, - "Invalid absl::Substitute() format string: \"%s\".", - absl::CEscape(format).c_str()); -#endif - return; - } - } else { - ++size; - } - } - - if (size == 0) return; - - // Build the string. - size_t original_size = output->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] == '$') { - if (absl::ascii_isdigit(format[i + 1])) { - const absl::string_view src = args_array[format[i + 1] - '0']; - target = std::copy(src.begin(), src.end(), target); - ++i; // Skip next char. - } else if (format[i + 1] == '$') { - *target++ = '$'; - ++i; // Skip next char. - } - } else { - *target++ = format[i]; - } - } - - assert(target == output->data() + output->size()); -} - -Arg::Arg(const void* value) { - static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2, - "fix sizeof(scratch_)"); - if (value == nullptr) { - piece_ = "NULL"; - } else { - char* ptr = scratch_ + sizeof(scratch_); - uintptr_t num = reinterpret_cast<uintptr_t>(value); - do { - *--ptr = absl::numbers_internal::kHexChar[num & 0xf]; - num >>= 4; - } while (num != 0); - *--ptr = 'x'; - *--ptr = '0'; - piece_ = absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr); - } -} - -// TODO(jorg): Don't duplicate so much code between here and str_cat.cc -Arg::Arg(Hex hex) { - char* const end = &scratch_[numbers_internal::kFastToBufferSize]; - char* writer = end; - uint64_t value = hex.value; - do { - *--writer = absl::numbers_internal::kHexChar[value & 0xF]; - value >>= 4; - } while (value != 0); - - char* beg; - if (end - writer < hex.width) { - beg = end - hex.width; - std::fill_n(beg, writer - beg, hex.fill); - } else { - beg = writer; - } - - piece_ = absl::string_view(beg, end - beg); -} - -// TODO(jorg): Don't duplicate so much code between here and str_cat.cc -Arg::Arg(Dec dec) { - assert(dec.width <= numbers_internal::kFastToBufferSize); - char* const end = &scratch_[numbers_internal::kFastToBufferSize]; - char* const minfill = end - dec.width; - char* writer = end; - uint64_t value = dec.value; - bool neg = dec.neg; - while (value > 9) { - *--writer = '0' + (value % 10); - value /= 10; - } - *--writer = '0' + value; - if (neg) *--writer = '-'; - - ptrdiff_t fillers = writer - minfill; - if (fillers > 0) { - // Tricky: if the fill character is ' ', then it's <fill><+/-><digits> - // But...: if the fill character is '0', then it's <+/-><fill><digits> - bool add_sign_again = false; - if (neg && dec.fill == '0') { // If filling with '0', - ++writer; // ignore the sign we just added - add_sign_again = true; // and re-add the sign later. - } - writer -= fillers; - std::fill_n(writer, fillers, dec.fill); - if (add_sign_again) *--writer = '-'; - } - - piece_ = absl::string_view(writer, end - writer); -} - -} // namespace substitute_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/strings/substitute.h b/third_party/abseil_cpp/absl/strings/substitute.h deleted file mode 100644 index c6da4dc6e722..000000000000 --- a/third_party/abseil_cpp/absl/strings/substitute.h +++ /dev/null @@ -1,696 +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. -// -// ----------------------------------------------------------------------------- -// File: substitute.h -// ----------------------------------------------------------------------------- -// -// This package contains functions for efficiently performing string -// substitutions using a format string with positional notation: -// `Substitute()` and `SubstituteAndAppend()`. -// -// Unlike printf-style format specifiers, `Substitute()` functions do not need -// to specify the type of the substitution arguments. Supported arguments -// following the format string, such as strings, string_views, ints, -// floats, and bools, are automatically converted to strings during the -// substitution process. (See below for a full list of supported types.) -// -// `Substitute()` does not allow you to specify *how* to format a value, beyond -// the default conversion to string. For example, you cannot format an integer -// in hex. -// -// The format string uses positional identifiers indicated by a dollar sign ($) -// and single digit positional ids to indicate which substitution arguments to -// use at that location within the format string. -// -// A '$$' sequence in the format string causes a literal '$' character to be -// output. -// -// Example 1: -// std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!", -// 5, "Bob", "Apples"); -// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s); -// -// Example 2: -// std::string s = "Hi. "; -// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5); -// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s); -// -// Supported types: -// * absl::string_view, std::string, const char* (null is equivalent to "") -// * int32_t, int64_t, uint32_t, uint64_t -// * float, double -// * bool (Printed as "true" or "false") -// * pointer types other than char* (Printed as "0x<lower case hex string>", -// except that null is printed as "NULL") -// -// If an invalid format string is provided, Substitute returns an empty string -// and SubstituteAndAppend does not change the provided output string. -// A format string is invalid if it: -// * ends in an unescaped $ character, -// e.g. "Hello $", or -// * calls for a position argument which is not provided, -// e.g. Substitute("Hello $2", "world"), or -// * specifies a non-digit, non-$ character after an unescaped $ character, -// e.g. "Hello $f". -// In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program. - -#ifndef ABSL_STRINGS_SUBSTITUTE_H_ -#define ABSL_STRINGS_SUBSTITUTE_H_ - -#include <cstring> -#include <string> -#include <type_traits> -#include <vector> - -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/strings/ascii.h" -#include "absl/strings/escaping.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/strings/strip.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace substitute_internal { - -// Arg -// -// This class provides an argument type for `absl::Substitute()` and -// `absl::SubstituteAndAppend()`. `Arg` handles implicit conversion of various -// types to a string. (`Arg` is very similar to the `AlphaNum` class in -// `StrCat()`.) -// -// This class has implicit constructors. -class Arg { - public: - // Overloads for string-y things - // - // Explicitly overload `const char*` so the compiler doesn't cast to `bool`. - Arg(const char* value) // NOLINT(runtime/explicit) - : piece_(absl::NullSafeStringView(value)) {} - template <typename Allocator> - Arg( // NOLINT - const std::basic_string<char, std::char_traits<char>, Allocator>& - value) noexcept - : piece_(value) {} - Arg(absl::string_view value) // NOLINT(runtime/explicit) - : piece_(value) {} - - // Overloads for primitives - // - // No overloads are available for signed and unsigned char because if people - // are explicitly declaring their chars as signed or unsigned then they are - // probably using them as 8-bit integers and would probably prefer an integer - // representation. However, we can't really know, so we make the caller decide - // what to do. - Arg(char value) // NOLINT(runtime/explicit) - : piece_(scratch_, 1) { - scratch_[0] = value; - } - Arg(short value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(unsigned short value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(int value) // NOLINT(runtime/explicit) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(unsigned int value) // NOLINT(runtime/explicit) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(long value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(unsigned long value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(long long value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(unsigned long long value) // NOLINT(*) - : piece_(scratch_, - numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {} - Arg(float value) // NOLINT(runtime/explicit) - : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) { - } - Arg(double value) // NOLINT(runtime/explicit) - : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) { - } - Arg(bool value) // NOLINT(runtime/explicit) - : piece_(value ? "true" : "false") {} - - Arg(Hex hex); // NOLINT(runtime/explicit) - Arg(Dec dec); // NOLINT(runtime/explicit) - - // vector<bool>::reference and const_reference require special help to - // convert to `AlphaNum` because it requires two user defined conversions. - template <typename T, - absl::enable_if_t< - std::is_class<T>::value && - (std::is_same<T, std::vector<bool>::reference>::value || - std::is_same<T, std::vector<bool>::const_reference>::value)>* = - nullptr> - Arg(T value) // NOLINT(google-explicit-constructor) - : Arg(static_cast<bool>(value)) {} - - // `void*` values, with the exception of `char*`, are printed as - // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed. - Arg(const void* value); // NOLINT(runtime/explicit) - - Arg(const Arg&) = delete; - Arg& operator=(const Arg&) = delete; - - absl::string_view piece() const { return piece_; } - - private: - absl::string_view piece_; - char scratch_[numbers_internal::kFastToBufferSize]; -}; - -// Internal helper function. Don't call this from outside this implementation. -// This interface may change without notice. -void SubstituteAndAppendArray(std::string* output, absl::string_view format, - const absl::string_view* args_array, - size_t num_args); - -#if defined(ABSL_BAD_CALL_IF) -constexpr int CalculateOneBit(const char* format) { - // Returns: - // * 2^N for '$N' when N is in [0-9] - // * 0 for correct '$' escaping: '$$'. - // * -1 otherwise. - return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1) - : (1 << (*format - '0')); -} - -constexpr const char* SkipNumber(const char* format) { - return !*format ? format : (format + 1); -} - -constexpr int PlaceholderBitmask(const char* format) { - return !*format - ? 0 - : *format != '$' ? PlaceholderBitmask(format + 1) - : (CalculateOneBit(format + 1) | - PlaceholderBitmask(SkipNumber(format + 1))); -} -#endif // ABSL_BAD_CALL_IF - -} // namespace substitute_internal - -// -// PUBLIC API -// - -// SubstituteAndAppend() -// -// Substitutes variables into a given format string and appends to a given -// output string. See file comments above for usage. -// -// The declarations of `SubstituteAndAppend()` below consist of overloads -// for passing 0 to 10 arguments, respectively. -// -// NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic -// templates to allow a variable number of arguments. -// -// Example: -// template <typename... Args> -// void VarMsg(std::string* boilerplate, absl::string_view format, -// const Args&... args) { -// absl::SubstituteAndAppend(boilerplate, format, args...); -// } -// -inline void SubstituteAndAppend(std::string* output, absl::string_view format) { - substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0) { - const absl::string_view args[] = {a0.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1) { - const absl::string_view args[] = {a0.piece(), a1.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2) { - const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3) { - const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view 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 absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece(), a4.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view 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 absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece(), a4.piece(), a5.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6) { - const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece(), a4.piece(), a5.piece(), - a6.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend( - std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) { - const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece(), a4.piece(), a5.piece(), - a6.piece(), a7.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend( - std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6, const substitute_internal::Arg& a7, - const substitute_internal::Arg& a8) { - const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), - a3.piece(), a4.piece(), a5.piece(), - a6.piece(), a7.piece(), a8.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -inline void SubstituteAndAppend( - std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6, const substitute_internal::Arg& a7, - const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) { - const absl::string_view args[] = { - a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(), - a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()}; - substitute_internal::SubstituteAndAppendArray(output, format, args, - ABSL_ARRAYSIZE(args)); -} - -#if defined(ABSL_BAD_CALL_IF) -// 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 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 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 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 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 either missing its $0-$3, or " - "contains one of $4-$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) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31, - "There were 5 substitution arguments given, but " - "this format 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, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63, - "There were 6 substitution arguments given, but " - "this format 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 either missing its $0-$6, or " - "contains one of $7-$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, - 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 either missing its $0-$7, or " - "contains one of $8-$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, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) - ABSL_BAD_CALL_IF( - substitute_internal::PlaceholderBitmask(format) != 511, - "There were 9 substitution arguments given, but " - "this format string is either missing its $0-$8, or contains a $9"); - -void SubstituteAndAppend( - std::string* output, const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& 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 doesn't contain all of $0 through $9"); -#endif // ABSL_BAD_CALL_IF - -// Substitute() -// -// Substitutes variables into a given format string. See file comments above -// for usage. -// -// The declarations of `Substitute()` below consist of overloads for passing 0 -// to 10 arguments, respectively. -// -// NOTE: A zero-argument `Substitute()` may be used within variadic templates to -// allow a variable number of arguments. -// -// Example: -// template <typename... Args> -// void VarMsg(absl::string_view format, const Args&... args) { -// std::string s = absl::Substitute(format, args...); - -ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) { - std::string result; - SubstituteAndAppend(&result, format); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0) { - std::string result; - SubstituteAndAppend(&result, format, a0); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view 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) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view 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) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view 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) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8); - return result; -} - -ABSL_MUST_USE_RESULT inline std::string Substitute( - absl::string_view format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8, - const substitute_internal::Arg& a9) { - std::string result; - SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); - return result; -} - -#if defined(ABSL_BAD_CALL_IF) -// This body of functions catches cases where the number of placeholders -// doesn't match the number of data arguments. -std::string Substitute(const char* format) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0, - "There were no substitution arguments " - "but this format string has a $[0-9] in it"); - -std::string Substitute(const char* format, const substitute_internal::Arg& a0) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1, - "There was 1 substitution argument given, but " - "this format 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 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 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 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 either missing its $0-$4, or " - "contains one of $5-$9"); - -std::string Substitute(const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63, - "There were 6 substitution arguments given, but " - "this format string is either missing its $0-$5, or " - "contains one of $6-$9"); - -std::string Substitute(const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127, - "There were 7 substitution arguments given, but " - "this format string is either missing its $0-$6, or " - "contains one of $7-$9"); - -std::string Substitute(const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7) - ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255, - "There were 8 substitution arguments given, but " - "this format string is either missing its $0-$7, or " - "contains one of $8-$9"); - -std::string Substitute( - const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) - ABSL_BAD_CALL_IF( - substitute_internal::PlaceholderBitmask(format) != 511, - "There were 9 substitution arguments given, but " - "this format string is either missing its $0-$8, or contains a $9"); - -std::string Substitute( - const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& 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 doesn't contain all of $0 through $9"); -#endif // ABSL_BAD_CALL_IF - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_SUBSTITUTE_H_ diff --git a/third_party/abseil_cpp/absl/strings/substitute_test.cc b/third_party/abseil_cpp/absl/strings/substitute_test.cc deleted file mode 100644 index 442c921528d8..000000000000 --- a/third_party/abseil_cpp/absl/strings/substitute_test.cc +++ /dev/null @@ -1,204 +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/strings/substitute.h" - -#include <cstdint> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" - -namespace { - -TEST(SubstituteTest, Substitute) { - // Basic. - EXPECT_EQ("Hello, world!", absl::Substitute("$0, $1!", "Hello", "world")); - - // Non-char* types. - EXPECT_EQ("123 0.2 0.1 foo true false x", - absl::Substitute("$0 $1 $2 $3 $4 $5 $6", 123, 0.2, 0.1f, - std::string("foo"), true, false, 'x')); - - // All int types. - EXPECT_EQ( - "-32767 65535 " - "-1234567890 3234567890 " - "-1234567890 3234567890 " - "-1234567890123456789 9234567890123456789", - absl::Substitute( - "$0 $1 $2 $3 $4 $5 $6 $7", - static_cast<short>(-32767), // NOLINT(runtime/int) - static_cast<unsigned short>(65535), // NOLINT(runtime/int) - -1234567890, 3234567890U, -1234567890L, 3234567890UL, - -int64_t{1234567890123456789}, uint64_t{9234567890123456789u})); - - // Hex format - EXPECT_EQ("0 1 f ffff0ffff 0123456789abcdef", - absl::Substitute("$0$1$2$3$4 $5", // - absl::Hex(0), absl::Hex(1, absl::kSpacePad2), - absl::Hex(0xf, absl::kSpacePad2), - absl::Hex(int16_t{-1}, absl::kSpacePad5), - absl::Hex(int16_t{-1}, absl::kZeroPad5), - absl::Hex(0x123456789abcdef, absl::kZeroPad16))); - - // Dec format - EXPECT_EQ("0 115 -1-0001 81985529216486895", - absl::Substitute("$0$1$2$3$4 $5", // - absl::Dec(0), absl::Dec(1, absl::kSpacePad2), - absl::Dec(0xf, absl::kSpacePad2), - absl::Dec(int16_t{-1}, absl::kSpacePad5), - absl::Dec(int16_t{-1}, absl::kZeroPad5), - absl::Dec(0x123456789abcdef, absl::kZeroPad16))); - - // Pointer. - const int* int_p = reinterpret_cast<const int*>(0x12345); - std::string str = absl::Substitute("$0", int_p); - EXPECT_EQ(absl::StrCat("0x", absl::Hex(int_p)), str); - - // Volatile Pointer. - // Like C++ streamed I/O, such pointers implicitly become bool - volatile int vol = 237; - volatile int *volatile volptr = &vol; - str = absl::Substitute("$0", volptr); - EXPECT_EQ("true", str); - - // null is special. StrCat prints 0x0. Substitute prints NULL. - const uint64_t* null_p = nullptr; - str = absl::Substitute("$0", null_p); - EXPECT_EQ("NULL", str); - - // char* is also special. - const char* char_p = "print me"; - str = absl::Substitute("$0", char_p); - EXPECT_EQ("print me", str); - - char char_buf[16]; - strncpy(char_buf, "print me too", sizeof(char_buf)); - str = absl::Substitute("$0", char_buf); - EXPECT_EQ("print me too", str); - - // null char* is "doubly" special. Represented as the empty string. - char_p = nullptr; - str = absl::Substitute("$0", char_p); - EXPECT_EQ("", str); - - // Out-of-order. - EXPECT_EQ("b, a, c, b", absl::Substitute("$1, $0, $2, $1", "a", "b", "c")); - - // Literal $ - EXPECT_EQ("$", absl::Substitute("$$")); - - EXPECT_EQ("$1", absl::Substitute("$$1")); - - // Test all overloads. - EXPECT_EQ("a", absl::Substitute("$0", "a")); - EXPECT_EQ("a b", absl::Substitute("$0 $1", "a", "b")); - EXPECT_EQ("a b c", absl::Substitute("$0 $1 $2", "a", "b", "c")); - EXPECT_EQ("a b c d", absl::Substitute("$0 $1 $2 $3", "a", "b", "c", "d")); - EXPECT_EQ("a b c d e", - absl::Substitute("$0 $1 $2 $3 $4", "a", "b", "c", "d", "e")); - EXPECT_EQ("a b c d e f", absl::Substitute("$0 $1 $2 $3 $4 $5", "a", "b", "c", - "d", "e", "f")); - EXPECT_EQ("a b c d e f g", absl::Substitute("$0 $1 $2 $3 $4 $5 $6", "a", "b", - "c", "d", "e", "f", "g")); - EXPECT_EQ("a b c d e f g h", - absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7", "a", "b", "c", "d", "e", - "f", "g", "h")); - EXPECT_EQ("a b c d e f g h i", - absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8", "a", "b", "c", "d", - "e", "f", "g", "h", "i")); - EXPECT_EQ("a b c d e f g h i j", - absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9", "a", "b", "c", - "d", "e", "f", "g", "h", "i", "j")); - EXPECT_EQ("a b c d e f g h i j b0", - absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10", "a", "b", "c", - "d", "e", "f", "g", "h", "i", "j")); - - const char* null_cstring = nullptr; - EXPECT_EQ("Text: ''", absl::Substitute("Text: '$0'", null_cstring)); -} - -TEST(SubstituteTest, SubstituteAndAppend) { - std::string str = "Hello"; - absl::SubstituteAndAppend(&str, ", $0!", "world"); - EXPECT_EQ("Hello, world!", str); - - // Test all overloads. - str.clear(); - absl::SubstituteAndAppend(&str, "$0", "a"); - EXPECT_EQ("a", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1", "a", "b"); - EXPECT_EQ("a b", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2", "a", "b", "c"); - EXPECT_EQ("a b c", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3", "a", "b", "c", "d"); - EXPECT_EQ("a b c d", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4", "a", "b", "c", "d", "e"); - EXPECT_EQ("a b c d e", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5", "a", "b", "c", "d", "e", - "f"); - EXPECT_EQ("a b c d e f", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6", "a", "b", "c", "d", - "e", "f", "g"); - EXPECT_EQ("a b c d e f g", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7", "a", "b", "c", "d", - "e", "f", "g", "h"); - EXPECT_EQ("a b c d e f g h", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7 $8", "a", "b", "c", - "d", "e", "f", "g", "h", "i"); - EXPECT_EQ("a b c d e f g h i", str); - str.clear(); - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7 $8 $9", "a", "b", - "c", "d", "e", "f", "g", "h", "i", "j"); - EXPECT_EQ("a b c d e f g h i j", str); -} - -TEST(SubstituteTest, VectorBoolRef) { - std::vector<bool> v = {true, false}; - const auto& cv = v; - EXPECT_EQ("true false true false", - absl::Substitute("$0 $1 $2 $3", v[0], v[1], cv[0], cv[1])); - - std::string str = "Logic be like: "; - absl::SubstituteAndAppend(&str, "$0 $1 $2 $3", v[0], v[1], cv[0], cv[1]); - EXPECT_EQ("Logic be like: true false true false", str); -} - -#ifdef GTEST_HAS_DEATH_TEST - -TEST(SubstituteDeathTest, SubstituteDeath) { - EXPECT_DEBUG_DEATH( - static_cast<void>(absl::Substitute(absl::string_view("-$2"), "a", "b")), - "Invalid absl::Substitute\\(\\) format 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-\""); - EXPECT_DEBUG_DEATH( - static_cast<void>(absl::Substitute(absl::string_view("-$"))), - "Invalid absl::Substitute\\(\\) format string: \"-\\$\""); -} - -#endif // GTEST_HAS_DEATH_TEST - -} // namespace diff --git a/third_party/abseil_cpp/absl/synchronization/BUILD.bazel b/third_party/abseil_cpp/absl/synchronization/BUILD.bazel deleted file mode 100644 index cd4009a15739..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/BUILD.bazel +++ /dev/null @@ -1,288 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -# Internal data structure for efficiently detecting mutex dependency cycles -cc_library( - name = "graphcycles_internal", - srcs = [ - "internal/graphcycles.cc", - ], - hdrs = [ - "internal/graphcycles.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - "//absl/base", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:malloc_internal", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "kernel_timeout_internal", - hdrs = ["internal/kernel_timeout.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/synchronization:__pkg__", - ], - deps = [ - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/time", - ], -) - -cc_library( - name = "synchronization", - srcs = [ - "barrier.cc", - "blocking_counter.cc", - "internal/create_thread_identity.cc", - "internal/per_thread_sem.cc", - "internal/waiter.cc", - "mutex.cc", - "notification.cc", - ], - hdrs = [ - "barrier.h", - "blocking_counter.h", - "internal/create_thread_identity.h", - "internal/futex.h", - "internal/per_thread_sem.h", - "internal/waiter.h", - "mutex.h", - "notification.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = select({ - "//absl:windows": [], - "//absl:wasm": [], - "//conditions:default": ["-pthread"], - }) + ABSL_DEFAULT_LINKOPTS, - deps = [ - ":graphcycles_internal", - ":kernel_timeout_internal", - "//absl/base", - "//absl/base:atomic_hook", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:dynamic_annotations", - "//absl/base:malloc_internal", - "//absl/base:raw_logging_internal", - "//absl/debugging:stacktrace", - "//absl/debugging:symbolize", - "//absl/time", - ], -) - -cc_test( - name = "barrier_test", - size = "small", - srcs = ["barrier_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":synchronization", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "blocking_counter_test", - size = "small", - srcs = ["blocking_counter_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":synchronization", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "graphcycles_test", - size = "medium", - srcs = ["internal/graphcycles_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":graphcycles_internal", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "graphcycles_benchmark", - srcs = ["internal/graphcycles_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = [ - "benchmark", - ], - deps = [ - ":graphcycles_internal", - "//absl/base:raw_logging_internal", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_library( - name = "thread_pool", - testonly = 1, - hdrs = ["internal/thread_pool.h"], - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl:__subpackages__", - ], - deps = [ - ":synchronization", - "//absl/base:core_headers", - ], -) - -cc_test( - name = "mutex_test", - size = "large", - srcs = ["mutex_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - shard_count = 25, - deps = [ - ":synchronization", - ":thread_pool", - "//absl/base", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/memory", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "mutex_benchmark_common", - testonly = 1, - srcs = ["mutex_benchmark.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/synchronization:__pkg__", - ], - deps = [ - ":synchronization", - ":thread_pool", - "//absl/base", - "//absl/base:config", - "@com_github_google_benchmark//:benchmark_main", - ], - alwayslink = 1, -) - -cc_binary( - name = "mutex_benchmark", - testonly = 1, - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - ":mutex_benchmark_common", - ], -) - -cc_test( - name = "notification_test", - size = "small", - srcs = ["notification_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":synchronization", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "per_thread_sem_test_common", - testonly = 1, - srcs = ["internal/per_thread_sem_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":synchronization", - "//absl/base", - "//absl/base:config", - "//absl/strings", - "//absl/time", - "@com_google_googletest//:gtest", - ], - alwayslink = 1, -) - -cc_test( - name = "per_thread_sem_test", - size = "medium", - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":per_thread_sem_test_common", - ":synchronization", - "//absl/strings", - "//absl/time", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "lifetime_test", - srcs = [ - "lifetime_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["no_test_ios_x86_64"], - deps = [ - ":synchronization", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - ], -) diff --git a/third_party/abseil_cpp/absl/synchronization/CMakeLists.txt b/third_party/abseil_cpp/absl/synchronization/CMakeLists.txt deleted file mode 100644 index e633d0bf5312..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/CMakeLists.txt +++ /dev/null @@ -1,216 +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. -# - -absl_cc_library( - NAME - graphcycles_internal - HDRS - "internal/graphcycles.h" - SRCS - "internal/graphcycles.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::base_internal - absl::config - absl::core_headers - absl::malloc_internal - absl::raw_logging_internal -) - -absl_cc_library( - NAME - kernel_timeout_internal - HDRS - "internal/kernel_timeout.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::raw_logging_internal - absl::time -) - -absl_cc_library( - NAME - synchronization - HDRS - "barrier.h" - "blocking_counter.h" - "internal/create_thread_identity.h" - "internal/futex.h" - "internal/per_thread_sem.h" - "internal/waiter.h" - "mutex.h" - "notification.h" - SRCS - "barrier.cc" - "blocking_counter.cc" - "internal/create_thread_identity.cc" - "internal/per_thread_sem.cc" - "internal/waiter.cc" - "notification.cc" - "mutex.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::graphcycles_internal - absl::kernel_timeout_internal - absl::atomic_hook - absl::base - absl::base_internal - absl::config - absl::core_headers - absl::dynamic_annotations - absl::malloc_internal - absl::raw_logging_internal - absl::stacktrace - absl::symbolize - absl::time - Threads::Threads - PUBLIC -) - -absl_cc_test( - NAME - barrier_test - SRCS - "barrier_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::time - gmock_main -) - -absl_cc_test( - NAME - blocking_counter_test - SRCS - "blocking_counter_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::time - gmock_main -) - -absl_cc_test( - NAME - graphcycles_test - SRCS - "internal/graphcycles_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::graphcycles_internal - absl::core_headers - absl::raw_logging_internal - gmock_main -) - -absl_cc_library( - NAME - thread_pool - HDRS - "internal/thread_pool.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::synchronization - absl::core_headers - TESTONLY -) - -absl_cc_test( - NAME - mutex_test - SRCS - "mutex_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::thread_pool - absl::base - absl::config - absl::core_headers - absl::memory - absl::raw_logging_internal - absl::time - gmock_main -) - -absl_cc_test( - NAME - notification_test - SRCS - "notification_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::time - gmock_main -) - -absl_cc_library( - NAME - per_thread_sem_test_common - SRCS - "internal/per_thread_sem_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::base - absl::config - absl::strings - absl::time - gmock - TESTONLY -) - -absl_cc_test( - NAME - per_thread_sem_test - SRCS - "internal/per_thread_sem_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::per_thread_sem_test_common - absl::synchronization - absl::strings - absl::time - gmock_main -) - -absl_cc_test( - NAME - lifetime_test - SRCS - "lifetime_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::synchronization - absl::core_headers - absl::raw_logging_internal -) diff --git a/third_party/abseil_cpp/absl/synchronization/barrier.cc b/third_party/abseil_cpp/absl/synchronization/barrier.cc deleted file mode 100644 index 0dfd795e7b5f..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/barrier.cc +++ /dev/null @@ -1,52 +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/synchronization/barrier.h" - -#include "absl/base/internal/raw_logging.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Return whether int *arg is zero. -static bool IsZero(void *arg) { - return 0 == *reinterpret_cast<int *>(arg); -} - -bool Barrier::Block() { - MutexLock l(&this->lock_); - - this->num_to_block_--; - if (this->num_to_block_ < 0) { - ABSL_RAW_LOG( - FATAL, - "Block() called too many times. num_to_block_=%d out of total=%d", - this->num_to_block_, this->num_to_exit_); - } - - this->lock_.Await(Condition(IsZero, &this->num_to_block_)); - - // Determine which thread can safely delete this Barrier object - this->num_to_exit_--; - ABSL_RAW_CHECK(this->num_to_exit_ >= 0, "barrier underflow"); - - // If num_to_exit_ == 0 then all other threads in the barrier have - // exited the Wait() and have released the Mutex so this thread is - // free to delete the barrier. - return this->num_to_exit_ == 0; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/barrier.h b/third_party/abseil_cpp/absl/synchronization/barrier.h deleted file mode 100644 index d8e754406f4b..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/barrier.h +++ /dev/null @@ -1,79 +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. -// -// ----------------------------------------------------------------------------- -// barrier.h -// ----------------------------------------------------------------------------- - -#ifndef ABSL_SYNCHRONIZATION_BARRIER_H_ -#define ABSL_SYNCHRONIZATION_BARRIER_H_ - -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Barrier -// -// This class creates a barrier which blocks threads until a prespecified -// threshold of threads (`num_threads`) utilizes the barrier. A thread utilizes -// the `Barrier` by calling `Block()` on the barrier, which will block that -// thread; no call to `Block()` will return until `num_threads` threads have -// called it. -// -// Exactly one call to `Block()` will return `true`, which is then responsible -// for destroying the barrier; because stack allocation will cause the barrier -// to be deleted when it is out of scope, barriers should not be stack -// allocated. -// -// Example: -// -// // Main thread creates a `Barrier`: -// barrier = new Barrier(num_threads); -// -// // Each participating thread could then call: -// if (barrier->Block()) delete barrier; // Exactly one call to `Block()` -// // returns `true`; that call -// // deletes the barrier. -class Barrier { - public: - // `num_threads` is the number of threads that will participate in the barrier - explicit Barrier(int num_threads) - : num_to_block_(num_threads), num_to_exit_(num_threads) {} - - Barrier(const Barrier&) = delete; - Barrier& operator=(const Barrier&) = delete; - - // Barrier::Block() - // - // Blocks the current thread, and returns only when the `num_threads` - // threshold of threads utilizing this barrier has been reached. `Block()` - // returns `true` for precisely one caller, which may then destroy the - // barrier. - // - // Memory ordering: For any threads X and Y, any action taken by X - // before X calls `Block()` will be visible to Y after Y returns from - // `Block()`. - bool Block(); - - private: - Mutex lock_; - int num_to_block_ ABSL_GUARDED_BY(lock_); - int num_to_exit_ ABSL_GUARDED_BY(lock_); -}; - -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_SYNCHRONIZATION_BARRIER_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/barrier_test.cc b/third_party/abseil_cpp/absl/synchronization/barrier_test.cc deleted file mode 100644 index bfc6cb1883b1..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/barrier_test.cc +++ /dev/null @@ -1,75 +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/synchronization/barrier.h" - -#include <thread> // NOLINT(build/c++11) -#include <vector> - -#include "gtest/gtest.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/clock.h" - - -TEST(Barrier, SanityTest) { - constexpr int kNumThreads = 10; - absl::Barrier* barrier = new absl::Barrier(kNumThreads); - - absl::Mutex mutex; - int counter = 0; // Guarded by mutex. - - auto thread_func = [&] { - if (barrier->Block()) { - // This thread is the last thread to reach the barrier so it is - // responsible for deleting it. - delete barrier; - } - - // Increment the counter. - absl::MutexLock lock(&mutex); - ++counter; - }; - - // Start (kNumThreads - 1) threads running thread_func. - std::vector<std::thread> threads; - for (int i = 0; i < kNumThreads - 1; ++i) { - threads.push_back(std::thread(thread_func)); - } - - // Give (kNumThreads - 1) threads a chance to reach the barrier. - // This test assumes at least one thread will have run after the - // sleep has elapsed. Sleeping in a test is usually bad form, but we - // need to make sure that we are testing the barrier instead of some - // other synchronization method. - absl::SleepFor(absl::Seconds(1)); - - // The counter should still be zero since no thread should have - // been able to pass the barrier yet. - { - absl::MutexLock lock(&mutex); - EXPECT_EQ(counter, 0); - } - - // Start 1 more thread. This should make all threads pass the barrier. - threads.push_back(std::thread(thread_func)); - - // All threads should now be able to proceed and finish. - for (auto& thread : threads) { - thread.join(); - } - - // All threads should now have incremented the counter. - absl::MutexLock lock(&mutex); - EXPECT_EQ(counter, kNumThreads); -} diff --git a/third_party/abseil_cpp/absl/synchronization/blocking_counter.cc b/third_party/abseil_cpp/absl/synchronization/blocking_counter.cc deleted file mode 100644 index 3cea7aed2441..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/blocking_counter.cc +++ /dev/null @@ -1,57 +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/synchronization/blocking_counter.h" - -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Return whether int *arg is zero. -static bool IsZero(void *arg) { - return 0 == *reinterpret_cast<int *>(arg); -} - -bool BlockingCounter::DecrementCount() { - MutexLock l(&lock_); - count_--; - if (count_ < 0) { - ABSL_RAW_LOG( - FATAL, - "BlockingCounter::DecrementCount() called too many times. count=%d", - count_); - } - 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(IsZero, &this->count_)); - - // 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. -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/blocking_counter.h b/third_party/abseil_cpp/absl/synchronization/blocking_counter.h deleted file mode 100644 index 1f53f9f24045..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/blocking_counter.h +++ /dev/null @@ -1,99 +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. -// -// ----------------------------------------------------------------------------- -// blocking_counter.h -// ----------------------------------------------------------------------------- - -#ifndef ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ -#define ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ - -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// BlockingCounter -// -// This class allows a thread to block for a pre-specified number of actions. -// `BlockingCounter` maintains a single non-negative abstract integer "count" -// with an initial value `initial_count`. A thread can then call `Wait()` on -// this blocking counter to block until the specified number of events occur; -// worker threads then call 'DecrementCount()` on the counter upon completion of -// their work. Once the counter's internal "count" reaches zero, the blocked -// thread unblocks. -// -// A `BlockingCounter` requires the following: -// - its `initial_count` is non-negative. -// - the number of calls to `DecrementCount()` on it is at most -// `initial_count`. -// - `Wait()` is called at most once on it. -// -// Given the above requirements, a `BlockingCounter` provides the following -// guarantees: -// - Once its internal "count" reaches zero, no legal action on the object -// can further change the value of "count". -// - When `Wait()` returns, it is legal to destroy the `BlockingCounter`. -// - When `Wait()` returns, the number of calls to `DecrementCount()` on -// this blocking counter exactly equals `initial_count`. -// -// Example: -// BlockingCounter bcount(N); // there are N items of work -// ... Allow worker threads to start. -// ... On completing each work item, workers do: -// ... bcount.DecrementCount(); // an item of work has been completed -// -// bcount.Wait(); // wait for all work to be complete -// -class BlockingCounter { - public: - explicit BlockingCounter(int initial_count) - : count_(initial_count), num_waiting_(0) {} - - BlockingCounter(const BlockingCounter&) = delete; - BlockingCounter& operator=(const BlockingCounter&) = delete; - - // BlockingCounter::DecrementCount() - // - // Decrements the counter's "count" by one, and return "count == 0". This - // function requires that "count != 0" when it is called. - // - // Memory ordering: For any threads X and Y, any action taken by X - // before it calls `DecrementCount()` is visible to thread Y after - // Y's call to `DecrementCount()`, provided Y's call returns `true`. - bool DecrementCount(); - - // BlockingCounter::Wait() - // - // Blocks until the counter reaches zero. This function may be called at most - // once. On return, `DecrementCount()` will have been called "initial_count" - // times and the blocking counter may be destroyed. - // - // Memory ordering: For any threads X and Y, any action taken by X - // before X calls `DecrementCount()` is visible to Y after Y returns - // from `Wait()`. - void Wait(); - - private: - Mutex lock_; - int count_ ABSL_GUARDED_BY(lock_); - int num_waiting_ ABSL_GUARDED_BY(lock_); -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/blocking_counter_test.cc b/third_party/abseil_cpp/absl/synchronization/blocking_counter_test.cc deleted file mode 100644 index 2926224af750..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/blocking_counter_test.cc +++ /dev/null @@ -1,68 +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/synchronization/blocking_counter.h" - -#include <thread> // NOLINT(build/c++11) -#include <vector> - -#include "gtest/gtest.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -void PauseAndDecreaseCounter(BlockingCounter* counter, int* done) { - absl::SleepFor(absl::Seconds(1)); - *done = 1; - counter->DecrementCount(); -} - -TEST(BlockingCounterTest, BasicFunctionality) { - // This test verifies that BlockingCounter functions correctly. Starts a - // number of threads that just sleep for a second and decrement a counter. - - // Initialize the counter. - const int num_workers = 10; - BlockingCounter counter(num_workers); - - std::vector<std::thread> workers; - std::vector<int> done(num_workers, 0); - - // Start a number of parallel tasks that will just wait for a seconds and - // then decrement the count. - workers.reserve(num_workers); - for (int k = 0; k < num_workers; k++) { - workers.emplace_back( - [&counter, &done, k] { PauseAndDecreaseCounter(&counter, &done[k]); }); - } - - // Wait for the threads to have all finished. - counter.Wait(); - - // Check that all the workers have completed. - for (int k = 0; k < num_workers; k++) { - EXPECT_EQ(1, done[k]); - } - - for (std::thread& w : workers) { - w.join(); - } -} - -} // 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 deleted file mode 100644 index 53a71b342b9f..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/create_thread_identity.cc +++ /dev/null @@ -1,140 +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 <stdint.h> -#include <new> - -// This file is a no-op if the required LowLevelAlloc support is missing. -#include "absl/base/internal/low_level_alloc.h" -#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING - -#include <string.h> - -#include "absl/base/attributes.h" -#include "absl/base/internal/spinlock.h" -#include "absl/base/internal/thread_identity.h" -#include "absl/synchronization/internal/per_thread_sem.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// ThreadIdentity storage is persistent, we maintain a free-list of previously -// released ThreadIdentity objects. -ABSL_CONST_INIT static base_internal::SpinLock freelist_lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); -ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist; - -// A per-thread destructor for reclaiming associated ThreadIdentity objects. -// Since we must preserve their storage we cache them for re-use. -void ReclaimThreadIdentity(void* v) { - base_internal::ThreadIdentity* identity = - static_cast<base_internal::ThreadIdentity*>(v); - - // all_locks might have been allocated by the Mutex implementation. - // We free it here when we are notified that our thread is dying. - if (identity->per_thread_synch.all_locks != nullptr) { - base_internal::LowLevelAlloc::Free(identity->per_thread_synch.all_locks); - } - - PerThreadSem::Destroy(identity); - - // We must explicitly clear the current thread's identity: - // (a) Subsequent (unrelated) per-thread destructors may require an identity. - // We must guarantee a new identity is used in this case (this instructor - // will be reinvoked up to PTHREAD_DESTRUCTOR_ITERATIONS in this case). - // (b) ThreadIdentity implementations may depend on memory that is not - // reinitialized before reuse. We must allow explicit clearing of the - // association state in this case. - base_internal::ClearCurrentThreadIdentity(); - { - base_internal::SpinLockHolder l(&freelist_lock); - identity->next = thread_identity_freelist; - thread_identity_freelist = identity; - } -} - -// Return value rounded up to next multiple of align. -// Align must be a power of two. -static intptr_t RoundUp(intptr_t addr, intptr_t align) { - return (addr + align - 1) & ~(align - 1); -} - -static void ResetThreadIdentity(base_internal::ThreadIdentity* identity) { - base_internal::PerThreadSynch* pts = &identity->per_thread_synch; - pts->next = nullptr; - pts->skip = nullptr; - pts->may_skip = false; - pts->waitp = nullptr; - pts->suppress_fatal_errors = false; - pts->readers = 0; - pts->priority = 0; - pts->next_priority_read_cycles = 0; - pts->state.store(base_internal::PerThreadSynch::State::kAvailable, - std::memory_order_relaxed); - pts->maybe_unlocking = false; - pts->wake = false; - pts->cond_waiter = false; - pts->all_locks = nullptr; - identity->blocked_count_ptr = nullptr; - identity->ticker.store(0, std::memory_order_relaxed); - identity->wait_start.store(0, std::memory_order_relaxed); - identity->is_idle.store(false, std::memory_order_relaxed); - identity->next = nullptr; -} - -static base_internal::ThreadIdentity* NewThreadIdentity() { - base_internal::ThreadIdentity* identity = nullptr; - - { - // Re-use a previously released object if possible. - base_internal::SpinLockHolder l(&freelist_lock); - if (thread_identity_freelist) { - identity = thread_identity_freelist; // Take list-head. - thread_identity_freelist = thread_identity_freelist->next; - } - } - - if (identity == nullptr) { - // Allocate enough space to align ThreadIdentity to a multiple of - // PerThreadSynch::kAlignment. This space is never released (it is - // added to a freelist by ReclaimThreadIdentity instead). - void* allocation = base_internal::LowLevelAlloc::Alloc( - sizeof(*identity) + base_internal::PerThreadSynch::kAlignment - 1); - // Round up the address to the required alignment. - identity = reinterpret_cast<base_internal::ThreadIdentity*>( - RoundUp(reinterpret_cast<intptr_t>(allocation), - base_internal::PerThreadSynch::kAlignment)); - } - ResetThreadIdentity(identity); - - return identity; -} - -// Allocates and attaches ThreadIdentity object for the calling thread. Returns -// the new identity. -// REQUIRES: CurrentThreadIdentity(false) == nullptr -base_internal::ThreadIdentity* CreateThreadIdentity() { - base_internal::ThreadIdentity* identity = NewThreadIdentity(); - PerThreadSem::Init(identity); - // Associate the value with the current thread, and attach our destructor. - base_internal::SetCurrentThreadIdentity(identity, ReclaimThreadIdentity); - return identity; -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/third_party/abseil_cpp/absl/synchronization/internal/create_thread_identity.h b/third_party/abseil_cpp/absl/synchronization/internal/create_thread_identity.h deleted file mode 100644 index e121f68377b1..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/create_thread_identity.h +++ /dev/null @@ -1,60 +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. - */ - -// Interface for getting the current ThreadIdentity, creating one if necessary. -// See thread_identity.h. -// -// This file is separate from thread_identity.h because creating a new -// ThreadIdentity requires slightly higher level libraries (per_thread_sem -// and low_level_alloc) than accessing an existing one. This separation allows -// us to have a smaller //absl/base:base. - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ - -#include "absl/base/internal/thread_identity.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// Allocates and attaches a ThreadIdentity object for the calling thread. -// For private use only. -base_internal::ThreadIdentity* CreateThreadIdentity(); - -// A per-thread destructor for reclaiming associated ThreadIdentity objects. -// For private use only. -void ReclaimThreadIdentity(void* v); - -// Returns the ThreadIdentity object representing the calling thread; guaranteed -// to be unique for its lifetime. The returned object will remain valid for the -// program's lifetime; although it may be re-assigned to a subsequent thread. -// If one does not exist for the calling thread, allocate it now. -inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() { - base_internal::ThreadIdentity* identity = - base_internal::CurrentThreadIdentityIfPresent(); - if (ABSL_PREDICT_FALSE(identity == nullptr)) { - return CreateThreadIdentity(); - } - return identity; -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ 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 06fbd6d072d1..000000000000 --- 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 deleted file mode 100644 index 27fec21681dc..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles.cc +++ /dev/null @@ -1,698 +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. - -// GraphCycles provides incremental cycle detection on a dynamic -// graph using the following algorithm: -// -// A dynamic topological sort algorithm for directed acyclic graphs -// David J. Pearce, Paul H. J. Kelly -// Journal of Experimental Algorithmics (JEA) JEA Homepage archive -// Volume 11, 2006, Article No. 1.7 -// -// Brief summary of the algorithm: -// -// (1) Maintain a rank for each node that is consistent -// with the topological sort of the graph. I.e., path from x to y -// implies rank[x] < rank[y]. -// (2) When a new edge (x->y) is inserted, do nothing if rank[x] < rank[y]. -// (3) Otherwise: adjust ranks in the neighborhood of x and y. - -#include "absl/base/attributes.h" -// This file is a no-op if the required LowLevelAlloc support is missing. -#include "absl/base/internal/low_level_alloc.h" -#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING - -#include "absl/synchronization/internal/graphcycles.h" - -#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" - -// Do not use STL. This module does not use standard memory allocation. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -namespace { - -// Avoid LowLevelAlloc's default arena since it calls malloc hooks in -// which people are doing things like acquiring Mutexes. -ABSL_CONST_INIT static absl::base_internal::SpinLock arena_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); -ABSL_CONST_INIT static base_internal::LowLevelAlloc::Arena* arena; - -static void InitArenaIfNecessary() { - arena_mu.Lock(); - if (arena == nullptr) { - arena = base_internal::LowLevelAlloc::NewArena(0); - } - arena_mu.Unlock(); -} - -// Number of inlined elements in Vec. Hash table implementation -// relies on this being a power of two. -static const uint32_t kInline = 8; - -// A simple LowLevelAlloc based resizable vector with inlined storage -// for a few elements. T must be a plain type since constructor -// and destructor are not run on elements of type T managed by Vec. -template <typename T> -class Vec { - public: - Vec() { Init(); } - ~Vec() { Discard(); } - - void clear() { - Discard(); - Init(); - } - - bool empty() const { return size_ == 0; } - uint32_t size() const { return size_; } - T* begin() { return ptr_; } - T* end() { return ptr_ + size_; } - const T& operator[](uint32_t i) const { return ptr_[i]; } - T& operator[](uint32_t i) { return ptr_[i]; } - const T& back() const { return ptr_[size_-1]; } - void pop_back() { size_--; } - - void push_back(const T& v) { - if (size_ == capacity_) Grow(size_ + 1); - ptr_[size_] = v; - size_++; - } - - void resize(uint32_t n) { - if (n > capacity_) Grow(n); - size_ = n; - } - - void fill(const T& val) { - for (uint32_t i = 0; i < size(); i++) { - ptr_[i] = val; - } - } - - // Guarantees src is empty at end. - // Provided for the hash table resizing code below. - void MoveFrom(Vec<T>* src) { - if (src->ptr_ == src->space_) { - // Need to actually copy - resize(src->size_); - std::copy(src->ptr_, src->ptr_ + src->size_, ptr_); - src->size_ = 0; - } else { - Discard(); - ptr_ = src->ptr_; - size_ = src->size_; - capacity_ = src->capacity_; - src->Init(); - } - } - - private: - T* ptr_; - T space_[kInline]; - uint32_t size_; - uint32_t capacity_; - - void Init() { - ptr_ = space_; - size_ = 0; - capacity_ = kInline; - } - - void Discard() { - if (ptr_ != space_) base_internal::LowLevelAlloc::Free(ptr_); - } - - void Grow(uint32_t n) { - while (capacity_ < n) { - capacity_ *= 2; - } - size_t request = static_cast<size_t>(capacity_) * sizeof(T); - T* copy = static_cast<T*>( - base_internal::LowLevelAlloc::AllocWithArena(request, arena)); - std::copy(ptr_, ptr_ + size_, copy); - Discard(); - ptr_ = copy; - } - - Vec(const Vec&) = delete; - Vec& operator=(const Vec&) = delete; -}; - -// A hash set of non-negative int32_t that uses Vec for its underlying storage. -class NodeSet { - public: - NodeSet() { Init(); } - - void clear() { Init(); } - bool contains(int32_t v) const { return table_[FindIndex(v)] == v; } - - bool insert(int32_t v) { - uint32_t i = FindIndex(v); - if (table_[i] == v) { - return false; - } - if (table_[i] == kEmpty) { - // Only inserting over an empty cell increases the number of occupied - // slots. - occupied_++; - } - table_[i] = v; - // Double when 75% full. - if (occupied_ >= table_.size() - table_.size()/4) Grow(); - return true; - } - - void erase(uint32_t v) { - uint32_t i = FindIndex(v); - if (static_cast<uint32_t>(table_[i]) == v) { - table_[i] = kDel; - } - } - - // Iteration: is done via HASH_FOR_EACH - // Example: - // HASH_FOR_EACH(elem, node->out) { ... } -#define HASH_FOR_EACH(elem, eset) \ - for (int32_t elem, _cursor = 0; (eset).Next(&_cursor, &elem); ) - bool Next(int32_t* cursor, int32_t* elem) { - while (static_cast<uint32_t>(*cursor) < table_.size()) { - int32_t v = table_[*cursor]; - (*cursor)++; - if (v >= 0) { - *elem = v; - return true; - } - } - return false; - } - - private: - enum : int32_t { kEmpty = -1, kDel = -2 }; - Vec<int32_t> table_; - uint32_t occupied_; // Count of non-empty slots (includes deleted slots) - - static uint32_t Hash(uint32_t a) { return a * 41; } - - // Return index for storing v. May return an empty index or deleted index - int FindIndex(int32_t v) const { - // Search starting at hash index. - const uint32_t mask = table_.size() - 1; - uint32_t i = Hash(v) & mask; - int deleted_index = -1; // If >= 0, index of first deleted element we see - while (true) { - int32_t e = table_[i]; - if (v == e) { - return i; - } else if (e == kEmpty) { - // Return any previously encountered deleted slot. - return (deleted_index >= 0) ? deleted_index : i; - } else if (e == kDel && deleted_index < 0) { - // Keep searching since v might be present later. - deleted_index = i; - } - i = (i + 1) & mask; // Linear probing; quadratic is slightly slower. - } - } - - void Init() { - table_.clear(); - table_.resize(kInline); - table_.fill(kEmpty); - occupied_ = 0; - } - - void Grow() { - Vec<int32_t> copy; - copy.MoveFrom(&table_); - occupied_ = 0; - table_.resize(copy.size() * 2); - table_.fill(kEmpty); - - for (const auto& e : copy) { - if (e >= 0) insert(e); - } - } - - NodeSet(const NodeSet&) = delete; - NodeSet& operator=(const NodeSet&) = delete; -}; - -// We encode a node index and a node version in GraphId. The version -// number is incremented when the GraphId is freed which automatically -// invalidates all copies of the GraphId. - -inline GraphId MakeId(int32_t index, uint32_t version) { - GraphId g; - g.handle = - (static_cast<uint64_t>(version) << 32) | static_cast<uint32_t>(index); - return g; -} - -inline int32_t NodeIndex(GraphId id) { - return static_cast<uint32_t>(id.handle & 0xfffffffful); -} - -inline uint32_t NodeVersion(GraphId id) { - return static_cast<uint32_t>(id.handle >> 32); -} - -struct Node { - int32_t rank; // rank number assigned by Pearce-Kelly algorithm - uint32_t version; // Current version number - int32_t next_hash; // Next entry in hash table - bool visited; // Temporary marker used by depth-first-search - uintptr_t masked_ptr; // User-supplied pointer - NodeSet in; // List of immediate predecessor nodes in graph - NodeSet out; // List of immediate successor nodes in graph - int priority; // Priority of recorded stack trace. - int nstack; // Depth of recorded stack trace. - void* stack[40]; // stack[0,nstack-1] holds stack trace for node. -}; - -// Hash table for pointer to node index lookups. -class PointerMap { - public: - explicit PointerMap(const Vec<Node*>* nodes) : nodes_(nodes) { - table_.fill(-1); - } - - int32_t Find(void* ptr) { - auto masked = base_internal::HidePtr(ptr); - for (int32_t i = table_[Hash(ptr)]; i != -1;) { - Node* n = (*nodes_)[i]; - if (n->masked_ptr == masked) return i; - i = n->next_hash; - } - return -1; - } - - void Add(void* ptr, int32_t i) { - int32_t* head = &table_[Hash(ptr)]; - (*nodes_)[i]->next_hash = *head; - *head = i; - } - - int32_t Remove(void* ptr) { - // Advance through linked list while keeping track of the - // predecessor slot that points to the current entry. - auto masked = base_internal::HidePtr(ptr); - for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1; ) { - int32_t index = *slot; - Node* n = (*nodes_)[index]; - if (n->masked_ptr == masked) { - *slot = n->next_hash; // Remove n from linked list - n->next_hash = -1; - return index; - } - slot = &n->next_hash; - } - return -1; - } - - private: - // Number of buckets in hash table for pointer lookups. - static constexpr uint32_t kHashTableSize = 8171; // should be prime - - const Vec<Node*>* nodes_; - std::array<int32_t, kHashTableSize> table_; - - static uint32_t Hash(void* ptr) { - return reinterpret_cast<uintptr_t>(ptr) % kHashTableSize; - } -}; - -} // namespace - -struct GraphCycles::Rep { - Vec<Node*> nodes_; - Vec<int32_t> free_nodes_; // Indices for unused entries in nodes_ - PointerMap ptrmap_; - - // Temporary state. - Vec<int32_t> deltaf_; // Results of forward DFS - Vec<int32_t> deltab_; // Results of backward DFS - Vec<int32_t> list_; // All nodes to reprocess - Vec<int32_t> merged_; // Rank values to assign to list_ entries - Vec<int32_t> stack_; // Emulates recursion stack for depth-first searches - - Rep() : ptrmap_(&nodes_) {} -}; - -static Node* FindNode(GraphCycles::Rep* rep, GraphId id) { - Node* n = rep->nodes_[NodeIndex(id)]; - return (n->version == NodeVersion(id)) ? n : nullptr; -} - -GraphCycles::GraphCycles() { - InitArenaIfNecessary(); - rep_ = new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Rep), arena)) - Rep; -} - -GraphCycles::~GraphCycles() { - for (auto* node : rep_->nodes_) { - node->Node::~Node(); - base_internal::LowLevelAlloc::Free(node); - } - rep_->Rep::~Rep(); - base_internal::LowLevelAlloc::Free(rep_); -} - -bool GraphCycles::CheckInvariants() const { - Rep* r = rep_; - NodeSet ranks; // Set of ranks seen so far. - for (uint32_t x = 0; x < r->nodes_.size(); x++) { - Node* nx = r->nodes_[x]; - void* ptr = base_internal::UnhidePtr<void>(nx->masked_ptr); - if (ptr != nullptr && static_cast<uint32_t>(r->ptrmap_.Find(ptr)) != x) { - ABSL_RAW_LOG(FATAL, "Did not find live node in hash table %u %p", x, ptr); - } - if (nx->visited) { - ABSL_RAW_LOG(FATAL, "Did not clear visited marker on node %u", x); - } - if (!ranks.insert(nx->rank)) { - ABSL_RAW_LOG(FATAL, "Duplicate occurrence of rank %d", nx->rank); - } - HASH_FOR_EACH(y, nx->out) { - Node* ny = r->nodes_[y]; - if (nx->rank >= ny->rank) { - ABSL_RAW_LOG(FATAL, "Edge %u->%d has bad rank assignment %d->%d", x, y, - nx->rank, ny->rank); - } - } - } - return true; -} - -GraphId GraphCycles::GetId(void* ptr) { - int32_t i = rep_->ptrmap_.Find(ptr); - if (i != -1) { - return MakeId(i, rep_->nodes_[i]->version); - } else if (rep_->free_nodes_.empty()) { - Node* n = - new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Node), arena)) - Node; - n->version = 1; // Avoid 0 since it is used by InvalidGraphId() - n->visited = false; - n->rank = rep_->nodes_.size(); - n->masked_ptr = base_internal::HidePtr(ptr); - n->nstack = 0; - n->priority = 0; - rep_->nodes_.push_back(n); - rep_->ptrmap_.Add(ptr, n->rank); - return MakeId(n->rank, n->version); - } else { - // Preserve preceding rank since the set of ranks in use must be - // a permutation of [0,rep_->nodes_.size()-1]. - int32_t r = rep_->free_nodes_.back(); - rep_->free_nodes_.pop_back(); - Node* n = rep_->nodes_[r]; - n->masked_ptr = base_internal::HidePtr(ptr); - n->nstack = 0; - n->priority = 0; - rep_->ptrmap_.Add(ptr, r); - return MakeId(r, n->version); - } -} - -void GraphCycles::RemoveNode(void* ptr) { - int32_t i = rep_->ptrmap_.Remove(ptr); - if (i == -1) { - return; - } - Node* x = rep_->nodes_[i]; - HASH_FOR_EACH(y, x->out) { - rep_->nodes_[y]->in.erase(i); - } - HASH_FOR_EACH(y, x->in) { - rep_->nodes_[y]->out.erase(i); - } - x->in.clear(); - x->out.clear(); - x->masked_ptr = base_internal::HidePtr<void>(nullptr); - if (x->version == std::numeric_limits<uint32_t>::max()) { - // Cannot use x any more - } else { - x->version++; // Invalidates all copies of node. - rep_->free_nodes_.push_back(i); - } -} - -void* GraphCycles::Ptr(GraphId id) { - Node* n = FindNode(rep_, id); - return n == nullptr ? nullptr - : base_internal::UnhidePtr<void>(n->masked_ptr); -} - -bool GraphCycles::HasNode(GraphId node) { - return FindNode(rep_, node) != nullptr; -} - -bool GraphCycles::HasEdge(GraphId x, GraphId y) const { - Node* xn = FindNode(rep_, x); - return xn && FindNode(rep_, y) && xn->out.contains(NodeIndex(y)); -} - -void GraphCycles::RemoveEdge(GraphId x, GraphId y) { - Node* xn = FindNode(rep_, x); - Node* yn = FindNode(rep_, y); - if (xn && yn) { - xn->out.erase(NodeIndex(y)); - yn->in.erase(NodeIndex(x)); - // No need to update the rank assignment since a previous valid - // rank assignment remains valid after an edge deletion. - } -} - -static bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound); -static void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound); -static void Reorder(GraphCycles::Rep* r); -static void Sort(const Vec<Node*>&, Vec<int32_t>* delta); -static void MoveToList( - GraphCycles::Rep* r, Vec<int32_t>* src, Vec<int32_t>* dst); - -bool GraphCycles::InsertEdge(GraphId idx, GraphId idy) { - Rep* r = rep_; - const int32_t x = NodeIndex(idx); - const int32_t y = NodeIndex(idy); - Node* nx = FindNode(r, idx); - Node* ny = FindNode(r, idy); - if (nx == nullptr || ny == nullptr) return true; // Expired ids - - if (nx == ny) return false; // Self edge - if (!nx->out.insert(y)) { - // Edge already exists. - return true; - } - - ny->in.insert(x); - - if (nx->rank <= ny->rank) { - // New edge is consistent with existing rank assignment. - return true; - } - - // Current rank assignments are incompatible with the new edge. Recompute. - // We only need to consider nodes that fall in the range [ny->rank,nx->rank]. - if (!ForwardDFS(r, y, nx->rank)) { - // Found a cycle. Undo the insertion and tell caller. - nx->out.erase(y); - ny->in.erase(x); - // Since we do not call Reorder() on this path, clear any visited - // markers left by ForwardDFS. - for (const auto& d : r->deltaf_) { - r->nodes_[d]->visited = false; - } - return false; - } - BackwardDFS(r, x, ny->rank); - Reorder(r); - return true; -} - -static bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound) { - // Avoid recursion since stack space might be limited. - // We instead keep a stack of nodes to visit. - r->deltaf_.clear(); - r->stack_.clear(); - r->stack_.push_back(n); - while (!r->stack_.empty()) { - n = r->stack_.back(); - r->stack_.pop_back(); - Node* nn = r->nodes_[n]; - if (nn->visited) continue; - - nn->visited = true; - r->deltaf_.push_back(n); - - HASH_FOR_EACH(w, nn->out) { - Node* nw = r->nodes_[w]; - if (nw->rank == upper_bound) { - return false; // Cycle - } - if (!nw->visited && nw->rank < upper_bound) { - r->stack_.push_back(w); - } - } - } - return true; -} - -static void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound) { - r->deltab_.clear(); - r->stack_.clear(); - r->stack_.push_back(n); - while (!r->stack_.empty()) { - n = r->stack_.back(); - r->stack_.pop_back(); - Node* nn = r->nodes_[n]; - if (nn->visited) continue; - - nn->visited = true; - r->deltab_.push_back(n); - - HASH_FOR_EACH(w, nn->in) { - Node* nw = r->nodes_[w]; - if (!nw->visited && lower_bound < nw->rank) { - r->stack_.push_back(w); - } - } - } -} - -static void Reorder(GraphCycles::Rep* r) { - Sort(r->nodes_, &r->deltab_); - Sort(r->nodes_, &r->deltaf_); - - // Adds contents of delta lists to list_ (backwards deltas first). - r->list_.clear(); - MoveToList(r, &r->deltab_, &r->list_); - MoveToList(r, &r->deltaf_, &r->list_); - - // Produce sorted list of all ranks that will be reassigned. - r->merged_.resize(r->deltab_.size() + r->deltaf_.size()); - std::merge(r->deltab_.begin(), r->deltab_.end(), - r->deltaf_.begin(), r->deltaf_.end(), - r->merged_.begin()); - - // Assign the ranks in order to the collected list. - for (uint32_t i = 0; i < r->list_.size(); i++) { - r->nodes_[r->list_[i]]->rank = r->merged_[i]; - } -} - -static void Sort(const Vec<Node*>& nodes, Vec<int32_t>* delta) { - struct ByRank { - const Vec<Node*>* nodes; - bool operator()(int32_t a, int32_t b) const { - return (*nodes)[a]->rank < (*nodes)[b]->rank; - } - }; - ByRank cmp; - cmp.nodes = &nodes; - std::sort(delta->begin(), delta->end(), cmp); -} - -static void MoveToList( - GraphCycles::Rep* r, Vec<int32_t>* src, Vec<int32_t>* dst) { - for (auto& v : *src) { - int32_t w = v; - v = r->nodes_[w]->rank; // Replace v entry with its rank - r->nodes_[w]->visited = false; // Prepare for future DFS calls - dst->push_back(w); - } -} - -int GraphCycles::FindPath(GraphId idx, GraphId idy, int max_path_len, - GraphId path[]) const { - Rep* r = rep_; - if (FindNode(r, idx) == nullptr || FindNode(r, idy) == nullptr) return 0; - const int32_t x = NodeIndex(idx); - const int32_t y = NodeIndex(idy); - - // Forward depth first search starting at x until we hit y. - // As we descend into a node, we push it onto the path. - // As we leave a node, we remove it from the path. - int path_len = 0; - - NodeSet seen; - r->stack_.clear(); - r->stack_.push_back(x); - while (!r->stack_.empty()) { - int32_t n = r->stack_.back(); - r->stack_.pop_back(); - if (n < 0) { - // Marker to indicate that we are leaving a node - path_len--; - continue; - } - - if (path_len < max_path_len) { - path[path_len] = MakeId(n, rep_->nodes_[n]->version); - } - path_len++; - r->stack_.push_back(-1); // Will remove tentative path entry - - if (n == y) { - return path_len; - } - - HASH_FOR_EACH(w, r->nodes_[n]->out) { - if (seen.insert(w)) { - r->stack_.push_back(w); - } - } - } - - return 0; -} - -bool GraphCycles::IsReachable(GraphId x, GraphId y) const { - return FindPath(x, y, 0, nullptr) > 0; -} - -void GraphCycles::UpdateStackTrace(GraphId id, int priority, - int (*get_stack_trace)(void** stack, int)) { - Node* n = FindNode(rep_, id); - if (n == nullptr || n->priority >= priority) { - return; - } - n->nstack = (*get_stack_trace)(n->stack, ABSL_ARRAYSIZE(n->stack)); - n->priority = priority; -} - -int GraphCycles::GetStackTrace(GraphId id, void*** ptr) { - Node* n = FindNode(rep_, id); - if (n == nullptr) { - *ptr = nullptr; - return 0; - } else { - *ptr = n->stack; - return n->nstack; - } -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles.h b/third_party/abseil_cpp/absl/synchronization/internal/graphcycles.h deleted file mode 100644 index ceba33e4de89..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles.h +++ /dev/null @@ -1,141 +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. -// - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_ - -// GraphCycles detects the introduction of a cycle into a directed -// graph that is being built up incrementally. -// -// Nodes are identified by small integers. It is not possible to -// record multiple edges with the same (source, destination) pair; -// requests to add an edge where one already exists are silently -// ignored. -// -// It is also not possible to introduce a cycle; an attempt to insert -// an edge that would introduce a cycle fails and returns false. -// -// GraphCycles uses no internal locking; calls into it should be -// serialized externally. - -// Performance considerations: -// Works well on sparse graphs, poorly on dense graphs. -// Extra information is maintained incrementally to detect cycles quickly. -// InsertEdge() is very fast when the edge already exists, and reasonably fast -// otherwise. -// FindPath() is linear in the size of the graph. -// The current implementation uses O(|V|+|E|) space. - -#include <cstdint> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// Opaque identifier for a graph node. -struct GraphId { - uint64_t handle; - - bool operator==(const GraphId& x) const { return handle == x.handle; } - bool operator!=(const GraphId& x) const { return handle != x.handle; } -}; - -// Return an invalid graph id that will never be assigned by GraphCycles. -inline GraphId InvalidGraphId() { - return GraphId{0}; -} - -class GraphCycles { - public: - GraphCycles(); - ~GraphCycles(); - - // Return the id to use for ptr, assigning one if necessary. - // Subsequent calls with the same ptr value will return the same id - // until Remove(). - GraphId GetId(void* ptr); - - // Remove "ptr" from the graph. Its corresponding node and all - // edges to and from it are removed. - void RemoveNode(void* ptr); - - // Return the pointer associated with id, or nullptr if id is not - // currently in the graph. - void* Ptr(GraphId id); - - // Attempt to insert an edge from source_node to dest_node. If the - // edge would introduce a cycle, return false without making any - // changes. Otherwise add the edge and return true. - bool InsertEdge(GraphId source_node, GraphId dest_node); - - // Remove any edge that exists from source_node to dest_node. - void RemoveEdge(GraphId source_node, GraphId dest_node); - - // Return whether node exists in the graph. - bool HasNode(GraphId node); - - // Return whether there is an edge directly from source_node to dest_node. - bool HasEdge(GraphId source_node, GraphId dest_node) const; - - // Return whether dest_node is reachable from source_node - // by following edges. - bool IsReachable(GraphId source_node, GraphId dest_node) const; - - // Find a path from "source" to "dest". If such a path exists, - // place the nodes on the path in the array path[], and return - // the number of nodes on the path. If the path is longer than - // max_path_len nodes, only the first max_path_len nodes are placed - // in path[]. The client should compare the return value with - // max_path_len" to see when this occurs. If no path exists, return - // 0. Any valid path stored in path[] will start with "source" and - // end with "dest". There is no guarantee that the path is the - // shortest, but no node will appear twice in the path, except the - // source and destination node if they are identical; therefore, the - // return value is at most one greater than the number of nodes in - // the graph. - int FindPath(GraphId source, GraphId dest, int max_path_len, - GraphId path[]) const; - - // Update the stack trace recorded for id with the current stack - // trace if the last time it was updated had a smaller priority - // than the priority passed on this call. - // - // *get_stack_trace is called to get the stack trace. - void UpdateStackTrace(GraphId id, int priority, - int (*get_stack_trace)(void**, int)); - - // Set *ptr to the beginning of the array that holds the recorded - // stack trace for id and return the depth of the stack trace. - int GetStackTrace(GraphId id, void*** ptr); - - // Check internal invariants. Crashes on failure, returns true on success. - // Expensive: should only be called from graphcycles_test.cc. - bool CheckInvariants() const; - - // ---------------------------------------------------- - struct Rep; - private: - Rep *rep_; // opaque representation - GraphCycles(const GraphCycles&) = delete; - GraphCycles& operator=(const GraphCycles&) = delete; -}; - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif diff --git a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_benchmark.cc b/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_benchmark.cc deleted file mode 100644 index 54823e0ba51a..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_benchmark.cc +++ /dev/null @@ -1,44 +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/synchronization/internal/graphcycles.h" - -#include <algorithm> -#include <cstdint> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/base/internal/raw_logging.h" - -namespace { - -void BM_StressTest(benchmark::State& state) { - const int num_nodes = state.range(0); - while (state.KeepRunningBatch(num_nodes)) { - absl::synchronization_internal::GraphCycles g; - std::vector<absl::synchronization_internal::GraphId> nodes(num_nodes); - for (int i = 0; i < num_nodes; i++) { - nodes[i] = g.GetId(reinterpret_cast<void*>(static_cast<uintptr_t>(i))); - } - for (int i = 0; i < num_nodes; i++) { - int end = std::min(num_nodes, i + 5); - for (int j = i + 1; j < end; j++) { - ABSL_RAW_CHECK(g.InsertEdge(nodes[i], nodes[j]), ""); - } - } - } -} -BENCHMARK(BM_StressTest)->Range(2048, 1048576); - -} // namespace diff --git a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_test.cc b/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_test.cc deleted file mode 100644 index 74eaffe7a806..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/graphcycles_test.cc +++ /dev/null @@ -1,464 +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/synchronization/internal/graphcycles.h" - -#include <map> -#include <random> -#include <unordered_set> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// We emulate a GraphCycles object with a node vector and an edge vector. -// We then compare the two implementations. - -using Nodes = std::vector<int>; -struct Edge { - int from; - int to; -}; -using Edges = std::vector<Edge>; -using RandomEngine = std::mt19937_64; - -// Mapping from integer index to GraphId. -typedef std::map<int, GraphId> IdMap; -static GraphId Get(const IdMap& id, int num) { - auto iter = id.find(num); - return (iter == id.end()) ? InvalidGraphId() : iter->second; -} - -// Return whether "to" is reachable from "from". -static bool IsReachable(Edges *edges, int from, int to, - std::unordered_set<int> *seen) { - seen->insert(from); // we are investigating "from"; don't do it again - if (from == to) return true; - for (const auto &edge : *edges) { - if (edge.from == from) { - if (edge.to == to) { // success via edge directly - return true; - } else if (seen->find(edge.to) == seen->end() && // success via edge - IsReachable(edges, edge.to, to, seen)) { - return true; - } - } - } - return false; -} - -static void PrintEdges(Edges *edges) { - ABSL_RAW_LOG(INFO, "EDGES (%zu)", edges->size()); - for (const auto &edge : *edges) { - int a = edge.from; - int b = edge.to; - ABSL_RAW_LOG(INFO, "%d %d", a, b); - } - ABSL_RAW_LOG(INFO, "---"); -} - -static void PrintGCEdges(Nodes *nodes, const IdMap &id, GraphCycles *gc) { - ABSL_RAW_LOG(INFO, "GC EDGES"); - for (int a : *nodes) { - for (int b : *nodes) { - if (gc->HasEdge(Get(id, a), Get(id, b))) { - ABSL_RAW_LOG(INFO, "%d %d", a, b); - } - } - } - ABSL_RAW_LOG(INFO, "---"); -} - -static void PrintTransitiveClosure(Nodes *nodes, Edges *edges) { - ABSL_RAW_LOG(INFO, "Transitive closure"); - for (int a : *nodes) { - for (int b : *nodes) { - std::unordered_set<int> seen; - if (IsReachable(edges, a, b, &seen)) { - ABSL_RAW_LOG(INFO, "%d %d", a, b); - } - } - } - ABSL_RAW_LOG(INFO, "---"); -} - -static void PrintGCTransitiveClosure(Nodes *nodes, const IdMap &id, - GraphCycles *gc) { - ABSL_RAW_LOG(INFO, "GC Transitive closure"); - for (int a : *nodes) { - for (int b : *nodes) { - if (gc->IsReachable(Get(id, a), Get(id, b))) { - ABSL_RAW_LOG(INFO, "%d %d", a, b); - } - } - } - ABSL_RAW_LOG(INFO, "---"); -} - -static void CheckTransitiveClosure(Nodes *nodes, Edges *edges, const IdMap &id, - GraphCycles *gc) { - std::unordered_set<int> seen; - for (const auto &a : *nodes) { - for (const auto &b : *nodes) { - seen.clear(); - bool gc_reachable = gc->IsReachable(Get(id, a), Get(id, b)); - bool reachable = IsReachable(edges, a, b, &seen); - if (gc_reachable != reachable) { - PrintEdges(edges); - PrintGCEdges(nodes, id, gc); - PrintTransitiveClosure(nodes, edges); - PrintGCTransitiveClosure(nodes, id, gc); - ABSL_RAW_LOG(FATAL, "gc_reachable %s reachable %s a %d b %d", - gc_reachable ? "true" : "false", - reachable ? "true" : "false", a, b); - } - } - } -} - -static void CheckEdges(Nodes *nodes, Edges *edges, const IdMap &id, - GraphCycles *gc) { - int count = 0; - for (const auto &edge : *edges) { - int a = edge.from; - int b = edge.to; - if (!gc->HasEdge(Get(id, a), Get(id, b))) { - PrintEdges(edges); - PrintGCEdges(nodes, id, gc); - ABSL_RAW_LOG(FATAL, "!gc->HasEdge(%d, %d)", a, b); - } - } - for (const auto &a : *nodes) { - for (const auto &b : *nodes) { - if (gc->HasEdge(Get(id, a), Get(id, b))) { - count++; - } - } - } - if (count != edges->size()) { - PrintEdges(edges); - PrintGCEdges(nodes, id, gc); - ABSL_RAW_LOG(FATAL, "edges->size() %zu count %d", edges->size(), count); - } -} - -static void CheckInvariants(const GraphCycles &gc) { - if (ABSL_PREDICT_FALSE(!gc.CheckInvariants())) - ABSL_RAW_LOG(FATAL, "CheckInvariants"); -} - -// Returns the index of a randomly chosen node in *nodes. -// Requires *nodes be non-empty. -static int RandomNode(RandomEngine* rng, Nodes *nodes) { - std::uniform_int_distribution<int> uniform(0, nodes->size()-1); - return uniform(*rng); -} - -// Returns the index of a randomly chosen edge in *edges. -// Requires *edges be non-empty. -static int RandomEdge(RandomEngine* rng, Edges *edges) { - std::uniform_int_distribution<int> uniform(0, edges->size()-1); - return uniform(*rng); -} - -// Returns the index of edge (from, to) in *edges or -1 if it is not in *edges. -static int EdgeIndex(Edges *edges, int from, int to) { - int i = 0; - while (i != edges->size() && - ((*edges)[i].from != from || (*edges)[i].to != to)) { - i++; - } - return i == edges->size()? -1 : i; -} - -TEST(GraphCycles, RandomizedTest) { - int next_node = 0; - Nodes nodes; - Edges edges; // from, to - IdMap id; - GraphCycles graph_cycles; - static const int kMaxNodes = 7; // use <= 7 nodes to keep test short - static const int kDataOffset = 17; // an offset to the node-specific data - int n = 100000; - int op = 0; - RandomEngine rng(testing::UnitTest::GetInstance()->random_seed()); - std::uniform_int_distribution<int> uniform(0, 5); - - auto ptr = [](intptr_t i) { - return reinterpret_cast<void*>(i + kDataOffset); - }; - - for (int iter = 0; iter != n; iter++) { - for (const auto &node : nodes) { - ASSERT_EQ(graph_cycles.Ptr(Get(id, node)), ptr(node)) << " node " << node; - } - CheckEdges(&nodes, &edges, id, &graph_cycles); - CheckTransitiveClosure(&nodes, &edges, id, &graph_cycles); - op = uniform(rng); - switch (op) { - case 0: // Add a node - if (nodes.size() < kMaxNodes) { - int new_node = next_node++; - GraphId new_gnode = graph_cycles.GetId(ptr(new_node)); - ASSERT_NE(new_gnode, InvalidGraphId()); - id[new_node] = new_gnode; - ASSERT_EQ(ptr(new_node), graph_cycles.Ptr(new_gnode)); - nodes.push_back(new_node); - } - break; - - case 1: // Remove a node - if (nodes.size() > 0) { - int node_index = RandomNode(&rng, &nodes); - int node = nodes[node_index]; - nodes[node_index] = nodes.back(); - nodes.pop_back(); - graph_cycles.RemoveNode(ptr(node)); - ASSERT_EQ(graph_cycles.Ptr(Get(id, node)), nullptr); - id.erase(node); - int i = 0; - while (i != edges.size()) { - if (edges[i].from == node || edges[i].to == node) { - edges[i] = edges.back(); - edges.pop_back(); - } else { - i++; - } - } - } - break; - - case 2: // Add an edge - if (nodes.size() > 0) { - int from = RandomNode(&rng, &nodes); - int to = RandomNode(&rng, &nodes); - if (EdgeIndex(&edges, nodes[from], nodes[to]) == -1) { - if (graph_cycles.InsertEdge(id[nodes[from]], id[nodes[to]])) { - Edge new_edge; - new_edge.from = nodes[from]; - new_edge.to = nodes[to]; - edges.push_back(new_edge); - } else { - std::unordered_set<int> seen; - ASSERT_TRUE(IsReachable(&edges, nodes[to], nodes[from], &seen)) - << "Edge " << nodes[to] << "->" << nodes[from]; - } - } - } - break; - - case 3: // Remove an edge - if (edges.size() > 0) { - int i = RandomEdge(&rng, &edges); - int from = edges[i].from; - int to = edges[i].to; - ASSERT_EQ(i, EdgeIndex(&edges, from, to)); - edges[i] = edges.back(); - edges.pop_back(); - ASSERT_EQ(-1, EdgeIndex(&edges, from, to)); - graph_cycles.RemoveEdge(id[from], id[to]); - } - break; - - case 4: // Check a path - if (nodes.size() > 0) { - int from = RandomNode(&rng, &nodes); - int to = RandomNode(&rng, &nodes); - GraphId path[2*kMaxNodes]; - int path_len = graph_cycles.FindPath(id[nodes[from]], id[nodes[to]], - ABSL_ARRAYSIZE(path), path); - std::unordered_set<int> seen; - bool reachable = IsReachable(&edges, nodes[from], nodes[to], &seen); - bool gc_reachable = - graph_cycles.IsReachable(Get(id, nodes[from]), Get(id, nodes[to])); - ASSERT_EQ(path_len != 0, reachable); - ASSERT_EQ(path_len != 0, gc_reachable); - // In the following line, we add one because a node can appear - // twice, if the path is from that node to itself, perhaps via - // every other node. - ASSERT_LE(path_len, kMaxNodes + 1); - if (path_len != 0) { - ASSERT_EQ(id[nodes[from]], path[0]); - ASSERT_EQ(id[nodes[to]], path[path_len-1]); - for (int i = 1; i < path_len; i++) { - ASSERT_TRUE(graph_cycles.HasEdge(path[i-1], path[i])); - } - } - } - break; - - case 5: // Check invariants - CheckInvariants(graph_cycles); - break; - - default: - ABSL_RAW_LOG(FATAL, "op %d", op); - } - - // Very rarely, test graph expansion by adding then removing many nodes. - std::bernoulli_distribution one_in_1024(1.0 / 1024); - if (one_in_1024(rng)) { - CheckEdges(&nodes, &edges, id, &graph_cycles); - CheckTransitiveClosure(&nodes, &edges, id, &graph_cycles); - for (int i = 0; i != 256; i++) { - int new_node = next_node++; - GraphId new_gnode = graph_cycles.GetId(ptr(new_node)); - ASSERT_NE(InvalidGraphId(), new_gnode); - id[new_node] = new_gnode; - ASSERT_EQ(ptr(new_node), graph_cycles.Ptr(new_gnode)); - for (const auto &node : nodes) { - ASSERT_NE(node, new_node); - } - nodes.push_back(new_node); - } - for (int i = 0; i != 256; i++) { - ASSERT_GT(nodes.size(), 0); - int node_index = RandomNode(&rng, &nodes); - int node = nodes[node_index]; - nodes[node_index] = nodes.back(); - nodes.pop_back(); - graph_cycles.RemoveNode(ptr(node)); - id.erase(node); - int j = 0; - while (j != edges.size()) { - if (edges[j].from == node || edges[j].to == node) { - edges[j] = edges.back(); - edges.pop_back(); - } else { - j++; - } - } - } - CheckInvariants(graph_cycles); - } - } -} - -class GraphCyclesTest : public ::testing::Test { - public: - IdMap id_; - GraphCycles g_; - - static void* Ptr(int i) { - return reinterpret_cast<void*>(static_cast<uintptr_t>(i)); - } - - static int Num(void* ptr) { - return static_cast<int>(reinterpret_cast<uintptr_t>(ptr)); - } - - // Test relies on ith NewNode() call returning Node numbered i - GraphCyclesTest() { - for (int i = 0; i < 100; i++) { - id_[i] = g_.GetId(Ptr(i)); - } - CheckInvariants(g_); - } - - bool AddEdge(int x, int y) { - return g_.InsertEdge(Get(id_, x), Get(id_, y)); - } - - void AddMultiples() { - // For every node x > 0: add edge to 2*x, 3*x - for (int x = 1; x < 25; x++) { - EXPECT_TRUE(AddEdge(x, 2*x)) << x; - EXPECT_TRUE(AddEdge(x, 3*x)) << x; - } - CheckInvariants(g_); - } - - std::string Path(int x, int y) { - GraphId path[5]; - int np = g_.FindPath(Get(id_, x), Get(id_, y), ABSL_ARRAYSIZE(path), path); - std::string result; - for (int i = 0; i < np; i++) { - if (i >= ABSL_ARRAYSIZE(path)) { - result += " ..."; - break; - } - if (!result.empty()) result.push_back(' '); - char buf[20]; - snprintf(buf, sizeof(buf), "%d", Num(g_.Ptr(path[i]))); - result += buf; - } - return result; - } -}; - -TEST_F(GraphCyclesTest, NoCycle) { - AddMultiples(); - CheckInvariants(g_); -} - -TEST_F(GraphCyclesTest, SimpleCycle) { - AddMultiples(); - EXPECT_FALSE(AddEdge(8, 4)); - EXPECT_EQ("4 8", Path(4, 8)); - CheckInvariants(g_); -} - -TEST_F(GraphCyclesTest, IndirectCycle) { - AddMultiples(); - EXPECT_TRUE(AddEdge(16, 9)); - CheckInvariants(g_); - EXPECT_FALSE(AddEdge(9, 2)); - EXPECT_EQ("2 4 8 16 9", Path(2, 9)); - CheckInvariants(g_); -} - -TEST_F(GraphCyclesTest, LongPath) { - ASSERT_TRUE(AddEdge(2, 4)); - ASSERT_TRUE(AddEdge(4, 6)); - ASSERT_TRUE(AddEdge(6, 8)); - ASSERT_TRUE(AddEdge(8, 10)); - ASSERT_TRUE(AddEdge(10, 12)); - ASSERT_FALSE(AddEdge(12, 2)); - EXPECT_EQ("2 4 6 8 10 ...", Path(2, 12)); - CheckInvariants(g_); -} - -TEST_F(GraphCyclesTest, RemoveNode) { - ASSERT_TRUE(AddEdge(1, 2)); - ASSERT_TRUE(AddEdge(2, 3)); - ASSERT_TRUE(AddEdge(3, 4)); - ASSERT_TRUE(AddEdge(4, 5)); - g_.RemoveNode(g_.Ptr(id_[3])); - id_.erase(3); - ASSERT_TRUE(AddEdge(5, 1)); -} - -TEST_F(GraphCyclesTest, ManyEdges) { - const int N = 50; - for (int i = 0; i < N; i++) { - for (int j = 1; j < N; j++) { - ASSERT_TRUE(AddEdge(i, i+j)); - } - } - CheckInvariants(g_); - ASSERT_TRUE(AddEdge(2*N-1, 0)); - CheckInvariants(g_); - ASSERT_FALSE(AddEdge(10, 9)); - CheckInvariants(g_); -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/internal/kernel_timeout.h b/third_party/abseil_cpp/absl/synchronization/internal/kernel_timeout.h deleted file mode 100644 index bbd4d2d70f44..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/kernel_timeout.h +++ /dev/null @@ -1,156 +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. -// - -// An optional absolute timeout, with nanosecond granularity, -// compatible with absl::Time. Suitable for in-register -// parameter-passing (e.g. syscalls.) -// Constructible from a absl::Time (for a timeout to be respected) or {} -// (for "no timeout".) -// This is a private low-level API for use by a handful of low-level -// components that are friends of this class. Higher-level components -// should build APIs based on absl::Time and absl::Duration. - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ - -#include <time.h> - -#include <algorithm> -#include <limits> - -#include "absl/base/internal/raw_logging.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -class Futex; -class Waiter; - -class KernelTimeout { - public: - // A timeout that should expire at <t>. Any value, in the full - // InfinitePast() to InfiniteFuture() range, is valid here and will be - // respected. - explicit KernelTimeout(absl::Time t) : ns_(MakeNs(t)) {} - // No timeout. - KernelTimeout() : ns_(0) {} - - // A more explicit factory for those who prefer it. Equivalent to {}. - static KernelTimeout Never() { return {}; } - - // We explicitly do not support other custom formats: timespec, int64_t nanos. - // Unify on this and absl::Time, please. - - bool has_timeout() const { return ns_ != 0; } - - // Convert to parameter for sem_timedwait/futex/similar. Only for approved - // users. Do not call if !has_timeout. - struct timespec MakeAbsTimespec(); - - private: - // internal rep, not user visible: ns after unix epoch. - // zero = no timeout. - // Negative we treat as an unlikely (and certainly expired!) but valid - // timeout. - int64_t ns_; - - static int64_t MakeNs(absl::Time t) { - // optimization--InfiniteFuture is common "no timeout" value - // and cheaper to compare than convert. - if (t == absl::InfiniteFuture()) return 0; - int64_t x = ToUnixNanos(t); - - // A timeout that lands exactly on the epoch (x=0) needs to be respected, - // so we alter it unnoticably to 1. Negative timeouts are in - // theory supported, but handled poorly by the kernel (long - // delays) so push them forward too; since all such times have - // already passed, it's indistinguishable. - if (x <= 0) x = 1; - // A time larger than what can be represented to the kernel is treated - // as no timeout. - if (x == (std::numeric_limits<int64_t>::max)()) x = 0; - return x; - } - -#ifdef _WIN32 - // Converts to milliseconds from now, or INFINITE when - // !has_timeout(). For use by SleepConditionVariableSRW on - // Windows. Callers should recognize that the return value is a - // relative duration (it should be recomputed by calling this method - // in the case of a spurious wakeup). - // This header file may be included transitively by public header files, - // so we define our own DWORD and INFINITE instead of getting them from - // <intsafe.h> and <WinBase.h>. - typedef unsigned long DWord; // NOLINT - DWord InMillisecondsFromNow() const { - constexpr DWord kInfinite = (std::numeric_limits<DWord>::max)(); - if (!has_timeout()) { - return kInfinite; - } - // The use of absl::Now() to convert from absolute time to - // relative time means that absl::Now() cannot use anything that - // depends on KernelTimeout (for example, Mutex) on Windows. - int64_t now = ToUnixNanos(absl::Now()); - if (ns_ >= now) { - // Round up so that Now() + ms_from_now >= ns_. - constexpr uint64_t max_nanos = - (std::numeric_limits<int64_t>::max)() - 999999u; - uint64_t ms_from_now = - (std::min<uint64_t>(max_nanos, ns_ - now) + 999999u) / 1000000u; - if (ms_from_now > kInfinite) { - return kInfinite; - } - return static_cast<DWord>(ms_from_now); - } - return 0; - } -#endif - - friend class Futex; - friend class Waiter; -}; - -inline struct timespec KernelTimeout::MakeAbsTimespec() { - int64_t n = ns_; - static const int64_t kNanosPerSecond = 1000 * 1000 * 1000; - if (n == 0) { - ABSL_RAW_LOG( - ERROR, "Tried to create a timespec from a non-timeout; never do this."); - // But we'll try to continue sanely. no-timeout ~= saturated timeout. - n = (std::numeric_limits<int64_t>::max)(); - } - - // Kernel APIs validate timespecs as being at or after the epoch, - // despite the kernel time type being signed. However, no one can - // tell the difference between a timeout at or before the epoch (since - // all such timeouts have expired!) - if (n < 0) n = 0; - - struct timespec abstime; - int64_t seconds = (std::min)(n / kNanosPerSecond, - int64_t{(std::numeric_limits<time_t>::max)()}); - abstime.tv_sec = static_cast<time_t>(seconds); - abstime.tv_nsec = static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond); - return abstime; -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/internal/per_thread_sem.cc b/third_party/abseil_cpp/absl/synchronization/internal/per_thread_sem.cc deleted file mode 100644 index 821ca9b4e9c3..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/per_thread_sem.cc +++ /dev/null @@ -1,106 +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 is a no-op if the required LowLevelAlloc support is missing. -#include "absl/base/internal/low_level_alloc.h" -#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING - -#include "absl/synchronization/internal/per_thread_sem.h" - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/internal/thread_identity.h" -#include "absl/synchronization/internal/waiter.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -void PerThreadSem::SetThreadBlockedCounter(std::atomic<int> *counter) { - base_internal::ThreadIdentity *identity; - identity = GetOrCreateCurrentThreadIdentity(); - identity->blocked_count_ptr = counter; -} - -std::atomic<int> *PerThreadSem::GetThreadBlockedCounter() { - base_internal::ThreadIdentity *identity; - identity = GetOrCreateCurrentThreadIdentity(); - return identity->blocked_count_ptr; -} - -void PerThreadSem::Init(base_internal::ThreadIdentity *identity) { - new (Waiter::GetWaiter(identity)) Waiter(); - identity->ticker.store(0, std::memory_order_relaxed); - identity->wait_start.store(0, std::memory_order_relaxed); - identity->is_idle.store(false, std::memory_order_relaxed); -} - -void PerThreadSem::Destroy(base_internal::ThreadIdentity *identity) { - Waiter::GetWaiter(identity)->~Waiter(); -} - -void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) { - const int ticker = - identity->ticker.fetch_add(1, std::memory_order_relaxed) + 1; - const int wait_start = identity->wait_start.load(std::memory_order_relaxed); - const bool is_idle = identity->is_idle.load(std::memory_order_relaxed); - if (wait_start && (ticker - wait_start > Waiter::kIdlePeriods) && !is_idle) { - // Wakeup the waiting thread since it is time for it to become idle. - Waiter::GetWaiter(identity)->Poke(); - } -} - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -extern "C" { - -ABSL_ATTRIBUTE_WEAK void AbslInternalPerThreadSemPost( - absl::base_internal::ThreadIdentity *identity) { - absl::synchronization_internal::Waiter::GetWaiter(identity)->Post(); -} - -ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait( - absl::synchronization_internal::KernelTimeout t) { - bool timeout = false; - absl::base_internal::ThreadIdentity *identity; - identity = absl::synchronization_internal::GetOrCreateCurrentThreadIdentity(); - - // Ensure wait_start != 0. - int ticker = identity->ticker.load(std::memory_order_relaxed); - identity->wait_start.store(ticker ? ticker : 1, std::memory_order_relaxed); - identity->is_idle.store(false, std::memory_order_relaxed); - - if (identity->blocked_count_ptr != nullptr) { - // Increment count of threads blocked in a given thread pool. - identity->blocked_count_ptr->fetch_add(1, std::memory_order_relaxed); - } - - timeout = - !absl::synchronization_internal::Waiter::GetWaiter(identity)->Wait(t); - - if (identity->blocked_count_ptr != nullptr) { - identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed); - } - - identity->is_idle.store(false, std::memory_order_relaxed); - identity->wait_start.store(0, std::memory_order_relaxed); - return !timeout; -} - -} // extern "C" - -#endif // ABSL_LOW_LEVEL_ALLOC_MISSING 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 deleted file mode 100644 index 2228b6e8ea91..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/per_thread_sem.h +++ /dev/null @@ -1,115 +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. -// - -// PerThreadSem is a low-level synchronization primitive controlling the -// runnability of a single thread, used internally by Mutex and CondVar. -// -// This is NOT a general-purpose synchronization mechanism, and should not be -// used directly by applications. Applications should use Mutex and CondVar. -// -// The semantics of PerThreadSem are the same as that of a counting semaphore. -// Each thread maintains an abstract "count" value associated with its identity. - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_ - -#include <atomic> - -#include "absl/base/internal/thread_identity.h" -#include "absl/synchronization/internal/create_thread_identity.h" -#include "absl/synchronization/internal/kernel_timeout.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class Mutex; - -namespace synchronization_internal { - -class PerThreadSem { - public: - PerThreadSem() = delete; - PerThreadSem(const PerThreadSem&) = delete; - PerThreadSem& operator=(const PerThreadSem&) = delete; - - // Routine invoked periodically (once a second) by a background thread. - // Has no effect on user-visible state. - static void Tick(base_internal::ThreadIdentity* identity); - - // --------------------------------------------------------------------------- - // Routines used by autosizing threadpools to detect when threads are - // blocked. Each thread has a counter pointer, initially zero. If non-zero, - // the implementation atomically increments the counter when it blocks on a - // semaphore, a decrements it again when it wakes. This allows a threadpool - // to keep track of how many of its threads are blocked. - // SetThreadBlockedCounter() should be used only by threadpool - // implementations. GetThreadBlockedCounter() should be used by modules that - // block threads; if the pointer returned is non-zero, the location should be - // incremented before the thread blocks, and decremented after it wakes. - static void SetThreadBlockedCounter(std::atomic<int> *counter); - static std::atomic<int> *GetThreadBlockedCounter(); - - private: - // Create the PerThreadSem associated with "identity". Initializes count=0. - // REQUIRES: May only be called by ThreadIdentity. - static void Init(base_internal::ThreadIdentity* identity); - - // Destroy the PerThreadSem associated with "identity". - // REQUIRES: May only be called by ThreadIdentity. - static void Destroy(base_internal::ThreadIdentity* identity); - - // Increments "identity"'s count. - static inline void Post(base_internal::ThreadIdentity* identity); - - // Waits until either our count > 0 or t has expired. - // If count > 0, decrements count and returns true. Otherwise returns false. - // !t.has_timeout() => Wait(t) will return true. - static inline bool Wait(KernelTimeout t); - - // Permitted callers. - friend class PerThreadSemTest; - friend class absl::Mutex; - friend absl::base_internal::ThreadIdentity* CreateThreadIdentity(); - friend void ReclaimThreadIdentity(void* v); -}; - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -// In some build configurations we pass --detect-odr-violations to the -// gold linker. This causes it to flag weak symbol overrides as ODR -// violations. Because ODR only applies to C++ and not C, -// --detect-odr-violations ignores symbols not mangled with C++ names. -// By changing our extension points to be extern "C", we dodge this -// check. -extern "C" { -void AbslInternalPerThreadSemPost( - absl::base_internal::ThreadIdentity* identity); -bool AbslInternalPerThreadSemWait( - absl::synchronization_internal::KernelTimeout t); -} // extern "C" - -void absl::synchronization_internal::PerThreadSem::Post( - absl::base_internal::ThreadIdentity* identity) { - AbslInternalPerThreadSemPost(identity); -} - -bool absl::synchronization_internal::PerThreadSem::Wait( - absl::synchronization_internal::KernelTimeout 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 deleted file mode 100644 index 8cf59e64e961..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/per_thread_sem_test.cc +++ /dev/null @@ -1,181 +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/synchronization/internal/per_thread_sem.h" - -#include <atomic> -#include <condition_variable> // NOLINT(build/c++11) -#include <functional> -#include <limits> -#include <mutex> // NOLINT(build/c++11) -#include <string> -#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" -#include "absl/time/clock.h" -#include "absl/time/time.h" - -// In this test we explicitly avoid the use of synchronization -// primitives which might use PerThreadSem, most notably absl::Mutex. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -class SimpleSemaphore { - public: - SimpleSemaphore() : count_(0) {} - - // Decrements (locks) the semaphore. If the semaphore's value is - // greater than zero, then the decrement proceeds, and the function - // returns, immediately. If the semaphore currently has the value - // zero, then the call blocks until it becomes possible to perform - // the decrement. - void Wait() { - std::unique_lock<std::mutex> lock(mu_); - cv_.wait(lock, [this]() { return count_ > 0; }); - --count_; - cv_.notify_one(); - } - - // Increments (unlocks) the semaphore. If the semaphore's value - // consequently becomes greater than zero, then another thread - // blocked Wait() call will be woken up and proceed to lock the - // semaphore. - void Post() { - std::lock_guard<std::mutex> lock(mu_); - ++count_; - cv_.notify_one(); - } - - private: - std::mutex mu_; - std::condition_variable cv_; - int count_; -}; - -struct ThreadData { - int num_iterations; // Number of replies to send. - SimpleSemaphore identity2_written; // Posted by thread writing identity2. - base_internal::ThreadIdentity *identity1; // First Post()-er. - base_internal::ThreadIdentity *identity2; // First Wait()-er. - KernelTimeout timeout; -}; - -// Need friendship with PerThreadSem. -class PerThreadSemTest : public testing::Test { - public: - static void TimingThread(ThreadData* t) { - t->identity2 = GetOrCreateCurrentThreadIdentity(); - t->identity2_written.Post(); - while (t->num_iterations--) { - Wait(t->timeout); - Post(t->identity1); - } - } - - void TestTiming(const char *msg, bool timeout) { - static const int kNumIterations = 100; - ThreadData t; - t.num_iterations = kNumIterations; - t.timeout = timeout ? - KernelTimeout(absl::Now() + absl::Seconds(10000)) // far in the future - : KernelTimeout::Never(); - t.identity1 = GetOrCreateCurrentThreadIdentity(); - - // We can't use the Thread class here because it uses the Mutex - // class which will invoke PerThreadSem, so we use std::thread instead. - std::thread partner_thread(std::bind(TimingThread, &t)); - - // Wait for our partner thread to register their identity. - t.identity2_written.Wait(); - - int64_t min_cycles = std::numeric_limits<int64_t>::max(); - int64_t total_cycles = 0; - for (int i = 0; i < kNumIterations; ++i) { - absl::SleepFor(absl::Milliseconds(20)); - int64_t cycles = base_internal::CycleClock::Now(); - Post(t.identity2); - Wait(t.timeout); - cycles = base_internal::CycleClock::Now() - cycles; - min_cycles = std::min(min_cycles, cycles); - total_cycles += cycles; - } - std::string out = StrCat( - msg, "min cycle count=", min_cycles, " avg cycle count=", - absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations)); - printf("%s\n", out.c_str()); - - partner_thread.join(); - } - - protected: - static void Post(base_internal::ThreadIdentity *id) { - PerThreadSem::Post(id); - } - static bool Wait(KernelTimeout t) { - return PerThreadSem::Wait(t); - } - - // convenience overload - static bool Wait(absl::Time t) { - return Wait(KernelTimeout(t)); - } - - static void Tick(base_internal::ThreadIdentity *identity) { - PerThreadSem::Tick(identity); - } -}; - -namespace { - -TEST_F(PerThreadSemTest, WithoutTimeout) { - PerThreadSemTest::TestTiming("Without timeout: ", false); -} - -TEST_F(PerThreadSemTest, WithTimeout) { - PerThreadSemTest::TestTiming("With timeout: ", true); -} - -TEST_F(PerThreadSemTest, Timeouts) { - const absl::Duration delay = absl::Milliseconds(50); - const absl::Time start = absl::Now(); - EXPECT_FALSE(Wait(start + delay)); - const absl::Duration elapsed = absl::Now() - start; - // Allow for a slight early return, to account for quality of implementation - // issues on various platforms. - const absl::Duration slop = absl::Microseconds(200); - EXPECT_LE(delay - slop, elapsed) - << "Wait returned " << delay - elapsed - << " early (with " << slop << " slop), start time was " << start; - - absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100); - EXPECT_FALSE(Wait(negative_timeout)); - EXPECT_LE(negative_timeout, absl::Now() + slop); // trivially true :) - - Post(GetOrCreateCurrentThreadIdentity()); - // The wait here has an expired timeout, but we have a wake to consume, - // so this should succeed - EXPECT_TRUE(Wait(negative_timeout)); -} - -} // namespace - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/internal/thread_pool.h b/third_party/abseil_cpp/absl/synchronization/internal/thread_pool.h deleted file mode 100644 index 0cb96dacde83..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/thread_pool.h +++ /dev/null @@ -1,93 +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. - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_ - -#include <cassert> -#include <cstddef> -#include <functional> -#include <queue> -#include <thread> // NOLINT(build/c++11) -#include <vector> - -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// A simple ThreadPool implementation for tests. -class ThreadPool { - public: - explicit ThreadPool(int num_threads) { - for (int i = 0; i < num_threads; ++i) { - threads_.push_back(std::thread(&ThreadPool::WorkLoop, this)); - } - } - - ThreadPool(const ThreadPool &) = delete; - ThreadPool &operator=(const ThreadPool &) = delete; - - ~ThreadPool() { - { - absl::MutexLock l(&mu_); - for (size_t i = 0; i < threads_.size(); i++) { - queue_.push(nullptr); // Shutdown signal. - } - } - for (auto &t : threads_) { - t.join(); - } - } - - // Schedule a function to be run on a ThreadPool thread immediately. - void Schedule(std::function<void()> func) { - assert(func != nullptr); - absl::MutexLock l(&mu_); - queue_.push(std::move(func)); - } - - private: - bool WorkAvailable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { - return !queue_.empty(); - } - - void WorkLoop() { - while (true) { - std::function<void()> func; - { - absl::MutexLock l(&mu_); - mu_.Await(absl::Condition(this, &ThreadPool::WorkAvailable)); - func = std::move(queue_.front()); - queue_.pop(); - } - if (func == nullptr) { // Shutdown signal. - break; - } - func(); - } - } - - absl::Mutex mu_; - std::queue<std::function<void()>> queue_ ABSL_GUARDED_BY(mu_); - std::vector<std::thread> threads_; -}; - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/internal/waiter.cc b/third_party/abseil_cpp/absl/synchronization/internal/waiter.cc deleted file mode 100644 index 2123be60f54f..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/waiter.cc +++ /dev/null @@ -1,428 +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/synchronization/internal/waiter.h" - -#include "absl/base/config.h" - -#ifdef _WIN32 -#include <windows.h> -#else -#include <pthread.h> -#include <sys/time.h> -#include <unistd.h> -#endif - -#ifdef __linux__ -#include <linux/futex.h> -#include <sys/syscall.h> -#endif - -#ifdef ABSL_HAVE_SEMAPHORE_H -#include <semaphore.h> -#endif - -#include <errno.h> -#include <stdio.h> -#include <time.h> - -#include <atomic> -#include <cassert> -#include <cstdint> -#include <new> -#include <type_traits> - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/thread_identity.h" -#include "absl/base/optimization.h" -#include "absl/synchronization/internal/kernel_timeout.h" - - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -static void MaybeBecomeIdle() { - base_internal::ThreadIdentity *identity = - base_internal::CurrentThreadIdentityIfPresent(); - assert(identity != nullptr); - const bool is_idle = identity->is_idle.load(std::memory_order_relaxed); - const int ticker = identity->ticker.load(std::memory_order_relaxed); - const int wait_start = identity->wait_start.load(std::memory_order_relaxed); - if (!is_idle && ticker - wait_start > Waiter::kIdlePeriods) { - identity->is_idle.store(true, std::memory_order_relaxed); - } -} - -#if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX - -Waiter::Waiter() { - futex_.store(0, std::memory_order_relaxed); -} - -Waiter::~Waiter() = default; - -bool Waiter::Wait(KernelTimeout t) { - // Loop until we can atomically decrement futex from a positive - // value, waiting on a futex while we believe it is zero. - // Note that, since the thread ticker is just reset, we don't need to check - // whether the thread is idle on the very first pass of the loop. - bool first_pass = true; - while (true) { - int32_t x = futex_.load(std::memory_order_relaxed); - while (x != 0) { - if (!futex_.compare_exchange_weak(x, x - 1, - std::memory_order_acquire, - std::memory_order_relaxed)) { - continue; // Raced with someone, retry. - } - return true; // Consumed a wakeup, we are done. - } - - - if (!first_pass) MaybeBecomeIdle(); - const int err = Futex::WaitUntil(&futex_, 0, t); - if (err != 0) { - if (err == -EINTR || err == -EWOULDBLOCK) { - // Do nothing, the loop will retry. - } else if (err == -ETIMEDOUT) { - return false; - } else { - ABSL_RAW_LOG(FATAL, "Futex operation failed with error %d\n", err); - } - } - first_pass = false; - } -} - -void Waiter::Post() { - if (futex_.fetch_add(1, std::memory_order_release) == 0) { - // We incremented from 0, need to wake a potential waiter. - Poke(); - } -} - -void Waiter::Poke() { - // Wake one thread waiting on the futex. - const int err = Futex::Wake(&futex_, 1); - if (ABSL_PREDICT_FALSE(err < 0)) { - ABSL_RAW_LOG(FATAL, "Futex operation failed with error %d\n", err); - } -} - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR - -class PthreadMutexHolder { - public: - explicit PthreadMutexHolder(pthread_mutex_t *mu) : mu_(mu) { - const int err = pthread_mutex_lock(mu_); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_mutex_lock failed: %d", err); - } - } - - PthreadMutexHolder(const PthreadMutexHolder &rhs) = delete; - PthreadMutexHolder &operator=(const PthreadMutexHolder &rhs) = delete; - - ~PthreadMutexHolder() { - const int err = pthread_mutex_unlock(mu_); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_mutex_unlock failed: %d", err); - } - } - - private: - pthread_mutex_t *mu_; -}; - -Waiter::Waiter() { - const int err = pthread_mutex_init(&mu_, 0); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_mutex_init failed: %d", err); - } - - const int err2 = pthread_cond_init(&cv_, 0); - if (err2 != 0) { - ABSL_RAW_LOG(FATAL, "pthread_cond_init failed: %d", err2); - } - - waiter_count_ = 0; - wakeup_count_ = 0; -} - -Waiter::~Waiter() { - const int err = pthread_mutex_destroy(&mu_); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_mutex_destroy failed: %d", err); - } - - const int err2 = pthread_cond_destroy(&cv_); - if (err2 != 0) { - ABSL_RAW_LOG(FATAL, "pthread_cond_destroy failed: %d", err2); - } -} - -bool Waiter::Wait(KernelTimeout t) { - struct timespec abs_timeout; - if (t.has_timeout()) { - abs_timeout = t.MakeAbsTimespec(); - } - - PthreadMutexHolder h(&mu_); - ++waiter_count_; - // Loop until we find a wakeup to consume or timeout. - // Note that, since the thread ticker is just reset, we don't need to check - // whether the thread is idle on the very first pass of the loop. - bool first_pass = true; - while (wakeup_count_ == 0) { - if (!first_pass) MaybeBecomeIdle(); - // No wakeups available, time to wait. - if (!t.has_timeout()) { - const int err = pthread_cond_wait(&cv_, &mu_); - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err); - } - } else { - const int err = pthread_cond_timedwait(&cv_, &mu_, &abs_timeout); - if (err == ETIMEDOUT) { - --waiter_count_; - return false; - } - if (err != 0) { - ABSL_RAW_LOG(FATAL, "pthread_cond_timedwait failed: %d", err); - } - } - first_pass = false; - } - // Consume a wakeup and we're done. - --wakeup_count_; - --waiter_count_; - return true; -} - -void Waiter::Post() { - PthreadMutexHolder h(&mu_); - ++wakeup_count_; - InternalCondVarPoke(); -} - -void Waiter::Poke() { - PthreadMutexHolder h(&mu_); - InternalCondVarPoke(); -} - -void Waiter::InternalCondVarPoke() { - if (waiter_count_ != 0) { - const int err = pthread_cond_signal(&cv_); - if (ABSL_PREDICT_FALSE(err != 0)) { - ABSL_RAW_LOG(FATAL, "pthread_cond_signal failed: %d", err); - } - } -} - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM - -Waiter::Waiter() { - if (sem_init(&sem_, 0, 0) != 0) { - ABSL_RAW_LOG(FATAL, "sem_init failed with errno %d\n", errno); - } - wakeups_.store(0, std::memory_order_relaxed); -} - -Waiter::~Waiter() { - if (sem_destroy(&sem_) != 0) { - ABSL_RAW_LOG(FATAL, "sem_destroy failed with errno %d\n", errno); - } -} - -bool Waiter::Wait(KernelTimeout t) { - struct timespec abs_timeout; - if (t.has_timeout()) { - abs_timeout = t.MakeAbsTimespec(); - } - - // Loop until we timeout or consume a wakeup. - // Note that, since the thread ticker is just reset, we don't need to check - // whether the thread is idle on the very first pass of the loop. - bool first_pass = true; - while (true) { - int x = wakeups_.load(std::memory_order_relaxed); - while (x != 0) { - if (!wakeups_.compare_exchange_weak(x, x - 1, - std::memory_order_acquire, - std::memory_order_relaxed)) { - continue; // Raced with someone, retry. - } - // Successfully consumed a wakeup, we're done. - return true; - } - - if (!first_pass) MaybeBecomeIdle(); - // Nothing to consume, wait (looping on EINTR). - while (true) { - if (!t.has_timeout()) { - if (sem_wait(&sem_) == 0) break; - if (errno == EINTR) continue; - ABSL_RAW_LOG(FATAL, "sem_wait failed: %d", errno); - } else { - if (sem_timedwait(&sem_, &abs_timeout) == 0) break; - if (errno == EINTR) continue; - if (errno == ETIMEDOUT) return false; - ABSL_RAW_LOG(FATAL, "sem_timedwait failed: %d", errno); - } - } - first_pass = false; - } -} - -void Waiter::Post() { - // Post a wakeup. - if (wakeups_.fetch_add(1, std::memory_order_release) == 0) { - // We incremented from 0, need to wake a potential waiter. - Poke(); - } -} - -void Waiter::Poke() { - if (sem_post(&sem_) != 0) { // Wake any semaphore waiter. - ABSL_RAW_LOG(FATAL, "sem_post failed with errno %d\n", errno); - } -} - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32 - -class Waiter::WinHelper { - public: - static SRWLOCK *GetLock(Waiter *w) { - return reinterpret_cast<SRWLOCK *>(&w->mu_storage_); - } - - static CONDITION_VARIABLE *GetCond(Waiter *w) { - return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_); - } - - static_assert(sizeof(SRWLOCK) == sizeof(void *), - "`mu_storage_` does not have the same size as SRWLOCK"); - static_assert(alignof(SRWLOCK) == alignof(void *), - "`mu_storage_` does not have the same alignment as SRWLOCK"); - - static_assert(sizeof(CONDITION_VARIABLE) == sizeof(void *), - "`ABSL_CONDITION_VARIABLE_STORAGE` does not have the same size " - "as `CONDITION_VARIABLE`"); - static_assert( - alignof(CONDITION_VARIABLE) == alignof(void *), - "`cv_storage_` does not have the same alignment as `CONDITION_VARIABLE`"); - - // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible - // and destructible because we never call their constructors or destructors. - static_assert(std::is_trivially_constructible<SRWLOCK>::value, - "The `SRWLOCK` type must be trivially constructible"); - static_assert( - std::is_trivially_constructible<CONDITION_VARIABLE>::value, - "The `CONDITION_VARIABLE` type must be trivially constructible"); - static_assert(std::is_trivially_destructible<SRWLOCK>::value, - "The `SRWLOCK` type must be trivially destructible"); - static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value, - "The `CONDITION_VARIABLE` type must be trivially destructible"); -}; - -class LockHolder { - public: - explicit LockHolder(SRWLOCK* mu) : mu_(mu) { - AcquireSRWLockExclusive(mu_); - } - - LockHolder(const LockHolder&) = delete; - LockHolder& operator=(const LockHolder&) = delete; - - ~LockHolder() { - ReleaseSRWLockExclusive(mu_); - } - - private: - SRWLOCK* mu_; -}; - -Waiter::Waiter() { - auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK; - auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE; - InitializeSRWLock(mu); - InitializeConditionVariable(cv); - waiter_count_ = 0; - wakeup_count_ = 0; -} - -// SRW locks and condition variables do not need to be explicitly destroyed. -// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializesrwlock -// https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with -Waiter::~Waiter() = default; - -bool Waiter::Wait(KernelTimeout t) { - SRWLOCK *mu = WinHelper::GetLock(this); - CONDITION_VARIABLE *cv = WinHelper::GetCond(this); - - LockHolder h(mu); - ++waiter_count_; - - // Loop until we find a wakeup to consume or timeout. - // Note that, since the thread ticker is just reset, we don't need to check - // whether the thread is idle on the very first pass of the loop. - bool first_pass = true; - while (wakeup_count_ == 0) { - if (!first_pass) MaybeBecomeIdle(); - // No wakeups available, time to wait. - if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) { - // GetLastError() returns a Win32 DWORD, but we assign to - // unsigned long to simplify the ABSL_RAW_LOG case below. The uniform - // initialization guarantees this is not a narrowing conversion. - const unsigned long err{GetLastError()}; // NOLINT(runtime/int) - if (err == ERROR_TIMEOUT) { - --waiter_count_; - return false; - } else { - ABSL_RAW_LOG(FATAL, "SleepConditionVariableSRW failed: %lu", err); - } - } - first_pass = false; - } - // Consume a wakeup and we're done. - --wakeup_count_; - --waiter_count_; - return true; -} - -void Waiter::Post() { - LockHolder h(WinHelper::GetLock(this)); - ++wakeup_count_; - InternalCondVarPoke(); -} - -void Waiter::Poke() { - LockHolder h(WinHelper::GetLock(this)); - InternalCondVarPoke(); -} - -void Waiter::InternalCondVarPoke() { - if (waiter_count_ != 0) { - WakeConditionVariable(WinHelper::GetCond(this)); - } -} - -#else -#error Unknown ABSL_WAITER_MODE -#endif - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/internal/waiter.h b/third_party/abseil_cpp/absl/synchronization/internal/waiter.h deleted file mode 100644 index be3df180d4e2..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/internal/waiter.h +++ /dev/null @@ -1,155 +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. -// - -#ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_ -#define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_ - -#include "absl/base/config.h" - -#ifdef _WIN32 -#include <sdkddkver.h> -#else -#include <pthread.h> -#endif - -#ifdef __linux__ -#include <linux/futex.h> -#endif - -#ifdef ABSL_HAVE_SEMAPHORE_H -#include <semaphore.h> -#endif - -#include <atomic> -#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> -#define ABSL_WAITER_MODE_FUTEX 0 -#define ABSL_WAITER_MODE_SEM 1 -#define ABSL_WAITER_MODE_CONDVAR 2 -#define ABSL_WAITER_MODE_WIN32 3 - -#if defined(ABSL_FORCE_WAITER_MODE) -#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) -#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX -#elif defined(ABSL_HAVE_SEMAPHORE_H) -#define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM -#else -#define ABSL_WAITER_MODE ABSL_WAITER_MODE_CONDVAR -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace synchronization_internal { - -// Waiter is an OS-specific semaphore. -class Waiter { - public: - // Prepare any data to track waits. - Waiter(); - - // Not copyable or movable - Waiter(const Waiter&) = delete; - Waiter& operator=(const Waiter&) = delete; - - // Destroy any data to track waits. - ~Waiter(); - - // Blocks the calling thread until a matching call to `Post()` or - // `t` has passed. Returns `true` if woken (`Post()` called), - // `false` on timeout. - bool Wait(KernelTimeout t); - - // Restart the caller of `Wait()` as with a normal semaphore. - void Post(); - - // If anyone is waiting, wake them up temporarily and cause them to - // call `MaybeBecomeIdle()`. They will then return to waiting for a - // `Post()` or timeout. - void Poke(); - - // Returns the Waiter associated with the identity. - static Waiter* GetWaiter(base_internal::ThreadIdentity* identity) { - static_assert( - sizeof(Waiter) <= sizeof(base_internal::ThreadIdentity::WaiterState), - "Insufficient space for Waiter"); - return reinterpret_cast<Waiter*>(identity->waiter_state.data); - } - - // How many periods to remain idle before releasing resources -#ifndef ABSL_HAVE_THREAD_SANITIZER - static constexpr int kIdlePeriods = 60; -#else - // Memory consumption under ThreadSanitizer is a serious concern, - // so we release resources sooner. The value of 1 leads to 1 to 2 second - // delay before marking a thread as idle. - static const int kIdlePeriods = 1; -#endif - - private: -#if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX - // Futexes are defined by specification to be 32-bits. - // Thus std::atomic<int32_t> must be just an int32_t with lockfree methods. - std::atomic<int32_t> futex_; - static_assert(sizeof(int32_t) == sizeof(futex_), "Wrong size for futex"); - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR - // REQUIRES: mu_ must be held. - void InternalCondVarPoke(); - - pthread_mutex_t mu_; - pthread_cond_t cv_; - int waiter_count_; - int wakeup_count_; // Unclaimed wakeups. - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM - sem_t sem_; - // This seems superfluous, but for Poke() we need to cause spurious - // wakeups on the semaphore. Hence we can't actually use the - // semaphore's count. - std::atomic<int> wakeups_; - -#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32 - // WinHelper - Used to define utilities for accessing the lock and - // condition variable storage once the types are complete. - class WinHelper; - - // REQUIRES: WinHelper::GetLock(this) must be held. - void InternalCondVarPoke(); - - // We can't include Windows.h in our headers, so we use aligned charachter - // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE. - alignas(void*) unsigned char mu_storage_[sizeof(void*)]; - alignas(void*) unsigned char cv_storage_[sizeof(void*)]; - int waiter_count_; - int wakeup_count_; - -#else - #error Unknown ABSL_WAITER_MODE -#endif -}; - -} // namespace synchronization_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/lifetime_test.cc b/third_party/abseil_cpp/absl/synchronization/lifetime_test.cc deleted file mode 100644 index cc973a329071..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/lifetime_test.cc +++ /dev/null @@ -1,181 +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 <cstdlib> -#include <thread> // NOLINT(build/c++11), Abseil test -#include <type_traits> - -#include "absl/base/attributes.h" -#include "absl/base/const_init.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/mutex.h" -#include "absl/synchronization/notification.h" - -namespace { - -// A two-threaded test which checks that Mutex, CondVar, and Notification have -// correct basic functionality. The intent is to establish that they -// function correctly in various phases of construction and destruction. -// -// Thread one acquires a lock on 'mutex', wakes thread two via 'notification', -// then waits for 'state' to be set, as signalled by 'condvar'. -// -// Thread two waits on 'notification', then sets 'state' inside the 'mutex', -// signalling the change via 'condvar'. -// -// These tests use ABSL_RAW_CHECK to validate invariants, rather than EXPECT or -// ASSERT from gUnit, because we need to invoke them during global destructors, -// when gUnit teardown would have already begun. -void ThreadOne(absl::Mutex* mutex, absl::CondVar* condvar, - absl::Notification* notification, bool* state) { - // Test that the notification is in a valid initial state. - ABSL_RAW_CHECK(!notification->HasBeenNotified(), "invalid Notification"); - ABSL_RAW_CHECK(*state == false, "*state not initialized"); - - { - absl::MutexLock lock(mutex); - - notification->Notify(); - ABSL_RAW_CHECK(notification->HasBeenNotified(), "invalid Notification"); - - while (*state == false) { - condvar->Wait(mutex); - } - } -} - -void ThreadTwo(absl::Mutex* mutex, absl::CondVar* condvar, - absl::Notification* notification, bool* state) { - ABSL_RAW_CHECK(*state == false, "*state not initialized"); - - // Wake thread one - notification->WaitForNotification(); - ABSL_RAW_CHECK(notification->HasBeenNotified(), "invalid Notification"); - { - absl::MutexLock lock(mutex); - *state = true; - condvar->Signal(); - } -} - -// Launch thread 1 and thread 2, and block on their completion. -// If any of 'mutex', 'condvar', or 'notification' is nullptr, use a locally -// constructed instance instead. -void RunTests(absl::Mutex* mutex, absl::CondVar* condvar) { - absl::Mutex default_mutex; - absl::CondVar default_condvar; - absl::Notification notification; - if (!mutex) { - mutex = &default_mutex; - } - if (!condvar) { - condvar = &default_condvar; - } - bool state = false; - std::thread thread_one(ThreadOne, mutex, condvar, ¬ification, &state); - std::thread thread_two(ThreadTwo, mutex, condvar, ¬ification, &state); - thread_one.join(); - thread_two.join(); -} - -void TestLocals() { - absl::Mutex mutex; - absl::CondVar condvar; - RunTests(&mutex, &condvar); -} - -// Normal kConstInit usage -ABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit); -void TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); } - -// Global variables during start and termination -// -// In a translation unit, static storage duration variables are initialized in -// the order of their definitions, and destroyed in the reverse order of their -// definitions. We can use this to arrange for tests to be run on these objects -// before they are created, and after they are destroyed. - -using Function = void (*)(); - -class OnConstruction { - public: - explicit OnConstruction(Function fn) { fn(); } -}; - -class OnDestruction { - public: - explicit OnDestruction(Function fn) : fn_(fn) {} - ~OnDestruction() { fn_(); } - private: - Function fn_; -}; - -// These tests require that the compiler correctly supports C++11 constant -// initialization... but MSVC has a known regression since v19.10: -// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html -// TODO(epastor): Limit the affected range once MSVC fixes this bug. -#if defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900) -// kConstInit -// Test early usage. (Declaration comes first; definitions must appear after -// the test runner.) -extern absl::Mutex early_const_init_mutex; -// (Normally I'd write this +[], to make the cast-to-function-pointer explicit, -// but in some MSVC setups we support, lambdas provide conversion operators to -// different flavors of function pointers, making this trick ambiguous.) -OnConstruction test_early_const_init([] { - RunTests(&early_const_init_mutex, nullptr); -}); -// This definition appears before test_early_const_init, but it should be -// initialized first (due to constant initialization). Test that the object -// actually works when constructed this way. -ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit); - -// Furthermore, test that the const-init c'tor doesn't stomp over the state of -// a Mutex. Really, this is a test that the platform under test correctly -// supports C++11 constant initialization. (The constant-initialization -// constructors of globals "happen at link time"; memory is pre-initialized, -// before the constructors of either grab_lock or check_still_locked are run.) -extern absl::Mutex const_init_sanity_mutex; -OnConstruction grab_lock([]() ABSL_NO_THREAD_SAFETY_ANALYSIS { - const_init_sanity_mutex.Lock(); -}); -ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit); -OnConstruction check_still_locked([]() ABSL_NO_THREAD_SAFETY_ANALYSIS { - const_init_sanity_mutex.AssertHeld(); - const_init_sanity_mutex.Unlock(); -}); -#endif // defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900) - -// Test shutdown usage. (Declarations come first; definitions must appear after -// the test runner.) -extern absl::Mutex late_const_init_mutex; -// OnDestruction is being used here as a global variable, even though it has a -// non-trivial destructor. This is against the style guide. We're violating -// that rule here to check that the exception we allow for kConstInit is safe. -// NOLINTNEXTLINE -OnDestruction test_late_const_init([] { - RunTests(&late_const_init_mutex, nullptr); -}); -ABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit); - -} // namespace - -int main() { - TestLocals(); - TestConstInitGlobal(); - // Explicitly call exit(0) here, to make it clear that we intend for the - // above global object destructors to run. - std::exit(0); -} diff --git a/third_party/abseil_cpp/absl/synchronization/mutex.cc b/third_party/abseil_cpp/absl/synchronization/mutex.cc deleted file mode 100644 index 9e01393ca4df..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/mutex.cc +++ /dev/null @@ -1,2740 +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/synchronization/mutex.h" - -#ifdef _WIN32 -#include <windows.h> -#ifdef ERROR -#undef ERROR -#endif -#else -#include <fcntl.h> -#include <pthread.h> -#include <sched.h> -#include <sys/time.h> -#endif - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include <algorithm> -#include <atomic> -#include <cinttypes> -#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" -#include "absl/base/internal/cycleclock.h" -#include "absl/base/internal/hide_ptr.h" -#include "absl/base/internal/low_level_alloc.h" -#include "absl/base/internal/raw_logging.h" -#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" -#include "absl/synchronization/internal/graphcycles.h" -#include "absl/synchronization/internal/per_thread_sem.h" -#include "absl/time/time.h" - -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; -using absl::synchronization_internal::GraphId; -using absl::synchronization_internal::InvalidGraphId; -using absl::synchronization_internal::KernelTimeout; -using absl::synchronization_internal::PerThreadSem; - -extern "C" { -ABSL_ATTRIBUTE_WEAK void AbslInternalMutexYield() { std::this_thread::yield(); } -} // extern "C" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -#if defined(ABSL_HAVE_THREAD_SANITIZER) -constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore; -#else -constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort; -#endif - -ABSL_CONST_INIT std::atomic<OnDeadlockCycle> synch_deadlock_detection( - kDeadlockDetectionDefault); -ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false); - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES -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; -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES - absl::base_internal::AtomicHook<void (*)(const char *msg, const void *cv)> - cond_var_tracer; -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook< - bool (*)(const void *pc, char *out, int out_size)> - symbolizer(absl::Symbolize); - -} // namespace - -static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu, - bool locking, bool trylock, - bool read_lock); - -void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)) { - submit_profile_data.Store(fn); -} - -void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj, - int64_t wait_cycles)) { - mutex_tracer.Store(fn); -} - -void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv)) { - cond_var_tracer.Store(fn); -} - -void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) { - symbolizer.Store(fn); -} - -struct ABSL_CACHELINE_ALIGNED MutexGlobals { - absl::once_flag once; - int num_cpus = 0; - int spinloop_iterations = 0; -}; - -static const MutexGlobals& GetMutexGlobals() { - ABSL_CONST_INIT static MutexGlobals data; - absl::base_internal::LowLevelCallOnce(&data.once, [&]() { - data.num_cpus = absl::base_internal::NumCPUs(); - data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0; - }); - return data; -} - -// Spinlock delay on iteration c. Returns new c. -namespace { - enum DelayMode { AGGRESSIVE, GENTLE }; -}; - -namespace synchronization_internal { -int MutexDelay(int32_t c, int 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. - const int32_t limit = - GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0; - if (c < limit) { - // Spin. - c++; - } else { - SchedulingGuard::ScopedEnable enable_rescheduling; - ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); - if (c == limit) { - // Yield once. - AbslInternalMutexYield(); - c++; - } else { - // Then wait. - absl::SleepFor(absl::Microseconds(10)); - c = 0; - } - ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0); - } - return c; -} -} // namespace synchronization_internal - -// --------------------------Generic atomic ops -// Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to -// "*pv | bits" if necessary. Wait until (*pv & wait_until_clear)==0 -// before making any change. -// This is used to set flags in mutex and condition variable words. -static void AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits, - intptr_t wait_until_clear) { - intptr_t v; - do { - v = pv->load(std::memory_order_relaxed); - } while ((v & bits) != bits && - ((v & wait_until_clear) != 0 || - !pv->compare_exchange_weak(v, v | bits, - std::memory_order_release, - std::memory_order_relaxed))); -} - -// Ensure that "(*pv & bits) == 0" by doing an atomic update of "*pv" to -// "*pv & ~bits" if necessary. Wait until (*pv & wait_until_clear)==0 -// before making any change. -// This is used to unset flags in mutex and condition variable words. -static void AtomicClearBits(std::atomic<intptr_t>* pv, intptr_t bits, - intptr_t wait_until_clear) { - intptr_t v; - do { - v = pv->load(std::memory_order_relaxed); - } while ((v & bits) != 0 && - ((v & wait_until_clear) != 0 || - !pv->compare_exchange_weak(v, v & ~bits, - std::memory_order_release, - std::memory_order_relaxed))); -} - -//------------------------------------------------------------------ - -// Data for doing deadlock detection. -ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); - -// Graph used to detect deadlocks. -ABSL_CONST_INIT static GraphCycles *deadlock_graph - ABSL_GUARDED_BY(deadlock_graph_mu) ABSL_PT_GUARDED_BY(deadlock_graph_mu); - -//------------------------------------------------------------------ -// An event mechanism for debugging mutex use. -// It also allows mutexes to be given names for those who can't handle -// addresses, and instead like to give their data structures names like -// "Henry", "Fido", or "Rupert IV, King of Yondavia". - -namespace { // to prevent name pollution -enum { // Mutex and CondVar events passed as "ev" to PostSynchEvent - // Mutex events - SYNCH_EV_TRYLOCK_SUCCESS, - SYNCH_EV_TRYLOCK_FAILED, - SYNCH_EV_READERTRYLOCK_SUCCESS, - SYNCH_EV_READERTRYLOCK_FAILED, - SYNCH_EV_LOCK, - SYNCH_EV_LOCK_RETURNING, - SYNCH_EV_READERLOCK, - SYNCH_EV_READERLOCK_RETURNING, - SYNCH_EV_UNLOCK, - SYNCH_EV_READERUNLOCK, - - // CondVar events - SYNCH_EV_WAIT, - SYNCH_EV_WAIT_RETURNING, - SYNCH_EV_SIGNAL, - SYNCH_EV_SIGNALALL, -}; - -enum { // Event flags - SYNCH_F_R = 0x01, // reader event - SYNCH_F_LCK = 0x02, // PostSynchEvent called with mutex held - SYNCH_F_TRY = 0x04, // TryLock or ReaderTryLock - SYNCH_F_UNLOCK = 0x08, // Unlock or ReaderUnlock - - SYNCH_F_LCK_W = SYNCH_F_LCK, - SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R, -}; -} // anonymous namespace - -// Properties of the events. -static const struct { - int flags; - const char *msg; -} event_properties[] = { - {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "}, - {0, "TryLock failed "}, - {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "}, - {0, "ReaderTryLock failed "}, - {0, "Lock blocking "}, - {SYNCH_F_LCK_W, "Lock returning "}, - {0, "ReaderLock blocking "}, - {SYNCH_F_LCK_R, "ReaderLock returning "}, - {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "}, - {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "}, - {0, "Wait on "}, - {0, "Wait unblocked "}, - {0, "Signal on "}, - {0, "SignalAll on "}, -}; - -ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); - -// Hash table size; should be prime > 2. -// Can't be too small, as it's used for deadlock detection information. -static constexpr uint32_t kNSynchEvent = 1031; - -static struct SynchEvent { // this is a trivial hash table for the events - // struct is freed when refcount reaches 0 - int refcount ABSL_GUARDED_BY(synch_event_mu); - - // buckets have linear, 0-terminated chains - SynchEvent *next ABSL_GUARDED_BY(synch_event_mu); - - // Constant after initialization - uintptr_t masked_addr; // object at this address is called "name" - - // No explicit synchronization used. Instead we assume that the - // client who enables/disables invariants/logging on a Mutex does so - // while the Mutex is not being concurrently accessed by others. - void (*invariant)(void *arg); // called on each event - void *arg; // first arg to (*invariant)() - bool log; // logging turned on - - // Constant after initialization - char name[1]; // actually longer---NUL-terminated string -} * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu); - -// Ensure that the object at "addr" has a SynchEvent struct associated with it, -// set "bits" in the word there (waiting until lockbit is clear before doing -// so), and return a refcounted reference that will remain valid until -// UnrefSynchEvent() is called. If a new SynchEvent is allocated, -// the string name is copied into it. -// When used with a mutex, the caller should also ensure that kMuEvent -// is set in the mutex word, and similarly for condition variables and kCVEvent. -static SynchEvent *EnsureSynchEvent(std::atomic<intptr_t> *addr, - const char *name, intptr_t bits, - intptr_t lockbit) { - uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent; - SynchEvent *e; - // first look for existing SynchEvent struct.. - synch_event_mu.Lock(); - for (e = synch_event[h]; - e != nullptr && e->masked_addr != base_internal::HidePtr(addr); - e = e->next) { - } - if (e == nullptr) { // no SynchEvent struct found; make one. - if (name == nullptr) { - name = ""; - } - size_t l = strlen(name); - e = reinterpret_cast<SynchEvent *>( - base_internal::LowLevelAlloc::Alloc(sizeof(*e) + l)); - e->refcount = 2; // one for return value, one for linked list - e->masked_addr = base_internal::HidePtr(addr); - e->invariant = nullptr; - e->arg = nullptr; - e->log = false; - strcpy(e->name, name); // NOLINT(runtime/printf) - e->next = synch_event[h]; - AtomicSetBits(addr, bits, lockbit); - synch_event[h] = e; - } else { - e->refcount++; // for return value - } - synch_event_mu.Unlock(); - return e; -} - -// Deallocate the SynchEvent *e, whose refcount has fallen to zero. -static void DeleteSynchEvent(SynchEvent *e) { - base_internal::LowLevelAlloc::Free(e); -} - -// Decrement the reference count of *e, or do nothing if e==null. -static void UnrefSynchEvent(SynchEvent *e) { - if (e != nullptr) { - synch_event_mu.Lock(); - bool del = (--(e->refcount) == 0); - synch_event_mu.Unlock(); - if (del) { - DeleteSynchEvent(e); - } - } -} - -// Forget the mapping from the object (Mutex or CondVar) at address addr -// to SynchEvent object, and clear "bits" in its word (waiting until lockbit -// is clear before doing so). -static void ForgetSynchEvent(std::atomic<intptr_t> *addr, intptr_t bits, - intptr_t lockbit) { - uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent; - SynchEvent **pe; - SynchEvent *e; - synch_event_mu.Lock(); - for (pe = &synch_event[h]; - (e = *pe) != nullptr && e->masked_addr != base_internal::HidePtr(addr); - pe = &e->next) { - } - bool del = false; - if (e != nullptr) { - *pe = e->next; - del = (--(e->refcount) == 0); - } - AtomicClearBits(addr, bits, lockbit); - synch_event_mu.Unlock(); - if (del) { - DeleteSynchEvent(e); - } -} - -// Return a refcounted reference to the SynchEvent of the object at address -// "addr", if any. The pointer returned is valid until the UnrefSynchEvent() is -// called. -static SynchEvent *GetSynchEvent(const void *addr) { - uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent; - SynchEvent *e; - synch_event_mu.Lock(); - for (e = synch_event[h]; - e != nullptr && e->masked_addr != base_internal::HidePtr(addr); - e = e->next) { - } - if (e != nullptr) { - e->refcount++; - } - synch_event_mu.Unlock(); - return e; -} - -// Called when an event "ev" occurs on a Mutex of CondVar "obj" -// if event recording is on -static void PostSynchEvent(void *obj, int ev) { - SynchEvent *e = GetSynchEvent(obj); - // logging is on if event recording is on and either there's no event struct, - // or it explicitly says to log - if (e == nullptr || e->log) { - void *pcs[40]; - int n = absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 1); - // A buffer with enough space for the ASCII for all the PCs, even on a - // 64-bit machine. - char buffer[ABSL_ARRAYSIZE(pcs) * 24]; - int pos = snprintf(buffer, sizeof (buffer), " @"); - for (int i = 0; i != n; i++) { - pos += snprintf(&buffer[pos], sizeof (buffer) - pos, " %p", pcs[i]); - } - ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj, - (e == nullptr ? "" : e->name), buffer); - } - const int flags = event_properties[ev].flags; - if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) { - // Calling the invariant as is causes problems under ThreadSanitizer. - // We are currently inside of Mutex Lock/Unlock and are ignoring all - // memory accesses and synchronization. If the invariant transitively - // synchronizes something else and we ignore the synchronization, we will - // get false positive race reports later. - // Reuse EvalConditionAnnotated to properly call into user code. - struct local { - static bool pred(SynchEvent *ev) { - (*ev->invariant)(ev->arg); - return false; - } - }; - Condition cond(&local::pred, e); - Mutex *mu = static_cast<Mutex *>(obj); - const bool locking = (flags & SYNCH_F_UNLOCK) == 0; - const bool trylock = (flags & SYNCH_F_TRY) != 0; - const bool read_lock = (flags & SYNCH_F_R) != 0; - EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock); - } - UnrefSynchEvent(e); -} - -//------------------------------------------------------------------ - -// The SynchWaitParams struct encapsulates the way in which a thread is waiting: -// whether it has a timeout, the condition, exclusive/shared, and whether a -// condition variable wait has an associated Mutex (as opposed to another -// type of lock). It also points to the PerThreadSynch struct of its thread. -// cv_word tells Enqueue() to enqueue on a CondVar using CondVarEnqueue(). -// -// This structure is held on the stack rather than directly in -// PerThreadSynch because a thread can be waiting on multiple Mutexes if, -// while waiting on one Mutex, the implementation calls a client callback -// (such as a Condition function) that acquires another Mutex. We don't -// strictly need to allow this, but programmers become confused if we do not -// allow them to use functions such a LOG() within Condition functions. The -// PerThreadSynch struct points at the most recent SynchWaitParams struct when -// the thread is on a Mutex's waiter queue. -struct SynchWaitParams { - SynchWaitParams(Mutex::MuHow how_arg, const Condition *cond_arg, - KernelTimeout timeout_arg, Mutex *cvmu_arg, - PerThreadSynch *thread_arg, - std::atomic<intptr_t> *cv_word_arg) - : how(how_arg), - cond(cond_arg), - timeout(timeout_arg), - cvmu(cvmu_arg), - thread(thread_arg), - cv_word(cv_word_arg), - contention_start_cycles(base_internal::CycleClock::Now()) {} - - const Mutex::MuHow how; // How this thread needs to wait. - const Condition *cond; // The condition that this thread is waiting for. - // In Mutex, this field is set to zero if a timeout - // expires. - KernelTimeout timeout; // timeout expiry---absolute time - // In Mutex, this field is set to zero if a timeout - // expires. - Mutex *const cvmu; // used for transfer from cond var to mutex - PerThreadSynch *const thread; // thread that is waiting - - // If not null, thread should be enqueued on the CondVar whose state - // word is cv_word instead of queueing normally on the Mutex. - std::atomic<intptr_t> *cv_word; - - int64_t contention_start_cycles; // Time (in cycles) when this thread started - // to contend for the mutex. -}; - -struct SynchLocksHeld { - int n; // number of valid entries in locks[] - bool overflow; // true iff we overflowed the array at some point - struct { - Mutex *mu; // lock acquired - int32_t count; // times acquired - GraphId id; // deadlock_graph id of acquired lock - } locks[40]; - // If a thread overfills the array during deadlock detection, we - // continue, discarding information as needed. If no overflow has - // taken place, we can provide more error checking, such as - // detecting when a thread releases a lock it does not hold. -}; - -// A sentinel value in lists that is not 0. -// A 0 value is used to mean "not on a list". -static PerThreadSynch *const kPerThreadSynchNull = - reinterpret_cast<PerThreadSynch *>(1); - -static SynchLocksHeld *LocksHeldAlloc() { - SynchLocksHeld *ret = reinterpret_cast<SynchLocksHeld *>( - base_internal::LowLevelAlloc::Alloc(sizeof(SynchLocksHeld))); - ret->n = 0; - ret->overflow = false; - return ret; -} - -// Return the PerThreadSynch-struct for this thread. -static PerThreadSynch *Synch_GetPerThread() { - ThreadIdentity *identity = GetOrCreateCurrentThreadIdentity(); - return &identity->per_thread_synch; -} - -static PerThreadSynch *Synch_GetPerThreadAnnotated(Mutex *mu) { - if (mu) { - ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - } - PerThreadSynch *w = Synch_GetPerThread(); - if (mu) { - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - } - return w; -} - -static SynchLocksHeld *Synch_GetAllLocks() { - PerThreadSynch *s = Synch_GetPerThread(); - if (s->all_locks == nullptr) { - s->all_locks = LocksHeldAlloc(); // Freed by ReclaimThreadIdentity. - } - return s->all_locks; -} - -// Post on "w"'s associated PerThreadSem. -inline void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) { - if (mu) { - ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - } - PerThreadSem::Post(w->thread_identity()); - if (mu) { - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - } -} - -// Wait on "w"'s associated PerThreadSem; returns false if timeout expired. -bool Mutex::DecrementSynchSem(Mutex *mu, PerThreadSynch *w, KernelTimeout t) { - if (mu) { - ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - } - assert(w == Synch_GetPerThread()); - static_cast<void>(w); - bool res = PerThreadSem::Wait(t); - if (mu) { - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - } - return res; -} - -// We're in a fatal signal handler that hopes to use Mutex and to get -// lucky by not deadlocking. We try to improve its chances of success -// by effectively disabling some of the consistency checks. This will -// prevent certain ABSL_RAW_CHECK() statements from being triggered when -// re-rentry is detected. The ABSL_RAW_CHECK() statements are those in the -// Mutex code checking that the "waitp" field has not been reused. -void Mutex::InternalAttemptToUseMutexInFatalSignalHandler() { - // Fix the per-thread state only if it exists. - ThreadIdentity *identity = CurrentThreadIdentityIfPresent(); - if (identity != nullptr) { - identity->per_thread_synch.suppress_fatal_errors = true; - } - // Don't do deadlock detection when we are already failing. - synch_deadlock_detection.store(OnDeadlockCycle::kIgnore, - std::memory_order_release); -} - -// --------------------------time support - -// Return the current time plus the timeout. Use the same clock as -// PerThreadSem::Wait() for consistency. Unfortunately, we don't have -// such a choice when a deadline is given directly. -static absl::Time DeadlineFromTimeout(absl::Duration timeout) { -#ifndef _WIN32 - struct timeval tv; - gettimeofday(&tv, nullptr); - return absl::TimeFromTimeval(tv) + timeout; -#else - return absl::Now() + timeout; -#endif -} - -// --------------------------Mutexes - -// In the layout below, the msb of the bottom byte is currently unused. Also, -// the following constraints were considered in choosing the layout: -// o Both the debug allocator's "uninitialized" and "freed" patterns (0xab and -// 0xcd) are illegal: reader and writer lock both held. -// o kMuWriter and kMuEvent should exceed kMuDesig and kMuWait, to enable the -// bit-twiddling trick in Mutex::Unlock(). -// o kMuWriter / kMuReader == kMuWrWait / kMuWait, -// to enable the bit-twiddling trick in CheckForMutexCorruption(). -static const intptr_t kMuReader = 0x0001L; // a reader holds the lock -static const intptr_t kMuDesig = 0x0002L; // there's a designated waker -static const intptr_t kMuWait = 0x0004L; // threads are waiting -static const intptr_t kMuWriter = 0x0008L; // a writer holds the lock -static const intptr_t kMuEvent = 0x0010L; // record this mutex's events -// INVARIANT1: there's a thread that was blocked on the mutex, is -// no longer, yet has not yet acquired the mutex. If there's a -// designated waker, all threads can avoid taking the slow path in -// unlock because the designated waker will subsequently acquire -// the lock and wake someone. To maintain INVARIANT1 the bit is -// set when a thread is unblocked(INV1a), and threads that were -// unblocked reset the bit when they either acquire or re-block -// (INV1b). -static const intptr_t kMuWrWait = 0x0020L; // runnable writer is waiting - // for a reader -static const intptr_t kMuSpin = 0x0040L; // spinlock protects wait list -static const intptr_t kMuLow = 0x00ffL; // mask all mutex bits -static const intptr_t kMuHigh = ~kMuLow; // mask pointer/reader count - -// Hack to make constant values available to gdb pretty printer -enum { - kGdbMuSpin = kMuSpin, - kGdbMuEvent = kMuEvent, - kGdbMuWait = kMuWait, - kGdbMuWriter = kMuWriter, - kGdbMuDesig = kMuDesig, - kGdbMuWrWait = kMuWrWait, - kGdbMuReader = kMuReader, - kGdbMuLow = kMuLow, -}; - -// kMuWrWait implies kMuWait. -// kMuReader and kMuWriter are mutually exclusive. -// If kMuReader is zero, there are no readers. -// Otherwise, if kMuWait is zero, the high order bits contain a count of the -// number of readers. Otherwise, the reader count is held in -// PerThreadSynch::readers of the most recently queued waiter, again in the -// bits above kMuLow. -static const intptr_t kMuOne = 0x0100; // a count of one reader - -// flags passed to Enqueue and LockSlow{,WithTimeout,Loop} -static const int kMuHasBlocked = 0x01; // already blocked (MUST == 1) -static const int kMuIsCond = 0x02; // conditional waiter (CV or Condition) - -static_assert(PerThreadSynch::kAlignment > kMuLow, - "PerThreadSynch::kAlignment must be greater than kMuLow"); - -// This struct contains various bitmasks to be used in -// acquiring and releasing a mutex in a particular mode. -struct MuHowS { - // if all the bits in fast_need_zero are zero, the lock can be acquired by - // adding fast_add and oring fast_or. The bit kMuDesig should be reset iff - // this is the designated waker. - intptr_t fast_need_zero; - intptr_t fast_or; - intptr_t fast_add; - - intptr_t slow_need_zero; // fast_need_zero with events (e.g. logging) - - intptr_t slow_inc_need_zero; // if all the bits in slow_inc_need_zero are - // zero a reader can acquire a read share by - // setting the reader bit and incrementing - // the reader count (in last waiter since - // we're now slow-path). kMuWrWait be may - // be ignored if we already waited once. -}; - -static const MuHowS kSharedS = { - // shared or read lock - kMuWriter | kMuWait | kMuEvent, // fast_need_zero - kMuReader, // fast_or - kMuOne, // fast_add - kMuWriter | kMuWait, // slow_need_zero - kMuSpin | kMuWriter | kMuWrWait, // slow_inc_need_zero -}; -static const MuHowS kExclusiveS = { - // exclusive or write lock - kMuWriter | kMuReader | kMuEvent, // fast_need_zero - kMuWriter, // fast_or - 0, // fast_add - kMuWriter | kMuReader, // slow_need_zero - ~static_cast<intptr_t>(0), // slow_inc_need_zero -}; -static const Mutex::MuHow kShared = &kSharedS; // shared lock -static const Mutex::MuHow kExclusive = &kExclusiveS; // exclusive lock - -#ifdef NDEBUG -static constexpr bool kDebugMode = false; -#else -static constexpr bool kDebugMode = true; -#endif - -#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE -static unsigned TsanFlags(Mutex::MuHow how) { - return how == kShared ? __tsan_mutex_read_lock : 0; -} -#endif - -static bool DebugOnlyIsExiting() { - return false; -} - -Mutex::~Mutex() { - intptr_t v = mu_.load(std::memory_order_relaxed); - if ((v & kMuEvent) != 0 && !DebugOnlyIsExiting()) { - ForgetSynchEvent(&this->mu_, kMuEvent, kMuSpin); - } - if (kDebugMode) { - this->ForgetDeadlockInfo(); - } - ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); -} - -void Mutex::EnableDebugLog(const char *name) { - SynchEvent *e = EnsureSynchEvent(&this->mu_, name, kMuEvent, kMuSpin); - e->log = true; - UnrefSynchEvent(e); -} - -void EnableMutexInvariantDebugging(bool enabled) { - synch_check_invariants.store(enabled, std::memory_order_release); -} - -void Mutex::EnableInvariantDebugging(void (*invariant)(void *), - void *arg) { - if (synch_check_invariants.load(std::memory_order_acquire) && - invariant != nullptr) { - SynchEvent *e = EnsureSynchEvent(&this->mu_, nullptr, kMuEvent, kMuSpin); - e->invariant = invariant; - e->arg = arg; - UnrefSynchEvent(e); - } -} - -void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) { - synch_deadlock_detection.store(mode, std::memory_order_release); -} - -// Return true iff threads x and y are waiting on the same condition for the -// same type of lock. Requires that x and y be waiting on the same Mutex -// queue. -static bool MuSameCondition(PerThreadSynch *x, PerThreadSynch *y) { - return x->waitp->how == y->waitp->how && - Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond); -} - -// Given the contents of a mutex word containing a PerThreadSynch pointer, -// return the pointer. -static inline PerThreadSynch *GetPerThreadSynch(intptr_t v) { - return reinterpret_cast<PerThreadSynch *>(v & kMuHigh); -} - -// The next several routines maintain the per-thread next and skip fields -// used in the Mutex waiter queue. -// The queue is a circular singly-linked list, of which the "head" is the -// last element, and head->next if the first element. -// The skip field has the invariant: -// For thread x, x->skip is one of: -// - invalid (iff x is not in a Mutex wait queue), -// - null, or -// - a pointer to a distinct thread waiting later in the same Mutex queue -// such that all threads in [x, x->skip] have the same condition and -// lock type (MuSameCondition() is true for all pairs in [x, x->skip]). -// In addition, if x->skip is valid, (x->may_skip || x->skip == null) -// -// By the spec of MuSameCondition(), it is not necessary when removing the -// first runnable thread y from the front a Mutex queue to adjust the skip -// field of another thread x because if x->skip==y, x->skip must (have) become -// invalid before y is removed. The function TryRemove can remove a specified -// thread from an arbitrary position in the queue whether runnable or not, so -// it fixes up skip fields that would otherwise be left dangling. -// The statement -// if (x->may_skip && MuSameCondition(x, x->next)) { x->skip = x->next; } -// 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; } -// maintains the invariant. - -// Returns the last thread y in a mutex waiter queue such that all threads in -// [x, y] inclusive share the same condition. Sets skip fields of some threads -// in that range to optimize future evaluation of Skip() on x values in -// the range. Requires thread x is in a mutex waiter queue. -// The locking is unusual. Skip() is called under these conditions: -// - spinlock is held in call from Enqueue(), with maybe_unlocking == false -// - Mutex is held in call from UnlockSlow() by last unlocker, with -// maybe_unlocking == true -// - both Mutex and spinlock are held in call from DequeueAllWakeable() (from -// UnlockSlow()) and TryRemove() -// These cases are mutually exclusive, so Skip() never runs concurrently -// with itself on the same Mutex. The skip chain is used in these other places -// that cannot occur concurrently: -// - FixSkip() (from TryRemove()) - spinlock and Mutex are held) -// - Dequeue() (with spinlock and Mutex held) -// - UnlockSlow() (with spinlock and Mutex held) -// A more complex case is Enqueue() -// - Enqueue() (with spinlock held and maybe_unlocking == false) -// This is the first case in which Skip is called, above. -// - Enqueue() (without spinlock held; but queue is empty and being freshly -// formed) -// - Enqueue() (with spinlock held and maybe_unlocking == true) -// The first case has mutual exclusion, and the second isolation through -// working on an otherwise unreachable data structure. -// In the last case, Enqueue() is required to change no skip/next pointers -// except those in the added node and the former "head" node. This implies -// that the new node is added after head, and so must be the new head or the -// new front of the queue. -static PerThreadSynch *Skip(PerThreadSynch *x) { - PerThreadSynch *x0 = nullptr; - PerThreadSynch *x1 = x; - PerThreadSynch *x2 = x->skip; - if (x2 != nullptr) { - // Each iteration attempts to advance sequence (x0,x1,x2) to next sequence - // such that x1 == x0->skip && x2 == x1->skip - while ((x0 = x1, x1 = x2, x2 = x2->skip) != nullptr) { - x0->skip = x2; // short-circuit skip from x0 to x2 - } - x->skip = x1; // short-circuit skip from x to result - } - return x1; -} - -// "ancestor" appears before "to_be_removed" in the same Mutex waiter queue. -// The latter is going to be removed out of order, because of a timeout. -// Check whether "ancestor" has a skip field pointing to "to_be_removed", -// and fix it if it does. -static void FixSkip(PerThreadSynch *ancestor, PerThreadSynch *to_be_removed) { - if (ancestor->skip == to_be_removed) { // ancestor->skip left dangling - if (to_be_removed->skip != nullptr) { - ancestor->skip = to_be_removed->skip; // can skip past to_be_removed - } else if (ancestor->next != to_be_removed) { // they are not adjacent - ancestor->skip = ancestor->next; // can skip one past ancestor - } else { - ancestor->skip = nullptr; // can't skip at all - } - } -} - -static void CondVarEnqueue(SynchWaitParams *waitp); - -// Enqueue thread "waitp->thread" on a waiter queue. -// Called with mutex spinlock held if head != nullptr -// If head==nullptr and waitp->cv_word==nullptr, then Enqueue() is -// idempotent; it alters no state associated with the existing (empty) -// queue. -// -// If waitp->cv_word == nullptr, queue the thread at either the front or -// the end (according to its priority) of the circular mutex waiter queue whose -// head is "head", and return the new head. mu is the previous mutex state, -// which contains the reader count (perhaps adjusted for the operation in -// progress) if the list was empty and a read lock held, and the holder hint if -// the list was empty and a write lock held. (flags & kMuIsCond) indicates -// whether this thread was transferred from a CondVar or is waiting for a -// non-trivial condition. In this case, Enqueue() never returns nullptr -// -// If waitp->cv_word != nullptr, CondVarEnqueue() is called, and "head" is -// returned. This mechanism is used by CondVar to queue a thread on the -// condition variable queue instead of the mutex queue in implementing Wait(). -// In this case, Enqueue() can return nullptr (if head==nullptr). -static PerThreadSynch *Enqueue(PerThreadSynch *head, - SynchWaitParams *waitp, intptr_t mu, int flags) { - // If we have been given a cv_word, call CondVarEnqueue() and return - // the previous head of the Mutex waiter queue. - if (waitp->cv_word != nullptr) { - CondVarEnqueue(waitp); - return head; - } - - PerThreadSynch *s = waitp->thread; - ABSL_RAW_CHECK( - s->waitp == nullptr || // normal case - s->waitp == waitp || // Fer()---transfer from condition variable - s->suppress_fatal_errors, - "detected illegal recursion into Mutex code"); - s->waitp = waitp; - s->skip = nullptr; // maintain skip invariant (see above) - s->may_skip = true; // always true on entering queue - s->wake = false; // not being woken - s->cond_waiter = ((flags & kMuIsCond) != 0); - if (head == nullptr) { // s is the only waiter - s->next = s; // it's the only entry in the cycle - s->readers = mu; // reader count is from mu word - s->maybe_unlocking = false; // no one is searching an empty list - head = s; // s is new head - } else { - PerThreadSynch *enqueue_after = nullptr; // we'll put s after this element -#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM - int64_t now_cycles = base_internal::CycleClock::Now(); - if (s->next_priority_read_cycles < now_cycles) { - // Every so often, update our idea of the thread's priority. - // pthread_getschedparam() is 5% of the block/wakeup time; - // base_internal::CycleClock::Now() is 0.5%. - int policy; - struct sched_param param; - const int err = pthread_getschedparam(pthread_self(), &policy, ¶m); - if (err != 0) { - ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err); - } else { - s->priority = param.sched_priority; - s->next_priority_read_cycles = - now_cycles + - static_cast<int64_t>(base_internal::CycleClock::Frequency()); - } - } - if (s->priority > head->priority) { // s's priority is above head's - // try to put s in priority-fifo order, or failing that at the front. - if (!head->maybe_unlocking) { - // No unlocker can be scanning the queue, so we can insert between - // skip-chains, and within a skip-chain if it has the same condition as - // s. We insert in priority-fifo order, examining the end of every - // skip-chain, plus every element with the same condition as s. - PerThreadSynch *advance_to = head; // next value of enqueue_after - PerThreadSynch *cur; // successor of enqueue_after - do { - enqueue_after = advance_to; - cur = enqueue_after->next; // this advance ensures progress - advance_to = Skip(cur); // normally, advance to end of skip chain - // (side-effect: optimizes skip chain) - if (advance_to != cur && s->priority > advance_to->priority && - MuSameCondition(s, cur)) { - // but this skip chain is not a singleton, s has higher priority - // than its tail and has the same condition as the chain, - // so we can insert within the skip-chain - advance_to = cur; // advance by just one - } - } while (s->priority <= advance_to->priority); - // termination guaranteed because s->priority > head->priority - // and head is the end of a skip chain - } else if (waitp->how == kExclusive && - Condition::GuaranteedEqual(waitp->cond, nullptr)) { - // An unlocker could be scanning the queue, but we know it will recheck - // the queue front for writers that have no condition, which is what s - // is, so an insert at front is safe. - enqueue_after = head; // add after head, at front - } - } -#endif - if (enqueue_after != nullptr) { - s->next = enqueue_after->next; - enqueue_after->next = s; - - // enqueue_after can be: head, Skip(...), or cur. - // The first two imply enqueue_after->skip == nullptr, and - // the last is used only if MuSameCondition(s, cur). - // We require this because clearing enqueue_after->skip - // is impossible; enqueue_after's predecessors might also - // incorrectly skip over s if we were to allow other - // insertion points. - ABSL_RAW_CHECK( - enqueue_after->skip == nullptr || MuSameCondition(enqueue_after, s), - "Mutex Enqueue failure"); - - if (enqueue_after != head && enqueue_after->may_skip && - MuSameCondition(enqueue_after, enqueue_after->next)) { - // enqueue_after can skip to its new successor, s - enqueue_after->skip = enqueue_after->next; - } - if (MuSameCondition(s, s->next)) { // s->may_skip is known to be true - s->skip = s->next; // s may skip to its successor - } - } else { // enqueue not done any other way, so - // we're inserting s at the back - // s will become new head; copy data from head into it - s->next = head->next; // add s after head - head->next = s; - s->readers = head->readers; // reader count is from previous head - s->maybe_unlocking = head->maybe_unlocking; // same for unlock hint - if (head->may_skip && MuSameCondition(head, s)) { - // head now has successor; may skip - head->skip = s; - } - head = s; // s is new head - } - } - s->state.store(PerThreadSynch::kQueued, std::memory_order_relaxed); - return head; -} - -// Dequeue the successor pw->next of thread pw from the Mutex waiter queue -// whose last element is head. The new head element is returned, or null -// if the list is made empty. -// Dequeue is called with both spinlock and Mutex held. -static PerThreadSynch *Dequeue(PerThreadSynch *head, PerThreadSynch *pw) { - PerThreadSynch *w = pw->next; - pw->next = w->next; // snip w out of list - if (head == w) { // we removed the head - head = (pw == w) ? nullptr : pw; // either emptied list, or pw is new head - } else if (pw != head && MuSameCondition(pw, pw->next)) { - // pw can skip to its new successor - if (pw->next->skip != - nullptr) { // either skip to its successors skip target - pw->skip = pw->next->skip; - } else { // or to pw's successor - pw->skip = pw->next; - } - } - return head; -} - -// Traverse the elements [ pw->next, h] of the circular list whose last element -// is head. -// Remove all elements with wake==true and place them in the -// singly-linked list wake_list in the order found. Assumes that -// there is only one such element if the element has how == kExclusive. -// Return the new head. -static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, - PerThreadSynch *pw, - PerThreadSynch **wake_tail) { - PerThreadSynch *orig_h = head; - PerThreadSynch *w = pw->next; - bool skipped = false; - do { - if (w->wake) { // remove this element - ABSL_RAW_CHECK(pw->skip == nullptr, "bad skip in DequeueAllWakeable"); - // we're removing pw's successor so either pw->skip is zero or we should - // already have removed pw since if pw->skip!=null, pw has the same - // condition as w. - head = Dequeue(head, pw); - w->next = *wake_tail; // keep list terminated - *wake_tail = w; // add w to wake_list; - wake_tail = &w->next; // next addition to end - if (w->waitp->how == kExclusive) { // wake at most 1 writer - break; - } - } else { // not waking this one; skip - pw = Skip(w); // skip as much as possible - skipped = true; - } - w = pw->next; - // We want to stop processing after we've considered the original head, - // orig_h. We can't test for w==orig_h in the loop because w may skip over - // it; we are guaranteed only that w's predecessor will not skip over - // orig_h. When we've considered orig_h, either we've processed it and - // removed it (so orig_h != head), or we considered it and skipped it (so - // skipped==true && pw == head because skipping from head always skips by - // just one, leaving pw pointing at head). So we want to - // continue the loop with the negation of that expression. - } while (orig_h == head && (pw != head || !skipped)); - return 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 && - mu_.compare_exchange_strong(v, v | kMuSpin | kMuWriter, - std::memory_order_acquire, - std::memory_order_relaxed)) { - PerThreadSynch *h = GetPerThreadSynch(v); - if (h != nullptr) { - PerThreadSynch *pw = h; // pw is w's predecessor - PerThreadSynch *w; - if ((w = pw->next) != s) { // search for thread, - do { // processing at least one element - 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 their condition differs from s - } else { // seeking same condition - FixSkip(w, s); // fix up any skip pointer from w to s - pw = w; - } - // don't search further if we found the thread, or we're about to - // process the first thread again. - } while ((w = pw->next) != s && pw != h); - } - if (w == s) { // found thread; remove it - // pw->skip may be non-zero here; the loop above ensured that - // no ancestor of s can skip to s, so removal is safe anyway. - h = Dequeue(h, pw); - s->next = nullptr; - s->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - } - } - intptr_t nv; - do { // release spinlock and lock - v = mu_.load(std::memory_order_relaxed); - nv = v & (kMuDesig | kMuEvent); - if (h != nullptr) { - nv |= kMuWait | reinterpret_cast<intptr_t>(h); - h->readers = 0; // we hold writer lock - h->maybe_unlocking = false; // finished unlocking - } - } while (!mu_.compare_exchange_weak(v, nv, - std::memory_order_release, - std::memory_order_relaxed)); - } -} - -// Wait until thread "s", which must be the current thread, is removed from the -// this mutex's waiter queue. If "s->waitp->timeout" has a timeout, wake up -// if the wait extends past the absolute time specified, even if "s" is still -// on the mutex queue. In this case, remove "s" from the queue and return -// true, otherwise return false. -ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { - while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { - if (!DecrementSynchSem(this, s, s->waitp->timeout)) { - // After a timeout, we go into a spin loop until we remove ourselves - // from the queue, or someone else removes us. We can't be sure to be - // able to remove ourselves in a single lock acquisition because this - // mutex may be held, and the holder has the right to read the centre - // of the waiter queue without holding the spinlock. - this->TryRemove(s); - int c = 0; - while (s->next != nullptr) { - c = synchronization_internal::MutexDelay(c, GENTLE); - this->TryRemove(s); - } - if (kDebugMode) { - // This ensures that we test the case that TryRemove() is called when s - // is not on the queue. - this->TryRemove(s); - } - s->waitp->timeout = KernelTimeout::Never(); // timeout is satisfied - s->waitp->cond = nullptr; // condition no longer relevant for wakeups - } - } - ABSL_RAW_CHECK(s->waitp != nullptr || s->suppress_fatal_errors, - "detected illegal recursion in Mutex code"); - s->waitp = nullptr; -} - -// Wake thread w, and return the next thread in the list. -PerThreadSynch *Mutex::Wakeup(PerThreadSynch *w) { - PerThreadSynch *next = w->next; - w->next = nullptr; - w->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - IncrementSynchSem(this, w); - - return next; -} - -static GraphId GetGraphIdLocked(Mutex *mu) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) { - if (!deadlock_graph) { // (re)create the deadlock graph. - deadlock_graph = - new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph))) - GraphCycles; - } - return deadlock_graph->GetId(mu); -} - -static GraphId GetGraphId(Mutex *mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) { - deadlock_graph_mu.Lock(); - GraphId id = GetGraphIdLocked(mu); - deadlock_graph_mu.Unlock(); - return id; -} - -// Record a lock acquisition. This is used in debug mode for deadlock -// detection. The held_locks pointer points to the relevant data -// structure for each case. -static void LockEnter(Mutex* mu, GraphId id, SynchLocksHeld *held_locks) { - int n = held_locks->n; - int i = 0; - while (i != n && held_locks->locks[i].id != id) { - i++; - } - if (i == n) { - if (n == ABSL_ARRAYSIZE(held_locks->locks)) { - held_locks->overflow = true; // lost some data - } else { // we have room for lock - held_locks->locks[i].mu = mu; - held_locks->locks[i].count = 1; - held_locks->locks[i].id = id; - held_locks->n = n + 1; - } - } else { - held_locks->locks[i].count++; - } -} - -// Record a lock release. Each call to LockEnter(mu, id, x) should be -// eventually followed by a call to LockLeave(mu, id, x) by the same thread. -// It does not process the event if is not needed when deadlock detection is -// disabled. -static void LockLeave(Mutex* mu, GraphId id, SynchLocksHeld *held_locks) { - int n = held_locks->n; - int i = 0; - while (i != n && held_locks->locks[i].id != id) { - i++; - } - if (i == n) { - if (!held_locks->overflow) { - // The deadlock id may have been reassigned after ForgetDeadlockInfo, - // but in that case mu should still be present. - i = 0; - while (i != n && held_locks->locks[i].mu != mu) { - i++; - } - if (i == n) { // mu missing means releasing unheld lock - SynchEvent *mu_events = GetSynchEvent(mu); - ABSL_RAW_LOG(FATAL, - "thread releasing lock it does not hold: %p %s; " - , - static_cast<void *>(mu), - mu_events == nullptr ? "" : mu_events->name); - } - } - } else if (held_locks->locks[i].count == 1) { - held_locks->n = n - 1; - held_locks->locks[i] = held_locks->locks[n - 1]; - held_locks->locks[n - 1].id = InvalidGraphId(); - held_locks->locks[n - 1].mu = - nullptr; // clear mu to please the leak detector. - } else { - assert(held_locks->locks[i].count > 0); - held_locks->locks[i].count--; - } -} - -// Call LockEnter() if in debug mode and deadlock detection is enabled. -static inline void DebugOnlyLockEnter(Mutex *mu) { - if (kDebugMode) { - if (synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - LockEnter(mu, GetGraphId(mu), Synch_GetAllLocks()); - } - } -} - -// Call LockEnter() if in debug mode and deadlock detection is enabled. -static inline void DebugOnlyLockEnter(Mutex *mu, GraphId id) { - if (kDebugMode) { - if (synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - LockEnter(mu, id, Synch_GetAllLocks()); - } - } -} - -// Call LockLeave() if in debug mode and deadlock detection is enabled. -static inline void DebugOnlyLockLeave(Mutex *mu) { - if (kDebugMode) { - if (synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - LockLeave(mu, GetGraphId(mu), Synch_GetAllLocks()); - } - } -} - -static char *StackString(void **pcs, int n, char *buf, int maxlen, - bool symbolize) { - static const int kSymLen = 200; - char sym[kSymLen]; - int len = 0; - for (int i = 0; i != n; i++) { - if (symbolize) { - if (!symbolizer(pcs[i], sym, kSymLen)) { - sym[0] = '\0'; - } - snprintf(buf + len, maxlen - len, "%s\t@ %p %s\n", - (i == 0 ? "\n" : ""), - pcs[i], sym); - } else { - snprintf(buf + len, maxlen - len, " %p", pcs[i]); - } - len += strlen(&buf[len]); - } - return buf; -} - -static char *CurrentStackString(char *buf, int maxlen, bool symbolize) { - void *pcs[40]; - return StackString(pcs, absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 2), buf, - maxlen, symbolize); -} - -namespace { -enum { kMaxDeadlockPathLen = 10 }; // maximum length of a deadlock cycle; - // a path this long would be remarkable -// Buffers required to report a deadlock. -// We do not allocate them on stack to avoid large stack frame. -struct DeadlockReportBuffers { - char buf[6100]; - GraphId path[kMaxDeadlockPathLen]; -}; - -struct ScopedDeadlockReportBuffers { - ScopedDeadlockReportBuffers() { - b = reinterpret_cast<DeadlockReportBuffers *>( - base_internal::LowLevelAlloc::Alloc(sizeof(*b))); - } - ~ScopedDeadlockReportBuffers() { base_internal::LowLevelAlloc::Free(b); } - DeadlockReportBuffers *b; -}; - -// Helper to pass to GraphCycles::UpdateStackTrace. -int GetStack(void** stack, int max_depth) { - return absl::GetStackTrace(stack, max_depth, 3); -} -} // anonymous namespace - -// Called in debug mode when a thread is about to acquire a lock in a way that -// may block. -static GraphId DeadlockCheck(Mutex *mu) { - if (synch_deadlock_detection.load(std::memory_order_acquire) == - OnDeadlockCycle::kIgnore) { - return InvalidGraphId(); - } - - SynchLocksHeld *all_locks = Synch_GetAllLocks(); - - absl::base_internal::SpinLockHolder lock(&deadlock_graph_mu); - const GraphId mu_id = GetGraphIdLocked(mu); - - if (all_locks->n == 0) { - // There are no other locks held. Return now so that we don't need to - // call GetSynchEvent(). This way we do not record the stack trace - // for this Mutex. It's ok, since if this Mutex is involved in a deadlock, - // it can't always be the first lock acquired by a thread. - return mu_id; - } - - // We prefer to keep stack traces that show a thread holding and acquiring - // as many locks as possible. This increases the chances that a given edge - // in the acquires-before graph will be represented in the stack traces - // recorded for the locks. - deadlock_graph->UpdateStackTrace(mu_id, all_locks->n + 1, GetStack); - - // For each other mutex already held by this thread: - for (int i = 0; i != all_locks->n; i++) { - const GraphId other_node_id = all_locks->locks[i].id; - const Mutex *other = - static_cast<const Mutex *>(deadlock_graph->Ptr(other_node_id)); - if (other == nullptr) { - // Ignore stale lock - continue; - } - - // Add the acquired-before edge to the graph. - if (!deadlock_graph->InsertEdge(other_node_id, mu_id)) { - ScopedDeadlockReportBuffers scoped_buffers; - DeadlockReportBuffers *b = scoped_buffers.b; - static int number_of_reported_deadlocks = 0; - number_of_reported_deadlocks++; - // Symbolize only 2 first deadlock report to avoid huge slowdowns. - bool symbolize = number_of_reported_deadlocks <= 2; - ABSL_RAW_LOG(ERROR, "Potential Mutex deadlock: %s", - CurrentStackString(b->buf, sizeof (b->buf), symbolize)); - int len = 0; - for (int j = 0; j != all_locks->n; j++) { - void* pr = deadlock_graph->Ptr(all_locks->locks[j].id); - if (pr != nullptr) { - snprintf(b->buf + len, sizeof (b->buf) - len, " %p", pr); - len += static_cast<int>(strlen(&b->buf[len])); - } - } - 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( - mu_id, other_node_id, ABSL_ARRAYSIZE(b->path), b->path); - for (int j = 0; j != path_len; j++) { - GraphId id = b->path[j]; - Mutex *path_mu = static_cast<Mutex *>(deadlock_graph->Ptr(id)); - if (path_mu == nullptr) continue; - void** stack; - int depth = deadlock_graph->GetStackTrace(id, &stack); - snprintf(b->buf, sizeof(b->buf), - "mutex@%p stack: ", static_cast<void *>(path_mu)); - StackString(stack, depth, b->buf + strlen(b->buf), - static_cast<int>(sizeof(b->buf) - strlen(b->buf)), - symbolize); - ABSL_RAW_LOG(ERROR, "%s", b->buf); - } - if (synch_deadlock_detection.load(std::memory_order_acquire) == - OnDeadlockCycle::kAbort) { - deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler - ABSL_RAW_LOG(FATAL, "dying due to potential deadlock"); - return mu_id; - } - break; // report at most one potential deadlock per acquisition - } - } - - return mu_id; -} - -// Invoke DeadlockCheck() iff we're in debug mode and -// deadlock checking has been enabled. -static inline GraphId DebugOnlyDeadlockCheck(Mutex *mu) { - if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - return DeadlockCheck(mu); - } else { - return InvalidGraphId(); - } -} - -void Mutex::ForgetDeadlockInfo() { - if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - deadlock_graph_mu.Lock(); - if (deadlock_graph != nullptr) { - deadlock_graph->RemoveNode(this); - } - deadlock_graph_mu.Unlock(); - } -} - -void Mutex::AssertNotHeld() const { - // We have the data to allow this check only if in debug mode and deadlock - // detection is enabled. - if (kDebugMode && - (mu_.load(std::memory_order_relaxed) & (kMuWriter | kMuReader)) != 0 && - synch_deadlock_detection.load(std::memory_order_acquire) != - OnDeadlockCycle::kIgnore) { - GraphId id = GetGraphId(const_cast<Mutex *>(this)); - SynchLocksHeld *locks = Synch_GetAllLocks(); - for (int i = 0; i != locks->n; i++) { - if (locks->locks[i].id == id) { - SynchEvent *mu_events = GetSynchEvent(this); - ABSL_RAW_LOG(FATAL, "thread should not hold mutex %p %s", - static_cast<const void *>(this), - (mu_events == nullptr ? "" : mu_events->name)); - } - } - } -} - -// 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; - 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 - } 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; - } - } while (--c > 0); - return false; -} - -ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - intptr_t v = mu_.load(std::memory_order_relaxed); - // try fast acquire, then spin loop - if ((v & (kMuWriter | kMuReader | kMuEvent)) != 0 || - !mu_.compare_exchange_strong(v, kMuWriter | v, - std::memory_order_acquire, - std::memory_order_relaxed)) { - // try spin acquire, then slow loop - if (!TryAcquireWithSpinning(&this->mu_)) { - this->LockSlow(kExclusive, nullptr, 0); - } - } - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); -} - -ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderLock() { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); - GraphId id = DebugOnlyDeadlockCheck(this); - intptr_t v = mu_.load(std::memory_order_relaxed); - // try fast acquire, then slow loop - if ((v & (kMuWriter | kMuWait | kMuEvent)) != 0 || - !mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { - this->LockSlow(kShared, nullptr, 0); - } - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); -} - -void Mutex::LockWhen(const Condition &cond) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - this->LockSlow(kExclusive, &cond, 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); -} - -bool Mutex::LockWhenWithTimeout(const Condition &cond, absl::Duration timeout) { - return LockWhenWithDeadline(cond, DeadlineFromTimeout(timeout)); -} - -bool Mutex::LockWhenWithDeadline(const Condition &cond, absl::Time deadline) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - bool res = LockSlowWithDeadline(kExclusive, &cond, - KernelTimeout(deadline), 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); - return res; -} - -void Mutex::ReaderLockWhen(const Condition &cond) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); - GraphId id = DebugOnlyDeadlockCheck(this); - this->LockSlow(kShared, &cond, 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); -} - -bool Mutex::ReaderLockWhenWithTimeout(const Condition &cond, - absl::Duration timeout) { - return ReaderLockWhenWithDeadline(cond, DeadlineFromTimeout(timeout)); -} - -bool Mutex::ReaderLockWhenWithDeadline(const Condition &cond, - absl::Time deadline) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); - GraphId id = DebugOnlyDeadlockCheck(this); - bool res = LockSlowWithDeadline(kShared, &cond, KernelTimeout(deadline), 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); - return res; -} - -void Mutex::Await(const Condition &cond) { - if (cond.Eval()) { // condition already true; nothing to do - if (kDebugMode) { - this->AssertReaderHeld(); - } - } else { // normal case - ABSL_RAW_CHECK(this->AwaitCommon(cond, KernelTimeout::Never()), - "condition untrue on return from Await"); - } -} - -bool Mutex::AwaitWithTimeout(const Condition &cond, absl::Duration timeout) { - return AwaitWithDeadline(cond, DeadlineFromTimeout(timeout)); -} - -bool Mutex::AwaitWithDeadline(const Condition &cond, absl::Time deadline) { - if (cond.Eval()) { // condition already true; nothing to do - if (kDebugMode) { - this->AssertReaderHeld(); - } - return true; - } - - KernelTimeout t{deadline}; - bool res = this->AwaitCommon(cond, t); - ABSL_RAW_CHECK(res || t.has_timeout(), - "condition untrue on return from Await"); - return res; -} - -bool Mutex::AwaitCommon(const Condition &cond, KernelTimeout t) { - this->AssertReaderHeld(); - MuHow how = - (mu_.load(std::memory_order_relaxed) & kMuWriter) ? kExclusive : kShared; - ABSL_TSAN_MUTEX_PRE_UNLOCK(this, TsanFlags(how)); - SynchWaitParams waitp( - how, &cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this), - nullptr /*no cv_word*/); - int flags = kMuHasBlocked; - if (!Condition::GuaranteedEqual(&cond, nullptr)) { - flags |= kMuIsCond; - } - this->UnlockSlow(&waitp); - this->Block(waitp.thread); - ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how)); - ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how)); - this->LockSlowLoop(&waitp, flags); - bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop - EvalConditionAnnotated(&cond, this, true, false, how == kShared); - ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0); - return res; -} - -ABSL_XRAY_LOG_ARGS(1) bool Mutex::TryLock() { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock); - intptr_t v = mu_.load(std::memory_order_relaxed); - if ((v & (kMuWriter | kMuReader | kMuEvent)) == 0 && // try fast acquire - mu_.compare_exchange_strong(v, kMuWriter | v, - std::memory_order_acquire, - std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0); - return true; - } - if ((v & kMuEvent) != 0) { // we're recording events - if ((v & kExclusive->slow_need_zero) == 0 && // try fast acquire - mu_.compare_exchange_strong( - v, (kExclusive->fast_or | v) + kExclusive->fast_add, - std::memory_order_acquire, std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0); - return true; - } else { - PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED); - } - } - ABSL_TSAN_MUTEX_POST_LOCK( - this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0); - return false; -} - -ABSL_XRAY_LOG_ARGS(1) bool Mutex::ReaderTryLock() { - ABSL_TSAN_MUTEX_PRE_LOCK(this, - __tsan_mutex_read_lock | __tsan_mutex_try_lock); - intptr_t v = mu_.load(std::memory_order_relaxed); - // The while-loops (here and below) iterate only if the mutex word keeps - // changing (typically because the reader count changes) under the CAS. We - // limit the number of attempts to avoid having to think about livelock. - int loop_limit = 5; - while ((v & (kMuWriter|kMuWait|kMuEvent)) == 0 && loop_limit != 0) { - if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - ABSL_TSAN_MUTEX_POST_LOCK( - this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0); - return true; - } - loop_limit--; - v = mu_.load(std::memory_order_relaxed); - } - if ((v & kMuEvent) != 0) { // we're recording events - loop_limit = 5; - while ((v & kShared->slow_need_zero) == 0 && loop_limit != 0) { - if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS); - ABSL_TSAN_MUTEX_POST_LOCK( - this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0); - return true; - } - loop_limit--; - v = mu_.load(std::memory_order_relaxed); - } - if ((v & kMuEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED); - } - } - ABSL_TSAN_MUTEX_POST_LOCK(this, - __tsan_mutex_read_lock | __tsan_mutex_try_lock | - __tsan_mutex_try_lock_failed, - 0); - return false; -} - -ABSL_XRAY_LOG_ARGS(1) void Mutex::Unlock() { - ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0); - DebugOnlyLockLeave(this); - intptr_t v = mu_.load(std::memory_order_relaxed); - - if (kDebugMode && ((v & (kMuWriter | kMuReader)) != kMuWriter)) { - ABSL_RAW_LOG(FATAL, "Mutex unlocked when destroyed or not locked: v=0x%x", - static_cast<unsigned>(v)); - } - - // should_try_cas is whether we'll try a compare-and-swap immediately. - // NOTE: optimized out when kDebugMode is false. - bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter && - (v & (kMuWait | kMuDesig)) != kMuWait); - // But, we can use an alternate computation of it, that compilers - // currently don't find on their own. When that changes, this function - // can be simplified. - intptr_t x = (v ^ (kMuWriter | kMuWait)) & (kMuWriter | kMuEvent); - intptr_t y = (v ^ (kMuWriter | kMuWait)) & (kMuWait | kMuDesig); - // Claim: "x == 0 && y > 0" is equal to should_try_cas. - // Also, because kMuWriter and kMuEvent exceed kMuDesig and kMuWait, - // all possible non-zero values for x exceed all possible values for y. - // Therefore, (x == 0 && y > 0) == (x < y). - if (kDebugMode && should_try_cas != (x < y)) { - // We would usually use PRIdPTR here, but is not correctly implemented - // within the android toolchain. - ABSL_RAW_LOG(FATAL, "internal logic error %llx %llx %llx\n", - static_cast<long long>(v), static_cast<long long>(x), - static_cast<long long>(y)); - } - if (x < y && - mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter), - std::memory_order_release, - std::memory_order_relaxed)) { - // fast writer release (writer with no waiters or with designated waker) - } else { - this->UnlockSlow(nullptr /*no waitp*/); // take slow path - } - ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0); -} - -// Requires v to represent a reader-locked state. -static bool ExactlyOneReader(intptr_t v) { - assert((v & (kMuWriter|kMuReader)) == kMuReader); - assert((v & kMuHigh) != 0); - // The more straightforward "(v & kMuHigh) == kMuOne" also works, but - // on some architectures the following generates slightly smaller code. - // It may be faster too. - constexpr intptr_t kMuMultipleWaitersMask = kMuHigh ^ kMuOne; - return (v & kMuMultipleWaitersMask) == 0; -} - -ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderUnlock() { - ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock); - DebugOnlyLockLeave(this); - intptr_t v = mu_.load(std::memory_order_relaxed); - assert((v & (kMuWriter|kMuReader)) == kMuReader); - if ((v & (kMuReader|kMuWait|kMuEvent)) == kMuReader) { - // fast reader release (reader with no waiters) - intptr_t clear = ExactlyOneReader(v) ? kMuReader|kMuOne : kMuOne; - if (mu_.compare_exchange_strong(v, v - clear, - std::memory_order_release, - std::memory_order_relaxed)) { - ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock); - return; - } - } - this->UnlockSlow(nullptr /*no waitp*/); // take slow path - ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock); -} - -// The zap_desig_waker bitmask is used to clear the designated waker flag in -// the mutex if this thread has blocked, and therefore may be the designated -// waker. -static const intptr_t zap_desig_waker[] = { - ~static_cast<intptr_t>(0), // not blocked - ~static_cast<intptr_t>( - kMuDesig) // blocked; turn off the designated waker bit -}; - -// The ignore_waiting_writers bitmask is used to ignore the existence -// of waiting writers if a reader that has already blocked once -// wakes up. -static const intptr_t ignore_waiting_writers[] = { - ~static_cast<intptr_t>(0), // not blocked - ~static_cast<intptr_t>( - kMuWrWait) // blocked; pretend there are no waiting writers -}; - -// Internal version of LockWhen(). See LockSlowWithDeadline() -ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition *cond, - int flags) { - ABSL_RAW_CHECK( - this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags), - "condition untrue on return from LockSlow"); -} - -// Compute cond->Eval() and tell race detectors that we do it under mutex mu. -static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu, - bool locking, bool trylock, - bool read_lock) { - // Delicate annotation dance. - // We are currently inside of read/write lock/unlock operation. - // All memory accesses are ignored inside of mutex operations + for unlock - // operation tsan considers that we've already released the mutex. - bool res = false; -#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE - const int flags = read_lock ? __tsan_mutex_read_lock : 0; - const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0); -#endif - if (locking) { - // For lock we pretend that we have finished the operation, - // evaluate the predicate, then unlock the mutex and start locking it again - // to match the annotation at the end of outer lock operation. - // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan - // will think the lock acquisition is recursive which will trigger - // deadlock detector. - ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0); - res = cond->Eval(); - // There is no "try" version of Unlock, so use flags instead of tryflags. - ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags); - ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags); - ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags); - } else { - // Similarly, for unlock we pretend that we have unlocked the mutex, - // lock the mutex, evaluate the predicate, and start unlocking it again - // to match the annotation at the end of outer unlock operation. - ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags); - ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags); - ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0); - res = cond->Eval(); - ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags); - } - // Prevent unused param warnings in non-TSAN builds. - static_cast<void>(mu); - static_cast<void>(trylock); - static_cast<void>(read_lock); - return res; -} - -// Compute cond->Eval() hiding it from race detectors. -// We are hiding it because inside of UnlockSlow we can evaluate a predicate -// that was just added by a concurrent Lock operation; Lock adds the predicate -// to the internal Mutex list without actually acquiring the Mutex -// (it only acquires the internal spinlock, which is rightfully invisible for -// tsan). As the result there is no tsan-visible synchronization between the -// addition and this thread. So if we would enable race detection here, -// it would race with the predicate initialization. -static inline bool EvalConditionIgnored(Mutex *mu, const Condition *cond) { - // Memory accesses are already ignored inside of lock/unlock operations, - // but synchronization operations are also ignored. When we evaluate the - // predicate we must ignore only memory accesses but not synchronization, - // because missed synchronization can lead to false reports later. - // 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(); - bool res = cond->Eval(); - ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - static_cast<void>(mu); // Prevent unused param warning in non-TSAN builds. - return res; -} - -// Internal equivalent of *LockWhenWithDeadline(), where -// "t" represents the absolute timeout; !t.has_timeout() means "forever". -// "how" is "kShared" (for ReaderLockWhen) or "kExclusive" (for LockWhen) -// In flags, bits are ored together: -// - kMuHasBlocked indicates that the client has already blocked on the call so -// the designated waker bit must be cleared and waiting writers should not -// obstruct this call -// - kMuIsCond indicates that this is a conditional acquire (condition variable, -// Await, LockWhen) so contention profiling should be suppressed. -bool Mutex::LockSlowWithDeadline(MuHow how, const Condition *cond, - KernelTimeout t, int flags) { - intptr_t v = mu_.load(std::memory_order_relaxed); - bool unlock = false; - if ((v & how->fast_need_zero) == 0 && // try fast acquire - mu_.compare_exchange_strong( - v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) + - how->fast_add, - std::memory_order_acquire, std::memory_order_relaxed)) { - if (cond == nullptr || - EvalConditionAnnotated(cond, this, true, false, how == kShared)) { - return true; - } - unlock = true; - } - SynchWaitParams waitp( - how, cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this), - nullptr /*no cv_word*/); - if (!Condition::GuaranteedEqual(cond, nullptr)) { - flags |= kMuIsCond; - } - if (unlock) { - this->UnlockSlow(&waitp); - this->Block(waitp.thread); - flags |= kMuHasBlocked; - } - this->LockSlowLoop(&waitp, flags); - return waitp.cond != nullptr || // => cond known true from LockSlowLoop - cond == nullptr || - EvalConditionAnnotated(cond, this, true, false, how == kShared); -} - -// RAW_CHECK_FMT() takes a condition, a printf-style format string, and -// the printf-style argument list. The format string must be a literal. -// Arguments after the first are not evaluated unless the condition is true. -#define RAW_CHECK_FMT(cond, ...) \ - do { \ - if (ABSL_PREDICT_FALSE(!(cond))) { \ - ABSL_RAW_LOG(FATAL, "Check " #cond " failed: " __VA_ARGS__); \ - } \ - } while (0) - -static void CheckForMutexCorruption(intptr_t v, const char* label) { - // Test for either of two situations that should not occur in v: - // kMuWriter and kMuReader - // kMuWrWait and !kMuWait - const uintptr_t w = v ^ kMuWait; - // By flipping that bit, we can now test for: - // kMuWriter and kMuReader in w - // kMuWrWait and kMuWait in w - // We've chosen these two pairs of values to be so that they will overlap, - // respectively, when the word is left shifted by three. This allows us to - // save a branch in the common (correct) case of them not being coincident. - static_assert(kMuReader << 3 == kMuWriter, "must match"); - static_assert(kMuWait << 3 == kMuWrWait, "must match"); - if (ABSL_PREDICT_TRUE((w & (w << 3) & (kMuWriter | kMuWrWait)) == 0)) return; - RAW_CHECK_FMT((v & (kMuWriter | kMuReader)) != (kMuWriter | kMuReader), - "%s: Mutex corrupt: both reader and writer lock held: %p", - label, reinterpret_cast<void *>(v)); - RAW_CHECK_FMT((v & (kMuWait | kMuWrWait)) != kMuWrWait, - "%s: Mutex corrupt: waiting writer with no waiters: %p", - label, reinterpret_cast<void *>(v)); - assert(false); -} - -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) { - PostSynchEvent(this, - waitp->how == kExclusive? SYNCH_EV_LOCK: SYNCH_EV_READERLOCK); - } - ABSL_RAW_CHECK( - waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, - "detected illegal recursion into Mutex code"); - for (;;) { - v = mu_.load(std::memory_order_relaxed); - CheckForMutexCorruption(v, "Lock"); - if ((v & waitp->how->slow_need_zero) == 0) { - if (mu_.compare_exchange_strong( - v, (waitp->how->fast_or | - (v & zap_desig_waker[flags & kMuHasBlocked])) + - waitp->how->fast_add, - std::memory_order_acquire, std::memory_order_relaxed)) { - if (waitp->cond == nullptr || - EvalConditionAnnotated(waitp->cond, this, true, false, - waitp->how == kShared)) { - break; // we timed out, or condition true, so return - } - this->UnlockSlow(waitp); // got lock but condition false - this->Block(waitp->thread); - flags |= kMuHasBlocked; - c = 0; - } - } else { // need to access waiter list - bool dowait = false; - if ((v & (kMuSpin|kMuWait)) == 0) { // no waiters - // This thread tries to become the one and only waiter. - PerThreadSynch *new_h = Enqueue(nullptr, waitp, v, flags); - intptr_t nv = (v & zap_desig_waker[flags & kMuHasBlocked] & kMuLow) | - kMuWait; - ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to empty list failed"); - if (waitp->how == kExclusive && (v & kMuReader) != 0) { - nv |= kMuWrWait; - } - if (mu_.compare_exchange_strong( - v, reinterpret_cast<intptr_t>(new_h) | nv, - std::memory_order_release, std::memory_order_relaxed)) { - dowait = true; - } else { // attempted Enqueue() failed - // zero out the waitp field set by Enqueue() - waitp->thread->waitp = nullptr; - } - } else if ((v & waitp->how->slow_inc_need_zero & - ignore_waiting_writers[flags & kMuHasBlocked]) == 0) { - // This is a reader that needs to increment the reader count, - // but the count is currently held in the last waiter. - if (mu_.compare_exchange_strong( - v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin | - kMuReader, - std::memory_order_acquire, std::memory_order_relaxed)) { - PerThreadSynch *h = GetPerThreadSynch(v); - h->readers += kMuOne; // inc reader count in waiter - do { // release spinlock - v = mu_.load(std::memory_order_relaxed); - } while (!mu_.compare_exchange_weak(v, (v & ~kMuSpin) | kMuReader, - std::memory_order_release, - std::memory_order_relaxed)); - if (waitp->cond == nullptr || - EvalConditionAnnotated(waitp->cond, this, true, false, - waitp->how == kShared)) { - break; // we timed out, or condition true, so return - } - this->UnlockSlow(waitp); // got lock but condition false - this->Block(waitp->thread); - flags |= kMuHasBlocked; - c = 0; - } - } else if ((v & kMuSpin) == 0 && // attempt to queue ourselves - mu_.compare_exchange_strong( - v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin | - kMuWait, - std::memory_order_acquire, std::memory_order_relaxed)) { - PerThreadSynch *h = GetPerThreadSynch(v); - PerThreadSynch *new_h = Enqueue(h, waitp, v, flags); - intptr_t wr_wait = 0; - ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to list failed"); - if (waitp->how == kExclusive && (v & kMuReader) != 0) { - wr_wait = kMuWrWait; // give priority to a waiting writer - } - do { // release spinlock - v = mu_.load(std::memory_order_relaxed); - } while (!mu_.compare_exchange_weak( - v, (v & (kMuLow & ~kMuSpin)) | kMuWait | wr_wait | - reinterpret_cast<intptr_t>(new_h), - std::memory_order_release, std::memory_order_relaxed)); - dowait = true; - } - if (dowait) { - this->Block(waitp->thread); // wait until removed from list or timeout - flags |= kMuHasBlocked; - c = 0; - } - } - 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); - } - ABSL_RAW_CHECK( - waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, - "detected illegal recursion into Mutex code"); - if ((v & kMuEvent) != 0) { - PostSynchEvent(this, - waitp->how == kExclusive? SYNCH_EV_LOCK_RETURNING : - SYNCH_EV_READERLOCK_RETURNING); - } -} - -// Unlock this mutex, which is held by the current thread. -// If waitp is non-zero, it must be the wait parameters for the current thread -// 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; - intptr_t v = mu_.load(std::memory_order_relaxed); - this->AssertReaderHeld(); - CheckForMutexCorruption(v, "Unlock"); - if ((v & kMuEvent) != 0) { - PostSynchEvent(this, - (v & kMuWriter) != 0? SYNCH_EV_UNLOCK: SYNCH_EV_READERUNLOCK); - } - int c = 0; - // the waiter under consideration to wake, or zero - PerThreadSynch *w = nullptr; - // the predecessor to w or zero - PerThreadSynch *pw = nullptr; - // head of the list searched previously, or zero - PerThreadSynch *old_h = nullptr; - // a condition that's known to be false. - const Condition *known_false = nullptr; - PerThreadSynch *wake_list = kPerThreadSynchNull; // list of threads to wake - intptr_t wr_wait = 0; // set to kMuWrWait if we wake a reader and a - // later writer could have acquired the lock - // (starvation avoidance) - ABSL_RAW_CHECK(waitp == nullptr || waitp->thread->waitp == nullptr || - waitp->thread->suppress_fatal_errors, - "detected illegal recursion into Mutex code"); - // This loop finds threads wake_list to wakeup if any, and removes them from - // the list of waiters. In addition, it places waitp.thread on the queue of - // waiters if waitp is non-zero. - for (;;) { - v = mu_.load(std::memory_order_relaxed); - if ((v & kMuWriter) != 0 && (v & (kMuWait | kMuDesig)) != kMuWait && - waitp == nullptr) { - // fast writer release (writer with no waiters or with designated waker) - if (mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter), - std::memory_order_release, - std::memory_order_relaxed)) { - return; - } - } else if ((v & (kMuReader | kMuWait)) == kMuReader && waitp == nullptr) { - // fast reader release (reader with no waiters) - intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne; - if (mu_.compare_exchange_strong(v, v - clear, - std::memory_order_release, - std::memory_order_relaxed)) { - return; - } - } else if ((v & kMuSpin) == 0 && // attempt to get spinlock - mu_.compare_exchange_strong(v, v | kMuSpin, - std::memory_order_acquire, - std::memory_order_relaxed)) { - if ((v & kMuWait) == 0) { // no one to wake - intptr_t nv; - bool do_enqueue = true; // always Enqueue() the first time - ABSL_RAW_CHECK(waitp != nullptr, - "UnlockSlow is confused"); // about to sleep - do { // must loop to release spinlock as reader count may change - v = mu_.load(std::memory_order_relaxed); - // decrement reader count if there are readers - intptr_t new_readers = (v >= kMuOne)? v - kMuOne : v; - PerThreadSynch *new_h = nullptr; - if (do_enqueue) { - // If we are enqueuing on a CondVar (waitp->cv_word != nullptr) then - // we must not retry here. The initial attempt will always have - // succeeded, further attempts would enqueue us against *this due to - // Fer() handling. - do_enqueue = (waitp->cv_word == nullptr); - new_h = Enqueue(nullptr, waitp, new_readers, kMuIsCond); - } - intptr_t clear = kMuWrWait | kMuWriter; // by default clear write bit - if ((v & kMuWriter) == 0 && ExactlyOneReader(v)) { // last reader - clear = kMuWrWait | kMuReader; // clear read bit - } - nv = (v & kMuLow & ~clear & ~kMuSpin); - if (new_h != nullptr) { - nv |= kMuWait | reinterpret_cast<intptr_t>(new_h); - } else { // new_h could be nullptr if we queued ourselves on a - // CondVar - // In that case, we must place the reader count back in the mutex - // word, as Enqueue() did not store it in the new waiter. - nv |= new_readers & kMuHigh; - } - // release spinlock & our lock; retry if reader-count changed - // (writer count cannot change since we hold lock) - } while (!mu_.compare_exchange_weak(v, nv, - std::memory_order_release, - std::memory_order_relaxed)); - break; - } - - // There are waiters. - // Set h to the head of the circular waiter list. - PerThreadSynch *h = GetPerThreadSynch(v); - if ((v & kMuReader) != 0 && (h->readers & kMuHigh) > kMuOne) { - // a reader but not the last - h->readers -= kMuOne; // release our lock - intptr_t nv = v; // normally just release spinlock - if (waitp != nullptr) { // but waitp!=nullptr => must queue ourselves - PerThreadSynch *new_h = Enqueue(h, waitp, v, kMuIsCond); - ABSL_RAW_CHECK(new_h != nullptr, - "waiters disappeared during Enqueue()!"); - nv &= kMuLow; - nv |= kMuWait | reinterpret_cast<intptr_t>(new_h); - } - mu_.store(nv, std::memory_order_release); // release spinlock - // can release with a store because there were waiters - break; - } - - // Either we didn't search before, or we marked the queue - // as "maybe_unlocking" and no one else should have changed it. - ABSL_RAW_CHECK(old_h == nullptr || h->maybe_unlocking, - "Mutex queue changed beneath us"); - - // The lock is becoming free, and there's a waiter - if (old_h != nullptr && - !old_h->may_skip) { // we used old_h as a terminator - old_h->may_skip = true; // allow old_h to skip once more - ABSL_RAW_CHECK(old_h->skip == nullptr, "illegal skip from head"); - if (h != old_h && MuSameCondition(old_h, old_h->next)) { - old_h->skip = old_h->next; // old_h not head & can skip to successor - } - } - if (h->next->waitp->how == kExclusive && - Condition::GuaranteedEqual(h->next->waitp->cond, nullptr)) { - // easy case: writer with no condition; no need to search - pw = h; // wake w, the successor of h (=pw) - w = h->next; - w->wake = true; - // We are waking up a writer. This writer may be racing against - // an already awake reader for the lock. We want the - // writer to usually win this race, - // because if it doesn't, we can potentially keep taking a reader - // perpetually and writers will starve. Worse than - // that, this can also starve other readers if kMuWrWait gets set - // later. - wr_wait = kMuWrWait; - } else if (w != nullptr && (w->waitp->how == kExclusive || h == old_h)) { - // we found a waiter w to wake on a previous iteration and either it's - // a writer, or we've searched the entire list so we have all the - // readers. - if (pw == nullptr) { // if w's predecessor is unknown, it must be h - pw = h; - } - } else { - // At this point we don't know all the waiters to wake, and the first - // waiter has a condition or is a reader. We avoid searching over - // waiters we've searched on previous iterations by starting at - // old_h if it's set. If old_h==h, there's no one to wakeup at all. - if (old_h == h) { // we've searched before, and nothing's new - // so there's no one to wake. - intptr_t nv = (v & ~(kMuReader|kMuWriter|kMuWrWait)); - h->readers = 0; - h->maybe_unlocking = false; // finished unlocking - if (waitp != nullptr) { // we must queue ourselves and sleep - PerThreadSynch *new_h = Enqueue(h, waitp, v, kMuIsCond); - nv &= kMuLow; - if (new_h != nullptr) { - nv |= kMuWait | reinterpret_cast<intptr_t>(new_h); - } // else new_h could be nullptr if we queued ourselves on a - // CondVar - } - // release spinlock & lock - // can release with a store because there were waiters - mu_.store(nv, std::memory_order_release); - break; - } - - // set up to walk the list - PerThreadSynch *w_walk; // current waiter during list walk - PerThreadSynch *pw_walk; // previous waiter during list walk - if (old_h != nullptr) { // we've searched up to old_h before - pw_walk = old_h; - w_walk = old_h->next; - } else { // no prior search, start at beginning - pw_walk = - nullptr; // h->next's predecessor may change; don't record it - w_walk = h->next; - } - - h->may_skip = false; // ensure we never skip past h in future searches - // even if other waiters are queued after it. - ABSL_RAW_CHECK(h->skip == nullptr, "illegal skip from head"); - - h->maybe_unlocking = true; // we're about to scan the waiter list - // without the spinlock held. - // Enqueue must be conservative about - // priority queuing. - - // We must release the spinlock to evaluate the conditions. - mu_.store(v, std::memory_order_release); // release just spinlock - // can release with a store because there were waiters - - // h is the last waiter queued, and w_walk the first unsearched waiter. - // Without the spinlock, the locations mu_ and h->next may now change - // underneath us, but since we hold the lock itself, the only legal - // change is to add waiters between h and w_walk. Therefore, it's safe - // to walk the path from w_walk to h inclusive. (TryRemove() can remove - // a waiter anywhere, but it acquires both the spinlock and the Mutex) - - old_h = h; // remember we searched to here - - // Walk the path upto and including h looking for waiters we can wake. - while (pw_walk != h) { - w_walk->wake = false; - if (w_walk->waitp->cond == - nullptr || // no condition => vacuously true OR - (w_walk->waitp->cond != known_false && - // this thread's condition is not known false, AND - // is in fact true - EvalConditionIgnored(this, w_walk->waitp->cond))) { - if (w == nullptr) { - w_walk->wake = true; // can wake this waiter - w = w_walk; - pw = pw_walk; - if (w_walk->waitp->how == kExclusive) { - wr_wait = kMuWrWait; - break; // bail if waking this writer - } - } else if (w_walk->waitp->how == kShared) { // wake if a reader - w_walk->wake = true; - } else { // writer with true condition - wr_wait = kMuWrWait; - } - } else { // can't wake; condition false - known_false = w_walk->waitp->cond; // remember last false condition - } - if (w_walk->wake) { // we're waking reader w_walk - pw_walk = w_walk; // don't skip similar waiters - } else { // not waking; skip as much as possible - pw_walk = Skip(w_walk); - } - // If pw_walk == h, then load of pw_walk->next can race with - // concurrent write in Enqueue(). However, at the same time - // we do not need to do the load, because we will bail out - // from the loop anyway. - if (pw_walk != h) { - w_walk = pw_walk->next; - } - } - - continue; // restart for(;;)-loop to wakeup w or to find more waiters - } - ABSL_RAW_CHECK(pw->next == w, "pw not w's predecessor"); - // The first (and perhaps only) waiter we've chosen to wake is w, whose - // predecessor is pw. If w is a reader, we must wake all the other - // waiters with wake==true as well. We may also need to queue - // ourselves if waitp != null. The spinlock and the lock are still - // held. - - // This traverses the list in [ pw->next, h ], where h is the head, - // removing all elements with wake==true and placing them in the - // singly-linked list wake_list. Returns the new head. - h = DequeueAllWakeable(h, pw, &wake_list); - - intptr_t nv = (v & kMuEvent) | kMuDesig; - // assume no waiters left, - // set kMuDesig for INV1a - - if (waitp != nullptr) { // we must queue ourselves and sleep - h = Enqueue(h, waitp, v, kMuIsCond); - // h is new last waiter; could be null if we queued ourselves on a - // CondVar - } - - ABSL_RAW_CHECK(wake_list != kPerThreadSynchNull, - "unexpected empty wake list"); - - if (h != nullptr) { // there are waiters left - h->readers = 0; - h->maybe_unlocking = false; // finished unlocking - nv |= wr_wait | kMuWait | reinterpret_cast<intptr_t>(h); - } - - // release both spinlock & lock - // can release with a store because there were waiters - 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); - } // end of for(;;)-loop - - if (wake_list != kPerThreadSynchNull) { - int64_t enqueue_timestamp = wake_list->waitp->contention_start_cycles; - bool cond_waiter = wake_list->cond_waiter; - do { - wake_list = Wakeup(wake_list); // wake waiters - } while (wake_list != kPerThreadSynchNull); - 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; - mutex_tracer("slow release", this, wait_cycles); - ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); - submit_profile_data(enqueue_timestamp); - ABSL_TSAN_MUTEX_POST_DIVERT(this, 0); - } - } -} - -// Used by CondVar implementation to reacquire mutex after waking from -// condition variable. This routine is used instead of Lock() because the -// waiting thread may have been moved from the condition variable queue to the -// mutex queue without a wakeup, by Trans(). In that case, when the thread is -// finally woken, the woken thread will believe it has been woken from the -// condition variable (i.e. its PC will be in when in the CondVar code), when -// in fact it has just been woken from the mutex. Thus, it must enter the slow -// path of the mutex in the same state as if it had just woken from the mutex. -// That is, it must ensure to clear kMuDesig (INV1b). -void Mutex::Trans(MuHow how) { - this->LockSlow(how, nullptr, kMuHasBlocked | kMuIsCond); -} - -// Used by CondVar implementation to effectively wake thread w from the -// condition variable. If this mutex is free, we simply wake the thread. -// 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"); - ABSL_RAW_CHECK(!w->waitp->timeout.has_timeout(), - "Mutex::Fer while in timed wait"); - ABSL_RAW_CHECK(w->waitp->cv_word == nullptr, - "Mutex::Fer with pending CondVar queueing"); - for (;;) { - intptr_t v = mu_.load(std::memory_order_relaxed); - // Note: must not queue if the mutex is unlocked (nobody will wake it). - // For example, we can have only kMuWait (conditional) or maybe - // kMuWait|kMuWrWait. - // conflicting != 0 implies that the waking thread cannot currently take - // the mutex, which in turn implies that someone else has it and can wake - // us if we queue. - const intptr_t conflicting = - kMuWriter | (w->waitp->how == kShared ? 0 : kMuReader); - if ((v & conflicting) == 0) { - w->next = nullptr; - w->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - IncrementSynchSem(this, w); - return; - } else { - if ((v & (kMuSpin|kMuWait)) == 0) { // no waiters - // This thread tries to become the one and only waiter. - PerThreadSynch *new_h = Enqueue(nullptr, w->waitp, v, kMuIsCond); - ABSL_RAW_CHECK(new_h != nullptr, - "Enqueue failed"); // we must queue ourselves - if (mu_.compare_exchange_strong( - v, reinterpret_cast<intptr_t>(new_h) | (v & kMuLow) | kMuWait, - std::memory_order_release, std::memory_order_relaxed)) { - return; - } - } else if ((v & kMuSpin) == 0 && - mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) { - PerThreadSynch *h = GetPerThreadSynch(v); - PerThreadSynch *new_h = Enqueue(h, w->waitp, v, kMuIsCond); - ABSL_RAW_CHECK(new_h != nullptr, - "Enqueue failed"); // we must queue ourselves - do { - v = mu_.load(std::memory_order_relaxed); - } while (!mu_.compare_exchange_weak( - v, - (v & kMuLow & ~kMuSpin) | kMuWait | - reinterpret_cast<intptr_t>(new_h), - std::memory_order_release, std::memory_order_relaxed)); - return; - } - } - c = synchronization_internal::MutexDelay(c, GENTLE); - } -} - -void Mutex::AssertHeld() const { - if ((mu_.load(std::memory_order_relaxed) & kMuWriter) == 0) { - SynchEvent *e = GetSynchEvent(this); - ABSL_RAW_LOG(FATAL, "thread should hold write lock on Mutex %p %s", - static_cast<const void *>(this), - (e == nullptr ? "" : e->name)); - } -} - -void Mutex::AssertReaderHeld() const { - if ((mu_.load(std::memory_order_relaxed) & (kMuReader | kMuWriter)) == 0) { - SynchEvent *e = GetSynchEvent(this); - ABSL_RAW_LOG( - FATAL, "thread should hold at least a read lock on Mutex %p %s", - static_cast<const void *>(this), (e == nullptr ? "" : e->name)); - } -} - -// -------------------------------- condition variables -static const intptr_t kCvSpin = 0x0001L; // spinlock protects waiter list -static const intptr_t kCvEvent = 0x0002L; // record events - -static const intptr_t kCvLow = 0x0003L; // low order bits of CV - -// Hack to make constant values available to gdb pretty printer -enum { kGdbCvSpin = kCvSpin, kGdbCvEvent = kCvEvent, kGdbCvLow = kCvLow, }; - -static_assert(PerThreadSynch::kAlignment > kCvLow, - "PerThreadSynch::kAlignment must be greater than kCvLow"); - -void CondVar::EnableDebugLog(const char *name) { - SynchEvent *e = EnsureSynchEvent(&this->cv_, name, kCvEvent, kCvSpin); - e->log = true; - UnrefSynchEvent(e); -} - -CondVar::~CondVar() { - if ((cv_.load(std::memory_order_relaxed) & kCvEvent) != 0) { - ForgetSynchEvent(&this->cv_, kCvEvent, kCvSpin); - } -} - - -// 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);; - v = cv_.load(std::memory_order_relaxed)) { - if ((v & kCvSpin) == 0 && // attempt to acquire spinlock - cv_.compare_exchange_strong(v, v | kCvSpin, - std::memory_order_acquire, - std::memory_order_relaxed)) { - PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow); - if (h != nullptr) { - PerThreadSynch *w = h; - while (w->next != s && w->next != h) { // search for thread - w = w->next; - } - if (w->next == s) { // found thread; remove it - w->next = s->next; - if (h == s) { - h = (w == s) ? nullptr : w; - } - s->next = nullptr; - s->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - } - } - // release spinlock - cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h), - std::memory_order_release); - return; - } else { - // try again after a delay - c = synchronization_internal::MutexDelay(c, GENTLE); - } - } -} - -// Queue thread waitp->thread on condition variable word cv_word using -// wait parameters waitp. -// We split this into a separate routine, rather than simply doing it as part -// of WaitCommon(). If we were to queue ourselves on the condition variable -// before calling Mutex::UnlockSlow(), the Mutex code might be re-entered (via -// the logging code, or via a Condition function) and might potentially attempt -// to block this thread. That would be a problem if the thread were already on -// a the condition variable waiter queue. Thus, we use the waitp->cv_word -// to tell the unlock code to call CondVarEnqueue() to queue the thread on the -// condition variable queue just before the mutex is to be unlocked, and (most -// importantly) after any call to an external routine that might re-enter the -// mutex code. -static void CondVarEnqueue(SynchWaitParams *waitp) { - // This thread might be transferred to the Mutex queue by Fer() when - // we are woken. To make sure that is what happens, Enqueue() doesn't - // call CondVarEnqueue() again but instead uses its normal code. We - // must do this before we queue ourselves so that cv_word will be null - // when seen by the dequeuer, who may wish immediately to requeue - // this thread on another queue. - std::atomic<intptr_t> *cv_word = waitp->cv_word; - waitp->cv_word = nullptr; - - intptr_t v = cv_word->load(std::memory_order_relaxed); - int c = 0; - while ((v & kCvSpin) != 0 || // acquire spinlock - !cv_word->compare_exchange_weak(v, v | kCvSpin, - std::memory_order_acquire, - std::memory_order_relaxed)) { - c = synchronization_internal::MutexDelay(c, GENTLE); - v = cv_word->load(std::memory_order_relaxed); - } - ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be"); - waitp->thread->waitp = waitp; // prepare ourselves for waiting - PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow); - if (h == nullptr) { // add this thread to waiter list - waitp->thread->next = waitp->thread; - } else { - waitp->thread->next = h->next; - h->next = waitp->thread; - } - waitp->thread->state.store(PerThreadSynch::kQueued, - std::memory_order_relaxed); - cv_word->store((v & kCvEvent) | reinterpret_cast<intptr_t>(waitp->thread), - std::memory_order_release); -} - -bool CondVar::WaitCommon(Mutex *mutex, KernelTimeout t) { - bool rc = false; // return value; true iff we timed-out - - intptr_t mutex_v = mutex->mu_.load(std::memory_order_relaxed); - Mutex::MuHow mutex_how = ((mutex_v & kMuWriter) != 0) ? kExclusive : kShared; - ABSL_TSAN_MUTEX_PRE_UNLOCK(mutex, TsanFlags(mutex_how)); - - // maybe trace this call - intptr_t v = cv_.load(std::memory_order_relaxed); - cond_var_tracer("Wait", this); - if ((v & kCvEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_WAIT); - } - - // Release mu and wait on condition variable. - SynchWaitParams waitp(mutex_how, nullptr, t, mutex, - Synch_GetPerThreadAnnotated(mutex), &cv_); - // UnlockSlow() will call CondVarEnqueue() just before releasing the - // Mutex, thus queuing this thread on the condition variable. See - // CondVarEnqueue() for the reasons. - mutex->UnlockSlow(&waitp); - - // wait for signal - while (waitp.thread->state.load(std::memory_order_acquire) == - PerThreadSynch::kQueued) { - if (!Mutex::DecrementSynchSem(mutex, waitp.thread, t)) { - this->Remove(waitp.thread); - rc = true; - } - } - - ABSL_RAW_CHECK(waitp.thread->waitp != nullptr, "not waiting when should be"); - waitp.thread->waitp = nullptr; // cleanup - - // maybe trace this call - cond_var_tracer("Unwait", this); - if ((v & kCvEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_WAIT_RETURNING); - } - - // From synchronization point of view Wait is unlock of the mutex followed - // by lock of the mutex. We've annotated start of unlock in the beginning - // of the function. Now, finish unlock and annotate lock of the mutex. - // (Trans is effectively lock). - ABSL_TSAN_MUTEX_POST_UNLOCK(mutex, TsanFlags(mutex_how)); - ABSL_TSAN_MUTEX_PRE_LOCK(mutex, TsanFlags(mutex_how)); - mutex->Trans(mutex_how); // Reacquire mutex - ABSL_TSAN_MUTEX_POST_LOCK(mutex, TsanFlags(mutex_how), 0); - return rc; -} - -bool CondVar::WaitWithTimeout(Mutex *mu, absl::Duration timeout) { - return WaitWithDeadline(mu, DeadlineFromTimeout(timeout)); -} - -bool CondVar::WaitWithDeadline(Mutex *mu, absl::Time deadline) { - return WaitCommon(mu, KernelTimeout(deadline)); -} - -void CondVar::Wait(Mutex *mu) { - WaitCommon(mu, KernelTimeout::Never()); -} - -// Wake thread w -// If it was a timed wait, w will be waiting on w->cv -// Otherwise, if it was not a Mutex mutex, w will be waiting on w->sem -// Otherwise, w is transferred to the Mutex mutex via Mutex::Fer(). -void CondVar::Wakeup(PerThreadSynch *w) { - if (w->waitp->timeout.has_timeout() || w->waitp->cvmu == nullptr) { - // The waiting thread only needs to observe "w->state == kAvailable" to be - // released, we must cache "cvmu" before clearing "next". - Mutex *mu = w->waitp->cvmu; - w->next = nullptr; - w->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - Mutex::IncrementSynchSem(mu, w); - } else { - w->waitp->cvmu->Fer(w); - } -} - -void CondVar::Signal() { - SchedulingGuard::ScopedDisable disable_rescheduling; - ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); - intptr_t v; - int c = 0; - for (v = cv_.load(std::memory_order_relaxed); v != 0; - v = cv_.load(std::memory_order_relaxed)) { - if ((v & kCvSpin) == 0 && // attempt to acquire spinlock - cv_.compare_exchange_strong(v, v | kCvSpin, - std::memory_order_acquire, - std::memory_order_relaxed)) { - PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow); - PerThreadSynch *w = nullptr; - if (h != nullptr) { // remove first waiter - w = h->next; - if (w == h) { - h = nullptr; - } else { - h->next = w->next; - } - } - // release spinlock - cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h), - std::memory_order_release); - if (w != nullptr) { - CondVar::Wakeup(w); // wake waiter, if there was one - cond_var_tracer("Signal wakeup", this); - } - if ((v & kCvEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_SIGNAL); - } - ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); - return; - } else { - c = synchronization_internal::MutexDelay(c, GENTLE); - } - } - ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); -} - -void CondVar::SignalAll () { - ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); - intptr_t v; - int c = 0; - for (v = cv_.load(std::memory_order_relaxed); v != 0; - v = cv_.load(std::memory_order_relaxed)) { - // empty the list if spinlock free - // We do this by simply setting the list to empty using - // compare and swap. We then have the entire list in our hands, - // which cannot be changing since we grabbed it while no one - // held the lock. - if ((v & kCvSpin) == 0 && - cv_.compare_exchange_strong(v, v & kCvEvent, std::memory_order_acquire, - std::memory_order_relaxed)) { - PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow); - if (h != nullptr) { - PerThreadSynch *w; - PerThreadSynch *n = h->next; - do { // for every thread, wake it up - w = n; - n = n->next; - CondVar::Wakeup(w); - } while (w != h); - cond_var_tracer("SignalAll wakeup", this); - } - if ((v & kCvEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_SIGNALALL); - } - ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); - return; - } else { - // try again after a delay - c = synchronization_internal::MutexDelay(c, GENTLE); - } - } - ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); -} - -void ReleasableMutexLock::Release() { - ABSL_RAW_CHECK(this->mu_ != nullptr, - "ReleasableMutexLock::Release may only be called once"); - this->mu_->Unlock(); - this->mu_ = nullptr; -} - -#ifdef ABSL_HAVE_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); -} - -bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) { - if (a == nullptr) { - return b == nullptr || b->eval_ == nullptr; - } - if (b == nullptr || b->eval_ == nullptr) { - return a->eval_ == nullptr; - } - return a->eval_ == b->eval_ && a->function_ == b->function_ && - a->arg_ == b->arg_ && a->method_ == b->method_; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/mutex.h b/third_party/abseil_cpp/absl/synchronization/mutex.h deleted file mode 100644 index 598d1e0617cf..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/mutex.h +++ /dev/null @@ -1,1084 +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. -// -// ----------------------------------------------------------------------------- -// mutex.h -// ----------------------------------------------------------------------------- -// -// This header file defines a `Mutex` -- a mutually exclusive lock -- and the -// most common type of synchronization primitive for facilitating locks on -// shared resources. A mutex is used to prevent multiple threads from accessing -// and/or writing to a shared resource concurrently. -// -// Unlike a `std::mutex`, the Abseil `Mutex` provides the following additional -// features: -// * Conditional predicates intrinsic to the `Mutex` object -// * Shared/reader locks, in addition to standard exclusive/writer locks -// * Deadlock detection and debug support. -// -// The following helper classes are also defined within this file: -// -// 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. -// -// 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. -// -// See below for more information on using `Condition` or `CondVar`. -// -// Mutexes and mutex behavior can be quite complicated. The information within -// this header file is limited, as a result. Please consult the Mutex guide for -// more complete information and examples. - -#ifndef ABSL_SYNCHRONIZATION_MUTEX_H_ -#define ABSL_SYNCHRONIZATION_MUTEX_H_ - -#include <atomic> -#include <cstdint> -#include <string> - -#include "absl/base/const_init.h" -#include "absl/base/internal/identity.h" -#include "absl/base/internal/low_level_alloc.h" -#include "absl/base/internal/thread_identity.h" -#include "absl/base/internal/tsan_mutex_interface.h" -#include "absl/base/port.h" -#include "absl/base/thread_annotations.h" -#include "absl/synchronization/internal/kernel_timeout.h" -#include "absl/synchronization/internal/per_thread_sem.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class Condition; -struct SynchWaitParams; - -// ----------------------------------------------------------------------------- -// Mutex -// ----------------------------------------------------------------------------- -// -// A `Mutex` is a non-reentrant (aka non-recursive) Mutually Exclusive lock -// on some resource, typically a variable or data structure with associated -// invariants. Proper usage of mutexes prevents concurrent access by different -// threads to the same resource. -// -// A `Mutex` has two basic operations: `Mutex::Lock()` and `Mutex::Unlock()`. -// The `Lock()` operation *acquires* a `Mutex` (in a state known as an -// *exclusive* -- or write -- lock), while the `Unlock()` operation *releases* a -// Mutex. During the span of time between the Lock() and Unlock() operations, -// a mutex is said to be *held*. By design all mutexes support exclusive/write -// locks, as this is the most common way to use a mutex. -// -// The `Mutex` state machine for basic lock/unlock operations is quite simple: -// -// | | Lock() | Unlock() | -// |----------------+------------+----------| -// | Free | Exclusive | invalid | -// | Exclusive | blocks | Free | -// -// Attempts to `Unlock()` must originate from the thread that performed the -// corresponding `Lock()` operation. -// -// An "invalid" operation is disallowed by the API. The `Mutex` implementation -// is allowed to do anything on an invalid call, including but not limited to -// crashing with a useful error message, silently succeeding, or corrupting -// data structures. In debug mode, the implementation attempts to crash with a -// useful error message. -// -// `Mutex` is not guaranteed to be "fair" in prioritizing waiting threads; it -// is, however, approximately fair over long periods, and starvation-free for -// threads at the same priority. -// -// The lock/unlock primitives are now annotated with lock annotations -// defined in (base/thread_annotations.h). When writing multi-threaded code, -// you should use lock annotations whenever possible to document your lock -// synchronization policy. Besides acting as documentation, these annotations -// also help compilers or static analysis tools to identify and warn about -// issues that could potentially result in race conditions and deadlocks. -// -// For more information about the lock annotations, please see -// [Thread Safety Analysis](http://clang.llvm.org/docs/ThreadSafetyAnalysis.html) -// in the Clang documentation. -// -// See also `MutexLock`, below, for scoped `Mutex` acquisition. - -class ABSL_LOCKABLE Mutex { - public: - // Creates a `Mutex` that is not held by anyone. This constructor is - // typically used for Mutexes allocated on the heap or the stack. - // - // To create `Mutex` instances with static storage duration - // (e.g. a namespace-scoped or global variable), see - // `Mutex::Mutex(absl::kConstInit)` below instead. - Mutex(); - - // Creates a mutex with static storage duration. A global variable - // constructed this way avoids the lifetime issues that can occur on program - // startup and shutdown. (See absl/base/const_init.h.) - // - // For Mutexes allocated on the heap and stack, instead use the default - // constructor, which can interact more fully with the thread sanitizer. - // - // Example usage: - // namespace foo { - // ABSL_CONST_INIT Mutex mu(absl::kConstInit); - // } - explicit constexpr Mutex(absl::ConstInitType); - - ~Mutex(); - - // Mutex::Lock() - // - // Blocks the calling thread, if necessary, until this `Mutex` is free, and - // then acquires it exclusively. (This lock is also known as a "write lock.") - void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(); - - // Mutex::Unlock() - // - // Releases this `Mutex` and returns it from the exclusive/write state to the - // free state. Caller must hold the `Mutex` exclusively. - void Unlock() ABSL_UNLOCK_FUNCTION(); - - // Mutex::TryLock() - // - // If the mutex can be acquired without blocking, does so exclusively and - // returns `true`. Otherwise, returns `false`. Returns `true` with high - // probability if the `Mutex` was free. - bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true); - - // Mutex::AssertHeld() - // - // Return immediately if this thread holds the `Mutex` exclusively (in write - // mode). Otherwise, may report an error (typically by crashing with a - // diagnostic), or may return immediately. - void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK(); - - // --------------------------------------------------------------------------- - // Reader-Writer Locking - // --------------------------------------------------------------------------- - - // A Mutex can also be used as a starvation-free reader-writer lock. - // Neither read-locks nor write-locks are reentrant/recursive to avoid - // potential client programming errors. - // - // The Mutex API provides `Writer*()` aliases for the existing `Lock()`, - // `Unlock()` and `TryLock()` methods for use within applications mixing - // reader/writer locks. Using `Reader*()` and `Writer*()` operations in this - // manner can make locking behavior clearer when mixing read and write modes. - // - // Introducing reader locks necessarily complicates the `Mutex` state - // machine somewhat. The table below illustrates the allowed state transitions - // of a mutex in such cases. Note that ReaderLock() may block even if the lock - // is held in shared mode; this occurs when another thread is blocked on a - // call to WriterLock(). - // - // --------------------------------------------------------------------------- - // Operation: WriterLock() Unlock() ReaderLock() ReaderUnlock() - // --------------------------------------------------------------------------- - // State - // --------------------------------------------------------------------------- - // Free Exclusive invalid Shared(1) invalid - // Shared(1) blocks invalid Shared(2) or blocks Free - // Shared(n) n>1 blocks invalid Shared(n+1) or blocks Shared(n-1) - // Exclusive blocks Free blocks invalid - // --------------------------------------------------------------------------- - // - // In comments below, "shared" refers to a state of Shared(n) for any n > 0. - - // Mutex::ReaderLock() - // - // Blocks the calling thread, if necessary, until this `Mutex` is either free, - // or in shared mode, and then acquires a share of it. Note that - // `ReaderLock()` will block if some other thread has an exclusive/writer lock - // on the mutex. - - void ReaderLock() ABSL_SHARED_LOCK_FUNCTION(); - - // Mutex::ReaderUnlock() - // - // Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to - // the free state if this thread holds the last reader lock on the mutex. Note - // that you cannot call `ReaderUnlock()` on a mutex held in write mode. - void ReaderUnlock() ABSL_UNLOCK_FUNCTION(); - - // Mutex::ReaderTryLock() - // - // If the mutex can be acquired without blocking, acquires this mutex for - // shared access and returns `true`. Otherwise, returns `false`. Returns - // `true` with high probability if the `Mutex` was free or shared. - bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true); - - // Mutex::AssertReaderHeld() - // - // Returns immediately if this thread holds the `Mutex` in at least shared - // mode (read mode). Otherwise, may report an error (typically by - // crashing with a diagnostic), or may return immediately. - void AssertReaderHeld() const ABSL_ASSERT_SHARED_LOCK(); - - // Mutex::WriterLock() - // Mutex::WriterUnlock() - // Mutex::WriterTryLock() - // - // Aliases for `Mutex::Lock()`, `Mutex::Unlock()`, and `Mutex::TryLock()`. - // - // These methods may be used (along with the complementary `Reader*()` - // methods) to distingish simple exclusive `Mutex` usage (`Lock()`, - // etc.) from reader/writer lock usage. - void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); } - - void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); } - - bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) { - return this->TryLock(); - } - - // --------------------------------------------------------------------------- - // Conditional Critical Regions - // --------------------------------------------------------------------------- - - // Conditional usage of a `Mutex` can occur using two distinct paradigms: - // - // * Use of `Mutex` member functions with `Condition` objects. - // * Use of the separate `CondVar` abstraction. - // - // In general, prefer use of `Condition` and the `Mutex` member functions - // listed below over `CondVar`. When there are multiple threads waiting on - // distinctly different conditions, however, a battery of `CondVar`s may be - // more efficient. This section discusses use of `Condition` objects. - // - // `Mutex` contains member functions for performing lock operations only under - // certain conditions, of class `Condition`. For correctness, the `Condition` - // must return a boolean that is a pure function, only of state protected by - // the `Mutex`. The condition must be invariant w.r.t. environmental state - // such as thread, cpu id, or time, and must be `noexcept`. The condition will - // always be invoked with the mutex held in at least read mode, so you should - // not block it for long periods or sleep it on a timer. - // - // Since a condition must not depend directly on the current time, use - // `*WithTimeout()` member function variants to make your condition - // effectively true after a given duration, or `*WithDeadline()` variants to - // make your condition effectively true after a given time. - // - // The condition function should have no side-effects aside from debug - // logging; as a special exception, the function may acquire other mutexes - // provided it releases all those that it acquires. (This exception was - // required to allow logging.) - - // Mutex::Await() - // - // Unlocks this `Mutex` and blocks until simultaneously both `cond` is `true` - // and this `Mutex` can be reacquired, then reacquires this `Mutex` in the - // same mode in which it was previously held. If the condition is initially - // `true`, `Await()` *may* skip the release/re-acquire step. - // - // `Await()` requires that this thread holds this `Mutex` in some mode. - void Await(const Condition &cond); - - // Mutex::LockWhen() - // Mutex::ReaderLockWhen() - // Mutex::WriterLockWhen() - // - // Blocks until simultaneously both `cond` is `true` and this `Mutex` can - // be acquired, then atomically acquires this `Mutex`. `LockWhen()` is - // logically equivalent to `*Lock(); Await();` though they may have different - // performance characteristics. - void LockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION(); - - void ReaderLockWhen(const Condition &cond) ABSL_SHARED_LOCK_FUNCTION(); - - void WriterLockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() { - this->LockWhen(cond); - } - - // --------------------------------------------------------------------------- - // Mutex Variants with Timeouts/Deadlines - // --------------------------------------------------------------------------- - - // Mutex::AwaitWithTimeout() - // Mutex::AwaitWithDeadline() - // - // Unlocks this `Mutex` and blocks until simultaneously: - // - either `cond` is true or the {timeout has expired, deadline has passed} - // and - // - this `Mutex` can be reacquired, - // then reacquire this `Mutex` in the same mode in which it was previously - // held, returning `true` iff `cond` is `true` on return. - // - // If the condition is initially `true`, the implementation *may* skip the - // release/re-acquire step and return immediately. - // - // Deadlines in the past are equivalent to an immediate deadline. - // Negative timeouts are equivalent to a zero timeout. - // - // This method requires that this thread holds this `Mutex` in some mode. - bool AwaitWithTimeout(const Condition &cond, absl::Duration timeout); - - bool AwaitWithDeadline(const Condition &cond, absl::Time deadline); - - // Mutex::LockWhenWithTimeout() - // Mutex::ReaderLockWhenWithTimeout() - // Mutex::WriterLockWhenWithTimeout() - // - // Blocks until simultaneously both: - // - either `cond` is `true` or the timeout has expired, and - // - this `Mutex` can be acquired, - // then atomically acquires this `Mutex`, returning `true` iff `cond` is - // `true` on return. - // - // Negative timeouts are equivalent to a zero timeout. - bool LockWhenWithTimeout(const Condition &cond, absl::Duration timeout) - ABSL_EXCLUSIVE_LOCK_FUNCTION(); - bool ReaderLockWhenWithTimeout(const Condition &cond, absl::Duration timeout) - ABSL_SHARED_LOCK_FUNCTION(); - bool WriterLockWhenWithTimeout(const Condition &cond, absl::Duration timeout) - ABSL_EXCLUSIVE_LOCK_FUNCTION() { - return this->LockWhenWithTimeout(cond, timeout); - } - - // Mutex::LockWhenWithDeadline() - // Mutex::ReaderLockWhenWithDeadline() - // Mutex::WriterLockWhenWithDeadline() - // - // Blocks until simultaneously both: - // - either `cond` is `true` or the deadline has been passed, and - // - this `Mutex` can be acquired, - // then atomically acquires this Mutex, returning `true` iff `cond` is `true` - // on return. - // - // Deadlines in the past are equivalent to an immediate deadline. - bool LockWhenWithDeadline(const Condition &cond, absl::Time deadline) - ABSL_EXCLUSIVE_LOCK_FUNCTION(); - bool ReaderLockWhenWithDeadline(const Condition &cond, absl::Time deadline) - ABSL_SHARED_LOCK_FUNCTION(); - bool WriterLockWhenWithDeadline(const Condition &cond, absl::Time deadline) - ABSL_EXCLUSIVE_LOCK_FUNCTION() { - return this->LockWhenWithDeadline(cond, deadline); - } - - // --------------------------------------------------------------------------- - // Debug Support: Invariant Checking, Deadlock Detection, Logging. - // --------------------------------------------------------------------------- - - // Mutex::EnableInvariantDebugging() - // - // If `invariant`!=null and if invariant debugging has been enabled globally, - // cause `(*invariant)(arg)` to be called at moments when the invariant for - // this `Mutex` should hold (for example: just after acquire, just before - // release). - // - // The routine `invariant` should have no side-effects since it is not - // guaranteed how many times it will be called; it should check the invariant - // and crash if it does not hold. Enabling global invariant debugging may - // substantially reduce `Mutex` performance; it should be set only for - // non-production runs. Optimization options may also disable invariant - // checks. - void EnableInvariantDebugging(void (*invariant)(void *), void *arg); - - // Mutex::EnableDebugLog() - // - // Cause all subsequent uses of this `Mutex` to be logged via - // `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if no previous - // call to `EnableInvariantDebugging()` or `EnableDebugLog()` has been made. - // - // Note: This method substantially reduces `Mutex` performance. - void EnableDebugLog(const char *name); - - // Deadlock detection - - // Mutex::ForgetDeadlockInfo() - // - // Forget any deadlock-detection information previously gathered - // about this `Mutex`. Call this method in debug mode when the lock ordering - // of a `Mutex` changes. - void ForgetDeadlockInfo(); - - // Mutex::AssertNotHeld() - // - // Return immediately if this thread does not hold this `Mutex` in any - // mode; otherwise, may report an error (typically by crashing with a - // diagnostic), or may return immediately. - // - // Currently this check is performed only if all of: - // - in debug mode - // - SetMutexDeadlockDetectionMode() has been set to kReport or kAbort - // - number of locks concurrently held by this thread is not large. - // are true. - void AssertNotHeld() const; - - // Special cases. - - // A `MuHow` is a constant that indicates how a lock should be acquired. - // Internal implementation detail. Clients should ignore. - typedef const struct MuHowS *MuHow; - - // Mutex::InternalAttemptToUseMutexInFatalSignalHandler() - // - // Causes the `Mutex` implementation to prepare itself for re-entry caused by - // future use of `Mutex` within a fatal signal handler. This method is - // intended for use only for last-ditch attempts to log crash information. - // It does not guarantee that attempts to use Mutexes within the handler will - // not deadlock; it merely makes other faults less likely. - // - // WARNING: This routine must be invoked from a signal handler, and the - // signal handler must either loop forever or terminate the process. - // Attempts to return from (or `longjmp` out of) the signal handler once this - // call has been made may cause arbitrary program behaviour including - // crashes and deadlocks. - static void InternalAttemptToUseMutexInFatalSignalHandler(); - - private: - std::atomic<intptr_t> mu_; // The Mutex state. - - // Post()/Wait() versus associated PerThreadSem; in class for required - // friendship with PerThreadSem. - static inline void IncrementSynchSem(Mutex *mu, - base_internal::PerThreadSynch *w); - static inline bool DecrementSynchSem( - Mutex *mu, base_internal::PerThreadSynch *w, - synchronization_internal::KernelTimeout t); - - // slow path acquire - void LockSlowLoop(SynchWaitParams *waitp, int flags); - // wrappers around LockSlowLoop() - bool LockSlowWithDeadline(MuHow how, const Condition *cond, - synchronization_internal::KernelTimeout t, - int flags); - void LockSlow(MuHow how, const Condition *cond, - int flags) ABSL_ATTRIBUTE_COLD; - // slow path release - void UnlockSlow(SynchWaitParams *waitp) ABSL_ATTRIBUTE_COLD; - // Common code between Await() and AwaitWithTimeout/Deadline() - bool AwaitCommon(const Condition &cond, - synchronization_internal::KernelTimeout t); - // Attempt to remove thread s from queue. - void TryRemove(base_internal::PerThreadSynch *s); - // Block a thread on mutex. - void Block(base_internal::PerThreadSynch *s); - // Wake a thread; return successor. - base_internal::PerThreadSynch *Wakeup(base_internal::PerThreadSynch *w); - - friend class CondVar; // for access to Trans()/Fer(). - void Trans(MuHow how); // used for CondVar->Mutex transfer - void Fer( - base_internal::PerThreadSynch *w); // used for CondVar->Mutex transfer - - // Catch the error of writing Mutex when intending MutexLock. - Mutex(const volatile Mutex * /*ignored*/) {} // NOLINT(runtime/explicit) - - Mutex(const Mutex&) = delete; - Mutex& operator=(const Mutex&) = delete; -}; - -// ----------------------------------------------------------------------------- -// Mutex RAII Wrappers -// ----------------------------------------------------------------------------- - -// MutexLock -// -// `MutexLock` is a helper class, which acquires and releases a `Mutex` via -// RAII. -// -// Example: -// -// Class Foo { -// public: -// Foo::Bar* Baz() { -// MutexLock lock(&mu_); -// ... -// return bar; -// } -// -// private: -// Mutex mu_; -// }; -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; - MutexLock& operator=(MutexLock&&) = delete; - - ~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->Unlock(); } - - private: - Mutex *const mu_; -}; - -// ReaderMutexLock -// -// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and -// releases a shared lock on a `Mutex` via RAII. -class ABSL_SCOPED_LOCKABLE ReaderMutexLock { - public: - explicit ReaderMutexLock(Mutex *mu) ABSL_SHARED_LOCK_FUNCTION(mu) : mu_(mu) { - mu->ReaderLock(); - } - - explicit ReaderMutexLock(Mutex *mu, const Condition &cond) - ABSL_SHARED_LOCK_FUNCTION(mu) - : mu_(mu) { - mu->ReaderLockWhen(cond); - } - - ReaderMutexLock(const ReaderMutexLock&) = delete; - ReaderMutexLock(ReaderMutexLock&&) = delete; - ReaderMutexLock& operator=(const ReaderMutexLock&) = delete; - ReaderMutexLock& operator=(ReaderMutexLock&&) = delete; - - ~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->ReaderUnlock(); } - - private: - Mutex *const mu_; -}; - -// WriterMutexLock -// -// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and -// releases a write (exclusive) lock on a `Mutex` via RAII. -class ABSL_SCOPED_LOCKABLE WriterMutexLock { - public: - explicit WriterMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) - : mu_(mu) { - mu->WriterLock(); - } - - explicit WriterMutexLock(Mutex *mu, const Condition &cond) - ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) - : mu_(mu) { - mu->WriterLockWhen(cond); - } - - WriterMutexLock(const WriterMutexLock&) = delete; - WriterMutexLock(WriterMutexLock&&) = delete; - WriterMutexLock& operator=(const WriterMutexLock&) = delete; - WriterMutexLock& operator=(WriterMutexLock&&) = delete; - - ~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->WriterUnlock(); } - - private: - Mutex *const mu_; -}; - -// ----------------------------------------------------------------------------- -// Condition -// ----------------------------------------------------------------------------- -// -// As noted above, `Mutex` contains a number of member functions which take a -// `Condition` as an argument; clients can wait for conditions to become `true` -// before attempting to acquire the mutex. These sections are known as -// "condition critical" sections. To use a `Condition`, you simply need to -// construct it, and use within an appropriate `Mutex` member function; -// everything else in the `Condition` class is an implementation detail. -// -// A `Condition` is specified as a function pointer which returns a boolean. -// `Condition` functions should be pure functions -- their results should depend -// only on passed arguments, should not consult any external state (such as -// clocks), and should have no side-effects, aside from debug logging. Any -// objects that the function may access should be limited to those which are -// constant while the mutex is blocked on the condition (e.g. a stack variable), -// or objects of state protected explicitly by the mutex. -// -// No matter which construction is used for `Condition`, the underlying -// function pointer / functor / callable must not throw any -// exceptions. Correctness of `Mutex` / `Condition` is not guaranteed in -// the face of a throwing `Condition`. (When Abseil is allowed to depend -// on C++17, these function pointers will be explicitly marked -// `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. -// -// Example using LockWhen/Unlock: -// -// // 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); -// // ... -// } -// -// When multiple threads are waiting on exactly the same condition, make sure -// that they are constructed with the same parameters (same pointer to function -// + arg, or same pointer to object + method), so that the mutex implementation -// can avoid redundantly evaluating the same condition for each thread. -class Condition { - public: - // A Condition that returns the result of "(*func)(arg)" - Condition(bool (*func)(void *), void *arg); - - // Templated version for people who are averse to casts. - // - // To use a lambda, prepend it with unary plus, which converts the lambda - // into a function pointer: - // Condition(+[](T* t) { return ...; }, arg). - // - // Note: lambdas in this case must contain no bound variables. - // - // See class comment for performance advice. - template<typename T> - Condition(bool (*func)(T *), T *arg); - - // Templated version for invoking a method that returns a `bool`. - // - // `Condition(object, &Class::Method)` constructs a `Condition` that evaluates - // `object->Method()`. - // - // Implementation Note: `absl::internal::identity` is used to allow methods to - // come from base classes. A simpler signature like - // `Condition(T*, bool (T::*)())` does not suffice. - template<typename T> - Condition(T *object, bool (absl::internal::identity<T>::type::* method)()); - - // Same as above, for const members - template<typename T> - Condition(const T *object, - bool (absl::internal::identity<T>::type::* method)() const); - - // A Condition that returns the value of `*cond` - explicit Condition(const bool *cond); - - // Templated version for invoking a functor that returns a `bool`. - // This approach accepts pointers to non-mutable lambdas, `std::function`, - // the result of` std::bind` and user-defined functors that define - // `bool F::operator()() const`. - // - // Example: - // - // auto reached = [this, current]() { - // mu_.AssertReaderHeld(); // For annotalysis. - // 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 - // that all waiters construct the condition with the same pointers. - - // Implementation note: The second template parameter ensures that this - // constructor doesn't participate in overload resolution if T doesn't have - // `bool operator() const`. - template <typename T, typename E = decltype( - static_cast<bool (T::*)() const>(&T::operator()))> - explicit Condition(const T *obj) - : Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {} - - // A Condition that always returns `true`. - static const Condition kTrue; - - // Evaluates the condition. - bool Eval() const; - - // Returns `true` if the two conditions are guaranteed to return the same - // value if evaluated at the same time, `false` if the evaluation *may* return - // different results. - // - // Two `Condition` values are guaranteed equal if both their `func` and `arg` - // components are the same. A null pointer is equivalent to a `true` - // condition. - static bool GuaranteedEqual(const Condition *a, const Condition *b); - - private: - typedef bool (*InternalFunctionType)(void * arg); - typedef bool (Condition::*InternalMethodType)(); - typedef bool (*InternalMethodCallerType)(void * arg, - InternalMethodType internal_method); - - bool (*eval_)(const Condition*); // Actual evaluator - InternalFunctionType function_; // function taking pointer returning bool - InternalMethodType method_; // method returning bool - void *arg_; // arg of function_ or object of method_ - - Condition(); // null constructor used only to create kTrue - - // Various functions eval_ can point to: - static bool CallVoidPtrFunction(const Condition*); - template <typename T> static bool CastAndCallFunction(const Condition* c); - template <typename T> static bool CastAndCallMethod(const Condition* c); -}; - -// ----------------------------------------------------------------------------- -// CondVar -// ----------------------------------------------------------------------------- -// -// A condition variable, reflecting state evaluated separately outside of the -// `Mutex` object, which can be signaled to wake callers. -// This class is not normally needed; use `Mutex` member functions such as -// `Mutex::Await()` and intrinsic `Condition` abstractions. In rare cases -// with many threads and many conditions, `CondVar` may be faster. -// -// The implementation may deliver signals to any condition variable at -// any time, even when no call to `Signal()` or `SignalAll()` is made; as a -// result, upon being awoken, you must check the logical condition you have -// been waiting upon. -// -// Examples: -// -// Usage for a thread waiting for some condition C protected by mutex mu: -// mu.Lock(); -// while (!C) { cv->Wait(&mu); } // releases and reacquires mu -// // C holds; process data -// mu.Unlock(); -// -// Usage to wake T is: -// mu.Lock(); -// // 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()`. -// -// With this implementation it is efficient to use `Signal()/SignalAll()` inside -// the locked region; this usage can make reasoning about your program easier. -// -class CondVar { - public: - // A `CondVar` allocated on the heap or on the stack can use the this - // constructor. - CondVar(); - ~CondVar(); - - // CondVar::Wait() - // - // Atomically releases a `Mutex` and blocks on this condition variable. - // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a - // spurious wakeup), then reacquires the `Mutex` and returns. - // - // Requires and ensures that the current thread holds the `Mutex`. - void Wait(Mutex *mu); - - // CondVar::WaitWithTimeout() - // - // Atomically releases a `Mutex` and blocks on this condition variable. - // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a - // spurious wakeup), or until the timeout has expired, then reacquires - // the `Mutex` and returns. - // - // Returns true if the timeout has expired without this `CondVar` - // being signalled in any manner. If both the timeout has expired - // and this `CondVar` has been signalled, the implementation is free - // to return `true` or `false`. - // - // Requires and ensures that the current thread holds the `Mutex`. - bool WaitWithTimeout(Mutex *mu, absl::Duration timeout); - - // CondVar::WaitWithDeadline() - // - // Atomically releases a `Mutex` and blocks on this condition variable. - // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a - // spurious wakeup), or until the deadline has passed, then reacquires - // the `Mutex` and returns. - // - // Deadlines in the past are equivalent to an immediate deadline. - // - // Returns true if the deadline has passed without this `CondVar` - // being signalled in any manner. If both the deadline has passed - // and this `CondVar` has been signalled, the implementation is free - // to return `true` or `false`. - // - // Requires and ensures that the current thread holds the `Mutex`. - bool WaitWithDeadline(Mutex *mu, absl::Time deadline); - - // CondVar::Signal() - // - // Signal this `CondVar`; wake at least one waiter if one exists. - void Signal(); - - // CondVar::SignalAll() - // - // Signal this `CondVar`; wake all waiters. - void SignalAll(); - - // CondVar::EnableDebugLog() - // - // Causes all subsequent uses of this `CondVar` to be logged via - // `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if `name != 0`. - // Note: this method substantially reduces `CondVar` performance. - void EnableDebugLog(const char *name); - - private: - 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. - CondVar(const CondVar&) = delete; - CondVar& operator=(const CondVar&) = delete; -}; - - -// Variants of MutexLock. -// -// If you find yourself using one of these, consider instead using -// Mutex::Unlock() and/or if-statements for clarity. - -// MutexLockMaybe -// -// MutexLockMaybe is like MutexLock, but is a no-op when mu is null. -class ABSL_SCOPED_LOCKABLE MutexLockMaybe { - public: - explicit MutexLockMaybe(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) - : mu_(mu) { - if (this->mu_ != nullptr) { - this->mu_->Lock(); - } - } - - explicit MutexLockMaybe(Mutex *mu, const Condition &cond) - ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) - : mu_(mu) { - if (this->mu_ != nullptr) { - this->mu_->LockWhen(cond); - } - } - - ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() { - if (this->mu_ != nullptr) { this->mu_->Unlock(); } - } - - private: - Mutex *const mu_; - MutexLockMaybe(const MutexLockMaybe&) = delete; - MutexLockMaybe(MutexLockMaybe&&) = delete; - MutexLockMaybe& operator=(const MutexLockMaybe&) = delete; - MutexLockMaybe& operator=(MutexLockMaybe&&) = delete; -}; - -// ReleasableMutexLock -// -// ReleasableMutexLock is like MutexLock, but permits `Release()` of its -// mutex before destruction. `Release()` may be called at most once. -class ABSL_SCOPED_LOCKABLE ReleasableMutexLock { - public: - explicit ReleasableMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) - : 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(); } - } - - void Release() ABSL_UNLOCK_FUNCTION(); - - private: - Mutex *mu_; - ReleasableMutexLock(const ReleasableMutexLock&) = delete; - ReleasableMutexLock(ReleasableMutexLock&&) = delete; - ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; - ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete; -}; - -inline Mutex::Mutex() : mu_(0) { - ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); -} - -inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {} - -inline CondVar::CondVar() : cv_(0) {} - -// static -template <typename T> -bool Condition::CastAndCallMethod(const Condition *c) { - typedef bool (T::*MemberType)(); - MemberType rm = reinterpret_cast<MemberType>(c->method_); - T *x = static_cast<T *>(c->arg_); - return (x->*rm)(); -} - -// static -template <typename T> -bool Condition::CastAndCallFunction(const Condition *c) { - typedef bool (*FuncType)(T *); - FuncType fn = reinterpret_cast<FuncType>(c->function_); - T *x = static_cast<T *>(c->arg_); - return (*fn)(x); -} - -template <typename T> -inline Condition::Condition(bool (*func)(T *), T *arg) - : eval_(&CastAndCallFunction<T>), - function_(reinterpret_cast<InternalFunctionType>(func)), - method_(nullptr), - arg_(const_cast<void *>(static_cast<const void *>(arg))) {} - -template <typename T> -inline Condition::Condition(T *object, - bool (absl::internal::identity<T>::type::*method)()) - : eval_(&CastAndCallMethod<T>), - function_(nullptr), - method_(reinterpret_cast<InternalMethodType>(method)), - arg_(object) {} - -template <typename T> -inline Condition::Condition(const T *object, - bool (absl::internal::identity<T>::type::*method)() - const) - : eval_(&CastAndCallMethod<T>), - function_(nullptr), - method_(reinterpret_cast<InternalMethodType>(method)), - arg_(reinterpret_cast<void *>(const_cast<T *>(object))) {} - -// Register a hook for profiling support. -// -// The function pointer registered here will be called whenever a mutex is -// contended. The callback is given the absl/base/cycleclock.h timestamp when -// waiting began. -// -// Calls to this function do not race or block, but there is no ordering -// guaranteed between calls to this function and call to the provided hook. -// In particular, the previously registered hook may still be called for some -// time after this function returns. -void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)); - -// Register a hook for Mutex tracing. -// -// The function pointer registered here will be called whenever a mutex is -// contended. The callback is given an opaque handle to the contended mutex, -// an event name, and the number of wait cycles (as measured by -// //absl/base/internal/cycleclock.h, and which may not be real -// "cycle" counts.) -// -// The only event name currently sent is "slow release". -// -// This has the same memory ordering concerns as RegisterMutexProfiler() above. -void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj, - int64_t wait_cycles)); - -// TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer() -// into a single interface, since they are only ever called in pairs. - -// Register a hook for CondVar tracing. -// -// The function pointer registered here will be called here on various CondVar -// events. The callback is given an opaque handle to the CondVar object and -// a string identifying the event. This is thread-safe, but only a single -// tracer can be registered. -// -// Events that can be sent are "Wait", "Unwait", "Signal wakeup", and -// "SignalAll wakeup". -// -// This has the same memory ordering concerns as RegisterMutexProfiler() above. -void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv)); - -// Register a hook for symbolizing stack traces in deadlock detector reports. -// -// 'pc' is the program counter being symbolized, 'out' is the buffer to write -// into, and 'out_size' is the size of the buffer. This function can return -// false if symbolizing failed, or true if a NUL-terminated symbol was written -// to 'out.' -// -// This has the same memory ordering concerns as RegisterMutexProfiler() above. -// -// DEPRECATED: The default symbolizer function is absl::Symbolize() and the -// ability to register a different hook for symbolizing stack traces will be -// removed on or after 2023-05-01. -ABSL_DEPRECATED("absl::RegisterSymbolizer() is deprecated and will be removed " - "on or after 2023-05-01") -void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)); - -// EnableMutexInvariantDebugging() -// -// Enable or disable global support for Mutex invariant debugging. If enabled, -// then invariant predicates can be registered per-Mutex for debug checking. -// See Mutex::EnableInvariantDebugging(). -void EnableMutexInvariantDebugging(bool enabled); - -// When in debug mode, and when the feature has been enabled globally, the -// implementation will keep track of lock ordering and complain (or optionally -// crash) if a cycle is detected in the acquired-before graph. - -// Possible modes of operation for the deadlock detector in debug mode. -enum class OnDeadlockCycle { - kIgnore, // Neither report on nor attempt to track cycles in lock ordering - kReport, // Report lock cycles to stderr when detected - kAbort, // Report lock cycles to stderr when detected, then abort -}; - -// SetMutexDeadlockDetectionMode() -// -// Enable or disable global support for detection of potential deadlocks -// due to Mutex lock ordering inversions. When set to 'kIgnore', tracking of -// lock ordering is disabled. Otherwise, in debug builds, a lock ordering graph -// will be maintained internally, and detected cycles will be reported in -// the manner chosen here. -void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode); - -ABSL_NAMESPACE_END -} // namespace absl - -// In some build configurations we pass --detect-odr-violations to the -// gold linker. This causes it to flag weak symbol overrides as ODR -// violations. Because ODR only applies to C++ and not C, -// --detect-odr-violations ignores symbols not mangled with C++ names. -// By changing our extension points to be extern "C", we dodge this -// check. -extern "C" { -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 deleted file mode 100644 index 933ea14f8f1d..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/mutex_benchmark.cc +++ /dev/null @@ -1,224 +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 <cstdint> -#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" -#include "absl/synchronization/internal/thread_pool.h" -#include "absl/synchronization/mutex.h" -#include "benchmark/benchmark.h" - -namespace { - -void BM_Mutex(benchmark::State& state) { - static absl::Mutex* mu = new absl::Mutex; - for (auto _ : state) { - absl::MutexLock lock(mu); - } -} -BENCHMARK(BM_Mutex)->UseRealTime()->Threads(1)->ThreadPerCpu(); - -static void DelayNs(int64_t ns, int* data) { - int64_t end = absl::base_internal::CycleClock::Now() + - ns * absl::base_internal::CycleClock::Frequency() / 1e9; - while (absl::base_internal::CycleClock::Now() < end) { - ++(*data); - benchmark::DoNotOptimize(*data); - } -} - -template <typename MutexType> -class RaiiLocker { - public: - explicit RaiiLocker(MutexType* mu) : mu_(mu) { mu_->Lock(); } - ~RaiiLocker() { mu_->Unlock(); } - private: - MutexType* mu_; -}; - -template <> -class RaiiLocker<std::mutex> { - public: - explicit RaiiLocker(std::mutex* mu) : mu_(mu) { mu_->lock(); } - ~RaiiLocker() { mu_->unlock(); } - private: - std::mutex* mu_; -}; - -template <typename MutexType> -void BM_Contended(benchmark::State& state) { - struct Shared { - MutexType mu; - int data = 0; - }; - static auto* shared = new Shared; - int local = 0; - for (auto _ : state) { - // Here we model both local work outside of the critical section as well as - // some work inside of the critical section. The idea is to capture some - // more or less realisitic contention levels. - // If contention is too low, the benchmark won't measure anything useful. - // If contention is unrealistically high, the benchmark will favor - // bad mutex implementations that block and otherwise distract threads - // from the mutex and shared state for as much as possible. - // 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); - RaiiLocker<MutexType> locker(&shared->mu); - DelayNs(state.range(0), &shared->data); - } -} - -BENCHMARK_TEMPLATE(BM_Contended, absl::Mutex) - ->UseRealTime() - // ThreadPerCpu poorly handles non-power-of-two CPU counts. - ->Threads(1) - ->Threads(2) - ->Threads(4) - ->Threads(6) - ->Threads(8) - ->Threads(12) - ->Threads(16) - ->Threads(24) - ->Threads(32) - ->Threads(48) - ->Threads(64) - ->Threads(96) - ->Threads(128) - ->Threads(192) - ->Threads(256) - // Some empirically chosen amounts of work in critical section. - // 1 is low contention, 200 is high contention and few values in between. - ->Arg(1) - ->Arg(20) - ->Arg(50) - ->Arg(200); - -BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock) - ->UseRealTime() - // ThreadPerCpu poorly handles non-power-of-two CPU counts. - ->Threads(1) - ->Threads(2) - ->Threads(4) - ->Threads(6) - ->Threads(8) - ->Threads(12) - ->Threads(16) - ->Threads(24) - ->Threads(32) - ->Threads(48) - ->Threads(64) - ->Threads(96) - ->Threads(128) - ->Threads(192) - ->Threads(256) - // Some empirically chosen amounts of work in critical section. - // 1 is low contention, 200 is high contention and few values in between. - ->Arg(1) - ->Arg(20) - ->Arg(50) - ->Arg(200); - -BENCHMARK_TEMPLATE(BM_Contended, std::mutex) - ->UseRealTime() - // ThreadPerCpu poorly handles non-power-of-two CPU counts. - ->Threads(1) - ->Threads(2) - ->Threads(4) - ->Threads(6) - ->Threads(8) - ->Threads(12) - ->Threads(16) - ->Threads(24) - ->Threads(32) - ->Threads(48) - ->Threads(64) - ->Threads(96) - ->Threads(128) - ->Threads(192) - ->Threads(256) - // Some empirically chosen amounts of work in critical section. - // 1 is low contention, 200 is high contention and few values in between. - ->Arg(1) - ->Arg(20) - ->Arg(50) - ->Arg(200); - -// Measure the overhead of conditions on mutex release (when they must be -// evaluated). Mutex has (some) support for equivalence classes allowing -// Conditions with the same function/argument to potentially not be multiply -// evaluated. -// -// num_classes==0 is used for the special case of every waiter being distinct. -void BM_ConditionWaiters(benchmark::State& state) { - int num_classes = state.range(0); - int num_waiters = state.range(1); - - struct Helper { - static void Waiter(absl::BlockingCounter* init, absl::Mutex* m, int* p) { - init->DecrementCount(); - m->LockWhen(absl::Condition( - static_cast<bool (*)(int*)>([](int* v) { return *v == 0; }), p)); - m->Unlock(); - } - }; - - if (num_classes == 0) { - // No equivalence classes. - num_classes = num_waiters; - } - - absl::BlockingCounter init(num_waiters); - absl::Mutex mu; - std::vector<int> equivalence_classes(num_classes, 1); - - // Must be declared last to be destroyed first. - absl::synchronization_internal::ThreadPool pool(num_waiters); - - for (int i = 0; i < num_waiters; i++) { - // Mutex considers Conditions with the same function and argument - // to be equivalent. - pool.Schedule([&, i] { - Helper::Waiter(&init, &mu, &equivalence_classes[i % num_classes]); - }); - } - init.Wait(); - - for (auto _ : state) { - mu.Lock(); - mu.Unlock(); // Each unlock requires Condition evaluation for our waiters. - } - - mu.Lock(); - for (int i = 0; i < num_classes; i++) { - equivalence_classes[i] = 0; - } - mu.Unlock(); -} - -// Some configurations have higher thread limits than others. -#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER) -constexpr int kMaxConditionWaiters = 8192; -#else -constexpr int kMaxConditionWaiters = 1024; -#endif -BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters); - -} // namespace diff --git a/third_party/abseil_cpp/absl/synchronization/mutex_test.cc b/third_party/abseil_cpp/absl/synchronization/mutex_test.cc deleted file mode 100644 index 058f757b482f..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/mutex_test.cc +++ /dev/null @@ -1,1706 +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/synchronization/mutex.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include <algorithm> -#include <atomic> -#include <cstdlib> -#include <functional> -#include <memory> -#include <random> -#include <string> -#include <thread> // NOLINT(build/c++11) -#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" -#include "absl/synchronization/internal/thread_pool.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" - -namespace { - -// TODO(dmauro): Replace with a commandline flag. -static constexpr bool kExtendedTest = false; - -std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool( - int threads) { - return absl::make_unique<absl::synchronization_internal::ThreadPool>(threads); -} - -std::unique_ptr<absl::synchronization_internal::ThreadPool> -CreateDefaultPool() { - return CreatePool(kExtendedTest ? 32 : 10); -} - -// Hack to schedule a function to run on a thread pool thread after a -// duration has elapsed. -static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp, - absl::Duration after, - const std::function<void()> &func) { - tp->Schedule([func, after] { - absl::SleepFor(after); - func(); - }); -} - -struct TestContext { - int iterations; - int threads; - int g0; // global 0 - int g1; // global 1 - absl::Mutex mu; - absl::CondVar cv; -}; - -// To test whether the invariant check call occurs -static std::atomic<bool> invariant_checked; - -static bool GetInvariantChecked() { - return invariant_checked.load(std::memory_order_relaxed); -} - -static void SetInvariantChecked(bool new_value) { - invariant_checked.store(new_value, std::memory_order_relaxed); -} - -static void CheckSumG0G1(void *v) { - TestContext *cxt = static_cast<TestContext *>(v); - ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in CheckSumG0G1"); - SetInvariantChecked(true); -} - -static void TestMu(TestContext *cxt, int c) { - for (int i = 0; i != cxt->iterations; i++) { - absl::MutexLock l(&cxt->mu); - int a = cxt->g0 + 1; - cxt->g0 = a; - cxt->g1--; - } -} - -static void TestTry(TestContext *cxt, int c) { - for (int i = 0; i != cxt->iterations; i++) { - do { - std::this_thread::yield(); - } while (!cxt->mu.TryLock()); - int a = cxt->g0 + 1; - cxt->g0 = a; - cxt->g1--; - cxt->mu.Unlock(); - } -} - -static void TestR20ms(TestContext *cxt, int c) { - for (int i = 0; i != cxt->iterations; i++) { - absl::ReaderMutexLock l(&cxt->mu); - absl::SleepFor(absl::Milliseconds(20)); - cxt->mu.AssertReaderHeld(); - } -} - -static void TestRW(TestContext *cxt, int c) { - if ((c & 1) == 0) { - for (int i = 0; i != cxt->iterations; i++) { - absl::WriterMutexLock l(&cxt->mu); - cxt->g0++; - cxt->g1--; - cxt->mu.AssertHeld(); - cxt->mu.AssertReaderHeld(); - } - } else { - for (int i = 0; i != cxt->iterations; i++) { - absl::ReaderMutexLock l(&cxt->mu); - ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in TestRW"); - cxt->mu.AssertReaderHeld(); - } - } -} - -struct MyContext { - int target; - TestContext *cxt; - bool MyTurn(); -}; - -bool MyContext::MyTurn() { - TestContext *cxt = this->cxt; - return cxt->g0 == this->target || cxt->g0 == cxt->iterations; -} - -static void TestAwait(TestContext *cxt, int c) { - MyContext mc; - mc.target = c; - mc.cxt = cxt; - absl::MutexLock l(&cxt->mu); - cxt->mu.AssertHeld(); - while (cxt->g0 < cxt->iterations) { - cxt->mu.Await(absl::Condition(&mc, &MyContext::MyTurn)); - ABSL_RAW_CHECK(mc.MyTurn(), "Error in TestAwait"); - cxt->mu.AssertHeld(); - if (cxt->g0 < cxt->iterations) { - int a = cxt->g0 + 1; - cxt->g0 = a; - mc.target += cxt->threads; - } - } -} - -static void TestSignalAll(TestContext *cxt, int c) { - int target = c; - absl::MutexLock l(&cxt->mu); - cxt->mu.AssertHeld(); - while (cxt->g0 < cxt->iterations) { - while (cxt->g0 != target && cxt->g0 != cxt->iterations) { - cxt->cv.Wait(&cxt->mu); - } - if (cxt->g0 < cxt->iterations) { - int a = cxt->g0 + 1; - cxt->g0 = a; - cxt->cv.SignalAll(); - target += cxt->threads; - } - } -} - -static void TestSignal(TestContext *cxt, int c) { - ABSL_RAW_CHECK(cxt->threads == 2, "TestSignal should use 2 threads"); - int target = c; - absl::MutexLock l(&cxt->mu); - cxt->mu.AssertHeld(); - while (cxt->g0 < cxt->iterations) { - while (cxt->g0 != target && cxt->g0 != cxt->iterations) { - cxt->cv.Wait(&cxt->mu); - } - if (cxt->g0 < cxt->iterations) { - int a = cxt->g0 + 1; - cxt->g0 = a; - cxt->cv.Signal(); - target += cxt->threads; - } - } -} - -static void TestCVTimeout(TestContext *cxt, int c) { - int target = c; - absl::MutexLock l(&cxt->mu); - cxt->mu.AssertHeld(); - while (cxt->g0 < cxt->iterations) { - while (cxt->g0 != target && cxt->g0 != cxt->iterations) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100)); - } - if (cxt->g0 < cxt->iterations) { - int a = cxt->g0 + 1; - cxt->g0 = a; - cxt->cv.SignalAll(); - target += cxt->threads; - } - } -} - -static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; } - -static void TestTime(TestContext *cxt, int c, bool use_cv) { - ABSL_RAW_CHECK(cxt->iterations == 1, "TestTime should only use 1 iteration"); - ABSL_RAW_CHECK(cxt->threads > 2, "TestTime should use more than 2 threads"); - const bool kFalse = false; - absl::Condition false_cond(&kFalse); - absl::Condition g0ge2(G0GE2, cxt); - if (c == 0) { - absl::MutexLock l(&cxt->mu); - - absl::Time start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1)); - } else { - ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)), - "TestTime failed"); - } - absl::Duration elapsed = absl::Now() - start; - ABSL_RAW_CHECK( - absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0), - "TestTime failed"); - ABSL_RAW_CHECK(cxt->g0 == 1, "TestTime failed"); - - start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1)); - } else { - ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)), - "TestTime failed"); - } - elapsed = absl::Now() - start; - ABSL_RAW_CHECK( - absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0), - "TestTime failed"); - cxt->g0++; - if (use_cv) { - cxt->cv.Signal(); - } - - start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(4)); - } else { - ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(4)), - "TestTime failed"); - } - elapsed = absl::Now() - start; - ABSL_RAW_CHECK( - absl::Seconds(3.9) <= elapsed && elapsed <= absl::Seconds(6.0), - "TestTime failed"); - ABSL_RAW_CHECK(cxt->g0 >= 3, "TestTime failed"); - - start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1)); - } else { - ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)), - "TestTime failed"); - } - elapsed = absl::Now() - start; - ABSL_RAW_CHECK( - absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0), - "TestTime failed"); - if (use_cv) { - cxt->cv.SignalAll(); - } - - start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1)); - } else { - ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)), - "TestTime failed"); - } - elapsed = absl::Now() - start; - ABSL_RAW_CHECK(absl::Seconds(0.9) <= elapsed && - elapsed <= absl::Seconds(2.0), "TestTime failed"); - ABSL_RAW_CHECK(cxt->g0 == cxt->threads, "TestTime failed"); - - } else if (c == 1) { - absl::MutexLock l(&cxt->mu); - const absl::Time start = absl::Now(); - if (use_cv) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Milliseconds(500)); - } else { - ABSL_RAW_CHECK( - !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)), - "TestTime failed"); - } - const absl::Duration elapsed = absl::Now() - start; - ABSL_RAW_CHECK( - absl::Seconds(0.4) <= elapsed && elapsed <= absl::Seconds(0.9), - "TestTime failed"); - cxt->g0++; - } else if (c == 2) { - absl::MutexLock l(&cxt->mu); - if (use_cv) { - while (cxt->g0 < 2) { - cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100)); - } - } else { - ABSL_RAW_CHECK(cxt->mu.AwaitWithTimeout(g0ge2, absl::Seconds(100)), - "TestTime failed"); - } - cxt->g0++; - } else { - absl::MutexLock l(&cxt->mu); - if (use_cv) { - while (cxt->g0 < 2) { - cxt->cv.Wait(&cxt->mu); - } - } else { - cxt->mu.Await(g0ge2); - } - cxt->g0++; - } -} - -static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); } - -static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); } - -static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv, - const std::function<void(int)>& cb) { - mu->Lock(); - int c = (*c0)++; - mu->Unlock(); - cb(c); - absl::MutexLock l(mu); - (*c1)++; - cv->Signal(); -} - -// Code common to RunTest() and RunTestWithInvariantDebugging(). -static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int), - int threads, int iterations, int operations) { - absl::Mutex mu2; - absl::CondVar cv2; - int c0 = 0; - int c1 = 0; - cxt->g0 = 0; - cxt->g1 = 0; - cxt->iterations = iterations; - cxt->threads = threads; - absl::synchronization_internal::ThreadPool tp(threads); - for (int i = 0; i != threads; i++) { - tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2, - std::function<void(int)>( - std::bind(test, cxt, std::placeholders::_1)))); - } - mu2.Lock(); - while (c1 != threads) { - cv2.Wait(&mu2); - } - mu2.Unlock(); - return cxt->g0; -} - -// Basis for the parameterized tests configured below. -static int RunTest(void (*test)(TestContext *cxt, int), int threads, - int iterations, int operations) { - TestContext cxt; - return RunTestCommon(&cxt, test, threads, iterations, operations); -} - -// Like RunTest(), but sets an invariant on the tested Mutex and -// verifies that the invariant check happened. The invariant function -// will be passed the TestContext* as its arg and must call -// SetInvariantChecked(true); -#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED) -static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int), - int threads, int iterations, - int operations, - void (*invariant)(void *)) { - absl::EnableMutexInvariantDebugging(true); - SetInvariantChecked(false); - TestContext cxt; - cxt.mu.EnableInvariantDebugging(invariant, &cxt); - int ret = RunTestCommon(&cxt, test, threads, iterations, operations); - ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked"); - absl::EnableMutexInvariantDebugging(false); // Restore. - return ret; -} -#endif - -// -------------------------------------------------------- -// Test for fix of bug in TryRemove() -struct TimeoutBugStruct { - absl::Mutex mu; - bool a; - int a_waiter_count; -}; - -static void WaitForA(TimeoutBugStruct *x) { - x->mu.LockWhen(absl::Condition(&x->a)); - x->a_waiter_count--; - x->mu.Unlock(); -} - -static bool NoAWaiters(TimeoutBugStruct *x) { return x->a_waiter_count == 0; } - -// Test that a CondVar.Wait(&mutex) can un-block a call to mutex.Await() in -// another thread. -TEST(Mutex, CondVarWaitSignalsAwait) { - // Use a struct so the lock annotations apply. - struct { - absl::Mutex barrier_mu; - bool barrier ABSL_GUARDED_BY(barrier_mu) = false; - - absl::Mutex release_mu; - bool release ABSL_GUARDED_BY(release_mu) = false; - absl::CondVar released_cv; - } state; - - auto pool = CreateDefaultPool(); - - // Thread A. Sets barrier, waits for release using Mutex::Await, then - // signals released_cv. - pool->Schedule([&state] { - state.release_mu.Lock(); - - state.barrier_mu.Lock(); - state.barrier = true; - state.barrier_mu.Unlock(); - - state.release_mu.Await(absl::Condition(&state.release)); - state.released_cv.Signal(); - state.release_mu.Unlock(); - }); - - state.barrier_mu.LockWhen(absl::Condition(&state.barrier)); - state.barrier_mu.Unlock(); - state.release_mu.Lock(); - // Thread A is now blocked on release by way of Mutex::Await(). - - // Set release. Calling released_cv.Wait() should un-block thread A, - // which will signal released_cv. If not, the test will hang. - state.release = true; - state.released_cv.Wait(&state.release_mu); - state.release_mu.Unlock(); -} - -// Test that a CondVar.WaitWithTimeout(&mutex) can un-block a call to -// mutex.Await() in another thread. -TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) { - // Use a struct so the lock annotations apply. - struct { - absl::Mutex barrier_mu; - bool barrier ABSL_GUARDED_BY(barrier_mu) = false; - - absl::Mutex release_mu; - bool release ABSL_GUARDED_BY(release_mu) = false; - absl::CondVar released_cv; - } state; - - auto pool = CreateDefaultPool(); - - // Thread A. Sets barrier, waits for release using Mutex::Await, then - // signals released_cv. - pool->Schedule([&state] { - state.release_mu.Lock(); - - state.barrier_mu.Lock(); - state.barrier = true; - state.barrier_mu.Unlock(); - - state.release_mu.Await(absl::Condition(&state.release)); - state.released_cv.Signal(); - state.release_mu.Unlock(); - }); - - state.barrier_mu.LockWhen(absl::Condition(&state.barrier)); - state.barrier_mu.Unlock(); - state.release_mu.Lock(); - // Thread A is now blocked on release by way of Mutex::Await(). - - // Set release. Calling released_cv.Wait() should un-block thread A, - // which will signal released_cv. If not, the test will hang. - state.release = true; - EXPECT_TRUE( - !state.released_cv.WaitWithTimeout(&state.release_mu, absl::Seconds(10))) - << "; Unrecoverable test failure: CondVar::WaitWithTimeout did not " - "unblock the absl::Mutex::Await call in another thread."; - - state.release_mu.Unlock(); -} - -// Test for regression of a bug in loop of TryRemove() -TEST(Mutex, MutexTimeoutBug) { - auto tp = CreateDefaultPool(); - - TimeoutBugStruct x; - x.a = false; - x.a_waiter_count = 2; - tp->Schedule(std::bind(&WaitForA, &x)); - tp->Schedule(std::bind(&WaitForA, &x)); - absl::SleepFor(absl::Seconds(1)); // Allow first two threads to hang. - // The skip field of the second will point to the first because there are - // only two. - - // Now cause a thread waiting on an always-false to time out - // This would deadlock when the bug was present. - bool always_false = false; - x.mu.LockWhenWithTimeout(absl::Condition(&always_false), - absl::Milliseconds(500)); - - // if we get here, the bug is not present. Cleanup the state. - - x.a = true; // wakeup the two waiters on A - x.mu.Await(absl::Condition(&NoAWaiters, &x)); // wait for them to exit - x.mu.Unlock(); -} - -struct CondVarWaitDeadlock : testing::TestWithParam<int> { - absl::Mutex mu; - absl::CondVar cv; - bool cond1 = false; - bool cond2 = false; - bool read_lock1; - bool read_lock2; - bool signal_unlocked; - - CondVarWaitDeadlock() { - read_lock1 = GetParam() & (1 << 0); - read_lock2 = GetParam() & (1 << 1); - signal_unlocked = GetParam() & (1 << 2); - } - - void Waiter1() { - if (read_lock1) { - mu.ReaderLock(); - while (!cond1) { - cv.Wait(&mu); - } - mu.ReaderUnlock(); - } else { - mu.Lock(); - while (!cond1) { - cv.Wait(&mu); - } - mu.Unlock(); - } - } - - void Waiter2() { - if (read_lock2) { - mu.ReaderLockWhen(absl::Condition(&cond2)); - mu.ReaderUnlock(); - } else { - mu.LockWhen(absl::Condition(&cond2)); - mu.Unlock(); - } - } -}; - -// Test for a deadlock bug in Mutex::Fer(). -// The sequence of events that lead to the deadlock is: -// 1. waiter1 blocks on cv in read mode (mu bits = 0). -// 2. waiter2 blocks on mu in either mode (mu bits = kMuWait). -// 3. main thread locks mu, sets cond1, unlocks mu (mu bits = kMuWait). -// 4. main thread signals on cv and this eventually calls Mutex::Fer(). -// Currently Fer wakes waiter1 since mu bits = kMuWait (mutex is unlocked). -// Before the bug fix Fer neither woke waiter1 nor queued it on mutex, -// which resulted in deadlock. -TEST_P(CondVarWaitDeadlock, Test) { - auto waiter1 = CreatePool(1); - auto waiter2 = CreatePool(1); - waiter1->Schedule([this] { this->Waiter1(); }); - waiter2->Schedule([this] { this->Waiter2(); }); - - // Wait while threads block (best-effort is fine). - absl::SleepFor(absl::Milliseconds(100)); - - // Wake condwaiter. - mu.Lock(); - cond1 = true; - if (signal_unlocked) { - mu.Unlock(); - cv.Signal(); - } else { - cv.Signal(); - mu.Unlock(); - } - waiter1.reset(); // "join" waiter1 - - // Wake waiter. - mu.Lock(); - cond2 = true; - mu.Unlock(); - waiter2.reset(); // "join" waiter2 -} - -INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock, - ::testing::Range(0, 8), - ::testing::PrintToStringParamName()); - -// -------------------------------------------------------- -// Test for fix of bug in DequeueAllWakeable() -// Bug was that if there was more than one waiting reader -// and all should be woken, the most recently blocked one -// would not be. - -struct DequeueAllWakeableBugStruct { - absl::Mutex mu; - absl::Mutex mu2; // protects all fields below - int unfinished_count; // count of unfinished readers; under mu2 - bool done1; // unfinished_count == 0; under mu2 - int finished_count; // count of finished readers, under mu2 - bool done2; // finished_count == 0; under mu2 -}; - -// Test for regression of a bug in loop of DequeueAllWakeable() -static void AcquireAsReader(DequeueAllWakeableBugStruct *x) { - x->mu.ReaderLock(); - x->mu2.Lock(); - x->unfinished_count--; - x->done1 = (x->unfinished_count == 0); - x->mu2.Unlock(); - // make sure that both readers acquired mu before we release it. - absl::SleepFor(absl::Seconds(2)); - x->mu.ReaderUnlock(); - - x->mu2.Lock(); - x->finished_count--; - x->done2 = (x->finished_count == 0); - x->mu2.Unlock(); -} - -// Test for regression of a bug in loop of DequeueAllWakeable() -TEST(Mutex, MutexReaderWakeupBug) { - auto tp = CreateDefaultPool(); - - DequeueAllWakeableBugStruct x; - x.unfinished_count = 2; - x.done1 = false; - x.finished_count = 2; - x.done2 = false; - x.mu.Lock(); // acquire mu exclusively - // queue two thread that will block on reader locks on x.mu - tp->Schedule(std::bind(&AcquireAsReader, &x)); - tp->Schedule(std::bind(&AcquireAsReader, &x)); - absl::SleepFor(absl::Seconds(1)); // give time for reader threads to block - x.mu.Unlock(); // wake them up - - // both readers should finish promptly - EXPECT_TRUE( - x.mu2.LockWhenWithTimeout(absl::Condition(&x.done1), absl::Seconds(10))); - x.mu2.Unlock(); - - EXPECT_TRUE( - x.mu2.LockWhenWithTimeout(absl::Condition(&x.done2), absl::Seconds(10))); - x.mu2.Unlock(); -} - -struct LockWhenTestStruct { - absl::Mutex mu1; - bool cond = false; - - absl::Mutex mu2; - bool waiting = false; -}; - -static bool LockWhenTestIsCond(LockWhenTestStruct* s) { - s->mu2.Lock(); - s->waiting = true; - s->mu2.Unlock(); - return s->cond; -} - -static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) { - s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s)); - s->mu1.Unlock(); -} - -TEST(Mutex, LockWhen) { - LockWhenTestStruct s; - - std::thread t(LockWhenTestWaitForIsCond, &s); - s.mu2.LockWhen(absl::Condition(&s.waiting)); - s.mu2.Unlock(); - - s.mu1.Lock(); - s.cond = true; - s.mu1.Unlock(); - - 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. -#if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE) - -// Test for fix of bug in UnlockSlow() that incorrectly decremented the reader -// count when putting a thread to sleep waiting for a false condition when the -// lock was not held. - -// For this bug to strike, we make a thread wait on a free mutex with no -// waiters by causing its wakeup condition to be false. Then the -// next two acquirers must be readers. The bug causes the lock -// to be released when one reader unlocks, rather than both. - -struct ReaderDecrementBugStruct { - bool cond; // to delay first thread (under mu) - int done; // reference count (under mu) - absl::Mutex mu; - - bool waiting_on_cond; // under mu2 - bool have_reader_lock; // under mu2 - bool complete; // under mu2 - absl::Mutex mu2; // > mu -}; - -// L >= mu, L < mu_waiting_on_cond -static bool IsCond(void *v) { - ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v); - x->mu2.Lock(); - x->waiting_on_cond = true; - x->mu2.Unlock(); - return x->cond; -} - -// L >= mu -static bool AllDone(void *v) { - ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v); - return x->done == 0; -} - -// L={} -static void WaitForCond(ReaderDecrementBugStruct *x) { - absl::Mutex dummy; - absl::MutexLock l(&dummy); - x->mu.LockWhen(absl::Condition(&IsCond, x)); - x->done--; - x->mu.Unlock(); -} - -// L={} -static void GetReadLock(ReaderDecrementBugStruct *x) { - x->mu.ReaderLock(); - x->mu2.Lock(); - x->have_reader_lock = true; - x->mu2.Await(absl::Condition(&x->complete)); - x->mu2.Unlock(); - x->mu.ReaderUnlock(); - x->mu.Lock(); - x->done--; - x->mu.Unlock(); -} - -// Test for reader counter being decremented incorrectly by waiter -// with false condition. -TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { - ReaderDecrementBugStruct x; - x.cond = false; - x.waiting_on_cond = false; - x.have_reader_lock = false; - x.complete = false; - x.done = 2; // initial ref count - - // Run WaitForCond() and wait for it to sleep - std::thread thread1(WaitForCond, &x); - x.mu2.LockWhen(absl::Condition(&x.waiting_on_cond)); - x.mu2.Unlock(); - - // Run GetReadLock(), and wait for it to get the read lock - std::thread thread2(GetReadLock, &x); - x.mu2.LockWhen(absl::Condition(&x.have_reader_lock)); - x.mu2.Unlock(); - - // Get the reader lock ourselves, and release it. - x.mu.ReaderLock(); - x.mu.ReaderUnlock(); - - // The lock should be held in read mode by GetReadLock(). - // If we have the bug, the lock will be free. - x.mu.AssertReaderHeld(); - - // Wake up all the threads. - x.mu2.Lock(); - x.complete = true; - x.mu2.Unlock(); - - // TODO(delesley): turn on analysis once lock upgrading is supported. - // (This call upgrades the lock from shared to exclusive.) - x.mu.Lock(); - x.cond = true; - x.mu.Await(absl::Condition(&AllDone, &x)); - x.mu.Unlock(); - - thread1.join(); - thread2.join(); -} -#endif // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE - -// Test that we correctly handle the situation when a lock is -// held and then destroyed (w/o unlocking). -#ifdef ABSL_HAVE_THREAD_SANITIZER -// TSAN reports errors when locked Mutexes are destroyed. -TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS { -#else -TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { -#endif - for (int i = 0; i != 10; i++) { - // Create, lock and destroy 10 locks. - const int kNumLocks = 10; - auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks); - for (int j = 0; j != kNumLocks; j++) { - if ((j % 2) == 0) { - mu[j].WriterLock(); - } else { - mu[j].ReaderLock(); - } - } - } -} - -// -------------------------------------------------------- -// 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 { - return true; - } -}; - -struct DerivedTrue : True {}; - -TEST(Mutex, FunctorCondition) { - { // Variadic - True f; - EXPECT_TRUE(absl::Condition(&f).Eval()); - } - - { // Inherited - DerivedTrue g; - EXPECT_TRUE(absl::Condition(&g).Eval()); - } - - { // lambda - int value = 3; - auto is_zero = [&value] { return value == 0; }; - absl::Condition c(&is_zero); - EXPECT_FALSE(c.Eval()); - value = 0; - EXPECT_TRUE(c.Eval()); - } - - { // bind - int value = 0; - auto is_positive = std::bind(std::less<int>(), 0, std::cref(value)); - absl::Condition c(&is_positive); - EXPECT_FALSE(c.Eval()); - value = 1; - EXPECT_TRUE(c.Eval()); - } - - { // std::function - int value = 3; - std::function<bool()> is_zero = [&value] { return value == 0; }; - absl::Condition c(&is_zero); - EXPECT_FALSE(c.Eval()); - value = 0; - EXPECT_TRUE(c.Eval()); - } -} - -static bool IntIsZero(int *x) { return *x == 0; } - -// Test for reader waiting condition variable when there are other readers -// but no waiters. -TEST(Mutex, TestReaderOnCondVar) { - auto tp = CreateDefaultPool(); - absl::Mutex mu; - absl::CondVar cv; - int running = 3; - tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running)); - tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running)); - absl::SleepFor(absl::Seconds(2)); - mu.Lock(); - running--; - mu.Await(absl::Condition(&IntIsZero, &running)); - mu.Unlock(); -} - -// -------------------------------------------------------- -struct AcquireFromConditionStruct { - absl::Mutex mu0; // protects value, done - int value; // times condition function is called; under mu0, - bool done; // done with test? under mu0 - absl::Mutex mu1; // used to attempt to mess up state of mu0 - absl::CondVar cv; // so the condition function can be invoked from - // CondVar::Wait(). -}; - -static bool ConditionWithAcquire(AcquireFromConditionStruct *x) { - x->value++; // count times this function is called - - if (x->value == 2 || x->value == 3) { - // On the second and third invocation of this function, sleep for 100ms, - // but with the side-effect of altering the state of a Mutex other than - // than one for which this is a condition. The spec now explicitly allows - // this side effect; previously it did not. it was illegal. - bool always_false = false; - x->mu1.LockWhenWithTimeout(absl::Condition(&always_false), - absl::Milliseconds(100)); - x->mu1.Unlock(); - } - ABSL_RAW_CHECK(x->value < 4, "should not be invoked a fourth time"); - - // We arrange for the condition to return true on only the 2nd and 3rd calls. - return x->value == 2 || x->value == 3; -} - -static void WaitForCond2(AcquireFromConditionStruct *x) { - // wait for cond0 to become true - x->mu0.LockWhen(absl::Condition(&ConditionWithAcquire, x)); - x->done = true; - x->mu0.Unlock(); -} - -// Test for Condition whose function acquires other Mutexes -TEST(Mutex, AcquireFromCondition) { - auto tp = CreateDefaultPool(); - - AcquireFromConditionStruct x; - x.value = 0; - x.done = false; - tp->Schedule( - std::bind(&WaitForCond2, &x)); // run WaitForCond2() in a thread T - // T will hang because the first invocation of ConditionWithAcquire() will - // return false. - absl::SleepFor(absl::Milliseconds(500)); // allow T time to hang - - x.mu0.Lock(); - x.cv.WaitWithTimeout(&x.mu0, absl::Milliseconds(500)); // wake T - // T will be woken because the Wait() will call ConditionWithAcquire() - // for the second time, and it will return true. - - x.mu0.Unlock(); - - // T will then acquire the lock and recheck its own condition. - // It will find the condition true, as this is the third invocation, - // but the use of another Mutex by the calling function will - // cause the old mutex implementation to think that the outer - // LockWhen() has timed out because the inner LockWhenWithTimeout() did. - // T will then check the condition a fourth time because it finds a - // timeout occurred. This should not happen in the new - // implementation that allows the Condition function to use Mutexes. - - // It should also succeed, even though the Condition function - // is being invoked from CondVar::Wait, and thus this thread - // is conceptually waiting both on the condition variable, and on mu2. - - x.mu0.LockWhen(absl::Condition(&x.done)); - x.mu0.Unlock(); -} - -TEST(Mutex, DeadlockDetector) { - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort); - - // check that we can call ForgetDeadlockInfo() on a lock with the lock held - absl::Mutex m1; - absl::Mutex m2; - absl::Mutex m3; - absl::Mutex m4; - - m1.Lock(); // m1 gets ID1 - m2.Lock(); // m2 gets ID2 - m3.Lock(); // m3 gets ID3 - m3.Unlock(); - m2.Unlock(); - // m1 still held - m1.ForgetDeadlockInfo(); // m1 loses ID - m2.Lock(); // m2 gets ID2 - m3.Lock(); // m3 gets ID3 - m4.Lock(); // m4 gets ID4 - m3.Unlock(); - m2.Unlock(); - m4.Unlock(); - m1.Unlock(); -} - -// Bazel has a test "warning" file that programs can write to if the -// test should pass with a warning. This class disables the warning -// file until it goes out of scope. -class ScopedDisableBazelTestWarnings { - public: - ScopedDisableBazelTestWarnings() { -#ifdef _WIN32 - char file[MAX_PATH]; - if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) { - warnings_output_file_ = file; - SetEnvironmentVariableA(kVarName, nullptr); - } -#else - const char *file = getenv(kVarName); - if (file != nullptr) { - warnings_output_file_ = file; - unsetenv(kVarName); - } -#endif - } - - ~ScopedDisableBazelTestWarnings() { - if (!warnings_output_file_.empty()) { -#ifdef _WIN32 - SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str()); -#else - setenv(kVarName, warnings_output_file_.c_str(), 0); -#endif - } - } - - private: - static const char kVarName[]; - std::string warnings_output_file_; -}; -const char ScopedDisableBazelTestWarnings::kVarName[] = - "TEST_WARNINGS_OUTPUT_FILE"; - -#ifdef ABSL_HAVE_THREAD_SANITIZER -// This test intentionally creates deadlocks to test the deadlock detector. -TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) { -#else -TEST(Mutex, DeadlockDetectorBazelWarning) { -#endif - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport); - - // Cause deadlock detection to detect something, if it's - // compiled in and enabled. But turn off the bazel warning. - ScopedDisableBazelTestWarnings disable_bazel_test_warnings; - - absl::Mutex mu0; - absl::Mutex mu1; - bool got_mu0 = mu0.TryLock(); - mu1.Lock(); // acquire mu1 while holding mu0 - if (got_mu0) { - mu0.Unlock(); - } - if (mu0.TryLock()) { // try lock shouldn't cause deadlock detector to fire - mu0.Unlock(); - } - mu0.Lock(); // acquire mu0 while holding mu1; should get one deadlock - // report here - mu0.Unlock(); - mu1.Unlock(); - - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort); -} - -// This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the -// 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 { - // 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. - const int n_locks = 1 << 17; - auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks); - for (int i = 0; i < n_locks; i++) { - int end = std::min(n_locks, i + 5); - // acquire and then release locks i, i+1, ..., i+4 - for (int j = i; j < end; j++) { - array_of_locks[j].Lock(); - } - for (int j = i; j < end; j++) { - array_of_locks[j].Unlock(); - } - } -} - -#ifdef ABSL_HAVE_THREAD_SANITIZER -// TSAN reports errors when locked Mutexes are destroyed. -TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS { -#else -TEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { -#endif - // Test a scenario where a cached deadlock graph node id in the - // list of held locks is not invalidated when the corresponding - // mutex is deleted. - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort); - // Mutex that will be destroyed while being held - absl::Mutex *a = new absl::Mutex; - // Other mutexes needed by test - absl::Mutex b, c; - - // Hold mutex. - a->Lock(); - - // Force deadlock id assignment by acquiring another lock. - b.Lock(); - b.Unlock(); - - // Delete the mutex. The Mutex destructor tries to remove held locks, - // but the attempt isn't foolproof. It can fail if: - // (a) Deadlock detection is currently disabled. - // (b) The destruction is from another thread. - // We exploit (a) by temporarily disabling deadlock detection. - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore); - delete a; - absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort); - - // Now acquire another lock which will force a deadlock id assignment. - // We should end up getting assigned the same deadlock id that was - // freed up when "a" was deleted, which will cause a spurious deadlock - // report if the held lock entry for "a" was not invalidated. - c.Lock(); - c.Unlock(); -} - -// -------------------------------------------------------- -// Test for timeouts/deadlines on condition waits that are specified using -// absl::Duration and absl::Time. For each waiting function we test with -// a timeout/deadline that has already expired/passed, one that is infinite -// and so never expires/passes, and one that will expire/pass in the near -// future. - -static absl::Duration TimeoutTestAllowedSchedulingDelay() { - // Note: we use a function here because Microsoft Visual Studio fails to - // properly initialize constexpr static absl::Duration variables. - return absl::Milliseconds(150); -} - -// Returns true if `actual_delay` is close enough to `expected_delay` to pass -// the timeouts/deadlines test. Otherwise, logs warnings and returns false. -ABSL_MUST_USE_RESULT -static bool DelayIsWithinBounds(absl::Duration expected_delay, - absl::Duration actual_delay) { - bool pass = true; - // Do not allow the observed delay to be less than expected. This may occur - // in practice due to clock skew or when the synchronization primitives use a - // different clock than absl::Now(), but these cases should be handled by the - // the retry mechanism in each TimeoutTest. - if (actual_delay < expected_delay) { - ABSL_RAW_LOG(WARNING, - "Actual delay %s was too short, expected %s (difference %s)", - absl::FormatDuration(actual_delay).c_str(), - absl::FormatDuration(expected_delay).c_str(), - absl::FormatDuration(actual_delay - expected_delay).c_str()); - pass = false; - } - // If the expected delay is <= zero then allow a small error tolerance, since - // we do not expect context switches to occur during test execution. - // Otherwise, thread scheduling delays may be substantial in rare cases, so - // tolerate up to kTimeoutTestAllowedSchedulingDelay of error. - absl::Duration tolerance = expected_delay <= absl::ZeroDuration() - ? absl::Milliseconds(10) - : TimeoutTestAllowedSchedulingDelay(); - if (actual_delay > expected_delay + tolerance) { - ABSL_RAW_LOG(WARNING, - "Actual delay %s was too long, expected %s (difference %s)", - absl::FormatDuration(actual_delay).c_str(), - absl::FormatDuration(expected_delay).c_str(), - absl::FormatDuration(actual_delay - expected_delay).c_str()); - pass = false; - } - return pass; -} - -// Parameters for TimeoutTest, below. -struct TimeoutTestParam { - // The file and line number (used for logging purposes only). - const char *from_file; - int from_line; - - // Should the absolute deadline API based on absl::Time be tested? If false, - // the relative deadline API based on absl::Duration is tested. - bool use_absolute_deadline; - - // The deadline/timeout used when calling the API being tested - // (e.g. Mutex::LockWhenWithDeadline). - absl::Duration wait_timeout; - - // The delay before the condition will be set true by the test code. If zero - // or negative, the condition is set true immediately (before calling the API - // being tested). Otherwise, if infinite, the condition is never set true. - // Otherwise a closure is scheduled for the future that sets the condition - // true. - absl::Duration satisfy_condition_delay; - - // The expected result of the condition after the call to the API being - // tested. Generally `true` means the condition was true when the API returns, - // `false` indicates an expected timeout. - bool expected_result; - - // The expected delay before the API under test returns. This is inherently - // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the - // test keeps trying indefinitely until this constraint passes. - absl::Duration expected_delay; -}; - -// Print a `TimeoutTestParam` to a debug log. -std::ostream &operator<<(std::ostream &os, const TimeoutTestParam ¶m) { - return os << "from: " << param.from_file << ":" << param.from_line - << " use_absolute_deadline: " - << (param.use_absolute_deadline ? "true" : "false") - << " wait_timeout: " << param.wait_timeout - << " satisfy_condition_delay: " << param.satisfy_condition_delay - << " expected_result: " - << (param.expected_result ? "true" : "false") - << " expected_delay: " << param.expected_delay; -} - -std::string FormatString(const TimeoutTestParam ¶m) { - std::ostringstream os; - os << param; - return os.str(); -} - -// Like `thread::Executor::ScheduleAt` except: -// a) Delays zero or negative are executed immediately in the current thread. -// b) Infinite delays are never scheduled. -// c) Calls this test's `ScheduleAt` helper instead of using `pool` directly. -static void RunAfterDelay(absl::Duration delay, - absl::synchronization_internal::ThreadPool *pool, - const std::function<void()> &callback) { - if (delay <= absl::ZeroDuration()) { - callback(); // immediate - } else if (delay != absl::InfiniteDuration()) { - ScheduleAfter(pool, delay, callback); - } -} - -class TimeoutTest : public ::testing::Test, - public ::testing::WithParamInterface<TimeoutTestParam> {}; - -std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() { - // The `finite` delay is a finite, relatively short, delay. We make it larger - // than our allowed scheduling delay (slop factor) to avoid confusion when - // diagnosing test failures. The other constants here have clear meanings. - const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay(); - const absl::Duration never = absl::InfiniteDuration(); - const absl::Duration negative = -absl::InfiniteDuration(); - const absl::Duration immediate = absl::ZeroDuration(); - - // Every test case is run twice; once using the absolute deadline API and once - // using the relative timeout API. - std::vector<TimeoutTestParam> values; - for (bool use_absolute_deadline : {false, true}) { - // Tests with a negative timeout (deadline in the past), which should - // immediately return current state of the condition. - - // The condition is already true: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - negative, // wait_timeout - immediate, // satisfy_condition_delay - true, // expected_result - immediate, // expected_delay - }); - - // The condition becomes true, but the timeout has already expired: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - negative, // wait_timeout - finite, // satisfy_condition_delay - false, // expected_result - immediate // expected_delay - }); - - // The condition never becomes true: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - negative, // wait_timeout - never, // satisfy_condition_delay - false, // expected_result - immediate // expected_delay - }); - - // Tests with an infinite timeout (deadline in the infinite future), which - // should only return when the condition becomes true. - - // The condition is already true: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - never, // wait_timeout - immediate, // satisfy_condition_delay - true, // expected_result - immediate // expected_delay - }); - - // The condition becomes true before the (infinite) expiry: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - never, // wait_timeout - finite, // satisfy_condition_delay - true, // expected_result - finite, // expected_delay - }); - - // Tests with a (small) finite timeout (deadline soon), with the condition - // becoming true both before and after its expiry. - - // The condition is already true: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - never, // wait_timeout - immediate, // satisfy_condition_delay - true, // expected_result - immediate // expected_delay - }); - - // The condition becomes true before the expiry: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - finite * 2, // wait_timeout - finite, // satisfy_condition_delay - true, // expected_result - finite // expected_delay - }); - - // The condition becomes true, but the timeout has already expired: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - finite, // wait_timeout - finite * 2, // satisfy_condition_delay - false, // expected_result - finite // expected_delay - }); - - // The condition never becomes true: - values.push_back(TimeoutTestParam{ - __FILE__, __LINE__, use_absolute_deadline, - finite, // wait_timeout - never, // satisfy_condition_delay - false, // expected_result - finite // expected_delay - }); - } - return values; -} - -// Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`. -INSTANTIATE_TEST_SUITE_P(All, TimeoutTest, - testing::ValuesIn(MakeTimeoutTestParamValues())); - -TEST_P(TimeoutTest, Await) { - const TimeoutTestParam params = GetParam(); - ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - - // Because this test asserts bounds on scheduling delays it is flaky. To - // compensate it loops forever until it passes. Failures express as test - // timeouts, in which case the test log can be used to diagnose the issue. - for (int attempt = 1;; ++attempt) { - ABSL_RAW_LOG(INFO, "Attempt %d", attempt); - - absl::Mutex mu; - bool value = false; // condition value (under mu) - - std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = - CreateDefaultPool(); - RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { - absl::MutexLock l(&mu); - value = true; - }); - - absl::MutexLock lock(&mu); - absl::Time start_time = absl::Now(); - absl::Condition cond(&value); - bool result = - params.use_absolute_deadline - ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout) - : mu.AwaitWithTimeout(cond, params.wait_timeout); - if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { - EXPECT_EQ(params.expected_result, result); - break; - } - } -} - -TEST_P(TimeoutTest, LockWhen) { - const TimeoutTestParam params = GetParam(); - ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - - // Because this test asserts bounds on scheduling delays it is flaky. To - // compensate it loops forever until it passes. Failures express as test - // timeouts, in which case the test log can be used to diagnose the issue. - for (int attempt = 1;; ++attempt) { - ABSL_RAW_LOG(INFO, "Attempt %d", attempt); - - absl::Mutex mu; - bool value = false; // condition value (under mu) - - std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = - CreateDefaultPool(); - RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { - absl::MutexLock l(&mu); - value = true; - }); - - absl::Time start_time = absl::Now(); - absl::Condition cond(&value); - bool result = - params.use_absolute_deadline - ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout) - : mu.LockWhenWithTimeout(cond, params.wait_timeout); - mu.Unlock(); - - if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { - EXPECT_EQ(params.expected_result, result); - break; - } - } -} - -TEST_P(TimeoutTest, ReaderLockWhen) { - const TimeoutTestParam params = GetParam(); - ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - - // Because this test asserts bounds on scheduling delays it is flaky. To - // compensate it loops forever until it passes. Failures express as test - // timeouts, in which case the test log can be used to diagnose the issue. - for (int attempt = 0;; ++attempt) { - ABSL_RAW_LOG(INFO, "Attempt %d", attempt); - - absl::Mutex mu; - bool value = false; // condition value (under mu) - - std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = - CreateDefaultPool(); - RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { - absl::MutexLock l(&mu); - value = true; - }); - - absl::Time start_time = absl::Now(); - bool result = - params.use_absolute_deadline - ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value), - start_time + params.wait_timeout) - : mu.ReaderLockWhenWithTimeout(absl::Condition(&value), - params.wait_timeout); - mu.ReaderUnlock(); - - if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { - EXPECT_EQ(params.expected_result, result); - break; - } - } -} - -TEST_P(TimeoutTest, Wait) { - const TimeoutTestParam params = GetParam(); - ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - - // Because this test asserts bounds on scheduling delays it is flaky. To - // compensate it loops forever until it passes. Failures express as test - // timeouts, in which case the test log can be used to diagnose the issue. - for (int attempt = 0;; ++attempt) { - ABSL_RAW_LOG(INFO, "Attempt %d", attempt); - - absl::Mutex mu; - bool value = false; // condition value (under mu) - absl::CondVar cv; // signals a change of `value` - - std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = - CreateDefaultPool(); - RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { - absl::MutexLock l(&mu); - value = true; - cv.Signal(); - }); - - absl::MutexLock lock(&mu); - absl::Time start_time = absl::Now(); - absl::Duration timeout = params.wait_timeout; - absl::Time deadline = start_time + timeout; - while (!value) { - if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline) - : cv.WaitWithTimeout(&mu, timeout)) { - break; // deadline/timeout exceeded - } - timeout = deadline - absl::Now(); // recompute - } - bool result = value; // note: `mu` is still held - - if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { - EXPECT_EQ(params.expected_result, result); - break; - } - } -} - -TEST(Mutex, Logging) { - // Allow user to look at logging output - absl::Mutex logged_mutex; - logged_mutex.EnableDebugLog("fido_mutex"); - absl::CondVar logged_cv; - logged_cv.EnableDebugLog("rover_cv"); - logged_mutex.Lock(); - logged_cv.WaitWithTimeout(&logged_mutex, absl::Milliseconds(20)); - logged_mutex.Unlock(); - logged_mutex.ReaderLock(); - logged_mutex.ReaderUnlock(); - logged_mutex.Lock(); - logged_mutex.Unlock(); - logged_cv.Signal(); - logged_cv.SignalAll(); -} - -// -------------------------------------------------------- - -// Generate the vector of thread counts for tests parameterized on thread count. -static std::vector<int> AllThreadCountValues() { - if (kExtendedTest) { - return {2, 4, 8, 10, 16, 20, 24, 30, 32}; - } - return {2, 4, 10}; -} - -// A test fixture parameterized by thread count. -class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {}; - -// Instantiate the above with AllThreadCountOptions(). -INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest, - ::testing::ValuesIn(AllThreadCountValues()), - ::testing::PrintToStringParamName()); - -// Reduces iterations by some factor for slow platforms -// (determined empirically). -static int ScaleIterations(int x) { - // ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE is set in the implementation - // of Mutex that uses either std::mutex or pthread_mutex_t. Use - // these as keys to determine the slow implementation. -#if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE) - return x / 10; -#else - return x; -#endif -} - -TEST_P(MutexVariableThreadCountTest, Mutex) { - int threads = GetParam(); - int iterations = ScaleIterations(10000000) / threads; - int operations = threads * iterations; - EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations); -#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED) - iterations = std::min(iterations, 10); - operations = threads * iterations; - EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations, - operations, CheckSumG0G1), - operations); -#endif -} - -TEST_P(MutexVariableThreadCountTest, Try) { - int threads = GetParam(); - int iterations = 1000000 / threads; - int operations = iterations * threads; - EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations); -#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED) - iterations = std::min(iterations, 10); - operations = threads * iterations; - EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations, - operations, CheckSumG0G1), - operations); -#endif -} - -TEST_P(MutexVariableThreadCountTest, R20ms) { - int threads = GetParam(); - int iterations = 100; - int operations = iterations * threads; - EXPECT_EQ(RunTest(&TestR20ms, threads, iterations, operations), 0); -} - -TEST_P(MutexVariableThreadCountTest, RW) { - int threads = GetParam(); - int iterations = ScaleIterations(20000000) / threads; - int operations = iterations * threads; - EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2); -#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED) - iterations = std::min(iterations, 10); - operations = threads * iterations; - EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations, - operations, CheckSumG0G1), - operations / 2); -#endif -} - -TEST_P(MutexVariableThreadCountTest, Await) { - int threads = GetParam(); - int iterations = ScaleIterations(500000); - int operations = iterations; - EXPECT_EQ(RunTest(&TestAwait, threads, iterations, operations), operations); -} - -TEST_P(MutexVariableThreadCountTest, SignalAll) { - int threads = GetParam(); - int iterations = 200000 / threads; - int operations = iterations; - EXPECT_EQ(RunTest(&TestSignalAll, threads, iterations, operations), - operations); -} - -TEST(Mutex, Signal) { - int threads = 2; // TestSignal must use two threads - int iterations = 200000; - int operations = iterations; - EXPECT_EQ(RunTest(&TestSignal, threads, iterations, operations), operations); -} - -TEST(Mutex, Timed) { - int threads = 10; // Use a fixed thread count of 10 - int iterations = 1000; - int operations = iterations; - EXPECT_EQ(RunTest(&TestCVTimeout, threads, iterations, operations), - operations); -} - -TEST(Mutex, CVTime) { - int threads = 10; // Use a fixed thread count of 10 - int iterations = 1; - EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1), - threads * iterations); -} - -TEST(Mutex, MuTime) { - int threads = 10; // Use a fixed thread count of 10 - int iterations = 1; - EXPECT_EQ(RunTest(&TestMuTime, threads, iterations, 1), threads * iterations); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/synchronization/notification.cc b/third_party/abseil_cpp/absl/synchronization/notification.cc deleted file mode 100644 index e91b90382271..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/notification.cc +++ /dev/null @@ -1,78 +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/synchronization/notification.h" - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -void Notification::Notify() { - MutexLock l(&this->mutex_); - -#ifndef NDEBUG - if (ABSL_PREDICT_FALSE(notified_yet_.load(std::memory_order_relaxed))) { - ABSL_RAW_LOG( - FATAL, - "Notify() method called more than once for Notification object %p", - static_cast<void *>(this)); - } -#endif - - notified_yet_.store(true, std::memory_order_release); -} - -Notification::~Notification() { - // Make sure that the thread running Notify() exits before the object is - // destructed. - MutexLock l(&this->mutex_); -} - -void Notification::WaitForNotification() const { - if (!HasBeenNotifiedInternal(&this->notified_yet_)) { - this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal, - &this->notified_yet_)); - this->mutex_.Unlock(); - } -} - -bool Notification::WaitForNotificationWithTimeout( - absl::Duration timeout) const { - bool notified = HasBeenNotifiedInternal(&this->notified_yet_); - if (!notified) { - notified = this->mutex_.LockWhenWithTimeout( - Condition(&HasBeenNotifiedInternal, &this->notified_yet_), timeout); - this->mutex_.Unlock(); - } - return notified; -} - -bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const { - bool notified = HasBeenNotifiedInternal(&this->notified_yet_); - if (!notified) { - notified = this->mutex_.LockWhenWithDeadline( - Condition(&HasBeenNotifiedInternal, &this->notified_yet_), deadline); - this->mutex_.Unlock(); - } - return notified; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/synchronization/notification.h b/third_party/abseil_cpp/absl/synchronization/notification.h deleted file mode 100644 index 9a354ca2c023..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/notification.h +++ /dev/null @@ -1,123 +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. -// -// ----------------------------------------------------------------------------- -// notification.h -// ----------------------------------------------------------------------------- -// -// This header file defines a `Notification` abstraction, which allows threads -// to receive notification of a single occurrence of a single event. -// -// The `Notification` object maintains a private boolean "notified" state that -// transitions to `true` at most once. The `Notification` class provides the -// following primary member functions: -// * `HasBeenNotified() `to query its state -// * `WaitForNotification*()` to have threads wait until the "notified" state -// is `true`. -// * `Notify()` to set the notification's "notified" state to `true` and -// notify all waiting threads that the event has occurred. -// This method may only be called once. -// -// Note that while `Notify()` may only be called once, it is perfectly valid to -// call any of the `WaitForNotification*()` methods multiple times, from -// multiple threads -- even after the notification's "notified" state has been -// set -- in which case those methods will immediately return. -// -// Note that the lifetime of a `Notification` requires careful consideration; -// it might not be safe to destroy a notification after calling `Notify()` since -// it is still legal for other threads to call `WaitForNotification*()` methods -// on the notification. However, observers responding to a "notified" state of -// `true` can safely delete the notification without interfering with the call -// to `Notify()` in the other thread. -// -// Memory ordering: For any threads X and Y, if X calls `Notify()`, then any -// action taken by X before it calls `Notify()` is visible to thread Y after: -// * Y returns from `WaitForNotification()`, or -// * Y receives a `true` return value from either `HasBeenNotified()` or -// `WaitForNotificationWithTimeout()`. - -#ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_ -#define ABSL_SYNCHRONIZATION_NOTIFICATION_H_ - -#include <atomic> - -#include "absl/base/macros.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// Notification -// ----------------------------------------------------------------------------- -class Notification { - public: - // Initializes the "notified" state to unnotified. - Notification() : notified_yet_(false) {} - explicit Notification(bool prenotify) : notified_yet_(prenotify) {} - Notification(const Notification&) = delete; - Notification& operator=(const Notification&) = delete; - ~Notification(); - - // Notification::HasBeenNotified() - // - // Returns the value of the notification's internal "notified" state. - bool HasBeenNotified() const { - return HasBeenNotifiedInternal(&this->notified_yet_); - } - - // Notification::WaitForNotification() - // - // Blocks the calling thread until the notification's "notified" state is - // `true`. Note that if `Notify()` has been previously called on this - // notification, this function will immediately return. - void WaitForNotification() const; - - // Notification::WaitForNotificationWithTimeout() - // - // Blocks until either the notification's "notified" state is `true` (which - // may occur immediately) or the timeout has elapsed, returning the value of - // its "notified" state in either case. - bool WaitForNotificationWithTimeout(absl::Duration timeout) const; - - // Notification::WaitForNotificationWithDeadline() - // - // Blocks until either the notification's "notified" state is `true` (which - // may occur immediately) or the deadline has expired, returning the value of - // its "notified" state in either case. - bool WaitForNotificationWithDeadline(absl::Time deadline) const; - - // Notification::Notify() - // - // Sets the "notified" state of this notification to `true` and wakes waiting - // threads. Note: do not call `Notify()` multiple times on the same - // `Notification`; calling `Notify()` more than once on the same notification - // results in undefined behavior. - void Notify(); - - private: - static inline bool HasBeenNotifiedInternal( - const std::atomic<bool>* notified_yet) { - return notified_yet->load(std::memory_order_acquire); - } - - mutable Mutex mutex_; - std::atomic<bool> notified_yet_; // written under mutex_ -}; - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_ diff --git a/third_party/abseil_cpp/absl/synchronization/notification_test.cc b/third_party/abseil_cpp/absl/synchronization/notification_test.cc deleted file mode 100644 index 100ea76f33ac..000000000000 --- a/third_party/abseil_cpp/absl/synchronization/notification_test.cc +++ /dev/null @@ -1,133 +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/synchronization/notification.h" - -#include <thread> // NOLINT(build/c++11) -#include <vector> - -#include "gtest/gtest.h" -#include "absl/synchronization/mutex.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// A thread-safe class that holds a counter. -class ThreadSafeCounter { - public: - ThreadSafeCounter() : count_(0) {} - - void Increment() { - MutexLock lock(&mutex_); - ++count_; - } - - int Get() const { - MutexLock lock(&mutex_); - return count_; - } - - void WaitUntilGreaterOrEqual(int n) { - MutexLock lock(&mutex_); - auto cond = [this, n]() { return count_ >= n; }; - mutex_.Await(Condition(&cond)); - } - - private: - mutable Mutex mutex_; - int count_; -}; - -// Runs the |i|'th worker thread for the tests in BasicTests(). Increments the -// |ready_counter|, waits on the |notification|, and then increments the -// |done_counter|. -static void RunWorker(int i, ThreadSafeCounter* ready_counter, - Notification* notification, - ThreadSafeCounter* done_counter) { - ready_counter->Increment(); - notification->WaitForNotification(); - done_counter->Increment(); -} - -// Tests that the |notification| properly blocks and awakens threads. Assumes -// that the |notification| is not yet triggered. If |notify_before_waiting| is -// true, the |notification| is triggered before any threads are created, so the -// threads never block in WaitForNotification(). Otherwise, the |notification| -// is triggered at a later point when most threads are likely to be blocking in -// WaitForNotification(). -static void BasicTests(bool notify_before_waiting, Notification* notification) { - EXPECT_FALSE(notification->HasBeenNotified()); - EXPECT_FALSE( - notification->WaitForNotificationWithTimeout(absl::Milliseconds(0))); - EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now())); - - const absl::Duration delay = absl::Milliseconds(50); - const absl::Time start = absl::Now(); - EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay)); - const absl::Duration elapsed = absl::Now() - start; - - // Allow for a slight early return, to account for quality of implementation - // issues on various platforms. - const absl::Duration slop = absl::Microseconds(200); - EXPECT_LE(delay - slop, elapsed) - << "WaitForNotificationWithTimeout returned " << delay - elapsed - << " early (with " << slop << " slop), start time was " << start; - - ThreadSafeCounter ready_counter; - ThreadSafeCounter done_counter; - - if (notify_before_waiting) { - notification->Notify(); - } - - // Create a bunch of threads that increment the |done_counter| after being - // notified. - const int kNumThreads = 10; - std::vector<std::thread> workers; - for (int i = 0; i < kNumThreads; ++i) { - workers.push_back(std::thread(&RunWorker, i, &ready_counter, notification, - &done_counter)); - } - - if (!notify_before_waiting) { - ready_counter.WaitUntilGreaterOrEqual(kNumThreads); - - // Workers have not been notified yet, so the |done_counter| should be - // unmodified. - EXPECT_EQ(0, done_counter.Get()); - - notification->Notify(); - } - - // After notifying and then joining the workers, both counters should be - // fully incremented. - notification->WaitForNotification(); // should exit immediately - EXPECT_TRUE(notification->HasBeenNotified()); - EXPECT_TRUE(notification->WaitForNotificationWithTimeout(absl::Seconds(0))); - EXPECT_TRUE(notification->WaitForNotificationWithDeadline(absl::Now())); - for (std::thread& worker : workers) { - worker.join(); - } - EXPECT_EQ(kNumThreads, ready_counter.Get()); - EXPECT_EQ(kNumThreads, done_counter.Get()); -} - -TEST(NotificationTest, SanityTest) { - Notification local_notification1, local_notification2; - BasicTests(false, &local_notification1); - BasicTests(true, &local_notification2); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/BUILD.bazel b/third_party/abseil_cpp/absl/time/BUILD.bazel deleted file mode 100644 index 991241a0df5b..000000000000 --- a/third_party/abseil_cpp/absl/time/BUILD.bazel +++ /dev/null @@ -1,125 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "time", - srcs = [ - "civil_time.cc", - "clock.cc", - "duration.cc", - "format.cc", - "internal/get_current_time_chrono.inc", - "internal/get_current_time_posix.inc", - "time.cc", - ], - hdrs = [ - "civil_time.h", - "clock.h", - "time.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/numeric:int128", - "//absl/strings", - "//absl/time/internal/cctz:civil_time", - "//absl/time/internal/cctz:time_zone", - ], -) - -cc_library( - name = "test_util", - testonly = 1, - srcs = [ - "internal/test_util.cc", - "internal/zoneinfo.inc", - ], - hdrs = ["internal/test_util.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - "//absl/time:__pkg__", - ], - deps = [ - ":time", - "//absl/base:config", - "//absl/base:raw_logging_internal", - "//absl/time/internal/cctz:time_zone", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "time_test", - srcs = [ - "civil_time_test.cc", - "clock_test.cc", - "duration_test.cc", - "format_test.cc", - "time_test.cc", - "time_zone_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":test_util", - ":time", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/numeric:int128", - "//absl/time/internal/cctz:time_zone", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "time_benchmark", - srcs = [ - "civil_time_benchmark.cc", - "clock_benchmark.cc", - "duration_benchmark.cc", - "format_benchmark.cc", - "time_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = [ - "benchmark", - ], - deps = [ - ":test_util", - ":time", - "//absl/base", - "//absl/base:core_headers", - "//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 deleted file mode 100644 index 00bdd499c1f3..000000000000 --- a/third_party/abseil_cpp/absl/time/CMakeLists.txt +++ /dev/null @@ -1,128 +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. -# - -absl_cc_library( - NAME - time - HDRS - "civil_time.h" - "clock.h" - "time.h" - SRCS - "civil_time.cc" - "clock.cc" - "duration.cc" - "format.cc" - "internal/get_current_time_chrono.inc" - "internal/get_current_time_posix.inc" - "time.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base - absl::civil_time - absl::core_headers - absl::int128 - absl::raw_logging_internal - absl::strings - absl::time_zone - PUBLIC -) - -absl_cc_library( - NAME - civil_time - HDRS - "internal/cctz/include/cctz/civil_time.h" - "internal/cctz/include/cctz/civil_time_detail.h" - SRCS - "internal/cctz/src/civil_time_detail.cc" - COPTS - ${ABSL_DEFAULT_COPTS} -) - -if(APPLE) - find_library(CoreFoundation CoreFoundation) -endif() - -absl_cc_library( - NAME - time_zone - HDRS - "internal/cctz/include/cctz/time_zone.h" - "internal/cctz/include/cctz/zone_info_source.h" - SRCS - "internal/cctz/src/time_zone_fixed.cc" - "internal/cctz/src/time_zone_fixed.h" - "internal/cctz/src/time_zone_format.cc" - "internal/cctz/src/time_zone_if.cc" - "internal/cctz/src/time_zone_if.h" - "internal/cctz/src/time_zone_impl.cc" - "internal/cctz/src/time_zone_impl.h" - "internal/cctz/src/time_zone_info.cc" - "internal/cctz/src/time_zone_info.h" - "internal/cctz/src/time_zone_libc.cc" - "internal/cctz/src/time_zone_libc.h" - "internal/cctz/src/time_zone_lookup.cc" - "internal/cctz/src/time_zone_posix.cc" - "internal/cctz/src/time_zone_posix.h" - "internal/cctz/src/tzfile.h" - "internal/cctz/src/zone_info_source.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - $<$<PLATFORM_ID:Darwin>:${CoreFoundation}> -) - -absl_cc_library( - NAME - time_internal_test_util - HDRS - "internal/test_util.h" - SRCS - "internal/test_util.cc" - "internal/zoneinfo.inc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::time - absl::config - absl::raw_logging_internal - absl::time_zone - gmock - TESTONLY -) - -absl_cc_test( - NAME - time_test - SRCS - "civil_time_test.cc" - "clock_test.cc" - "duration_test.cc" - "format_test.cc" - "time_test.cc" - "time_zone_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::time_internal_test_util - absl::time - absl::config - absl::core_headers - absl::time_zone - gmock_main -) diff --git a/third_party/abseil_cpp/absl/time/civil_time.cc b/third_party/abseil_cpp/absl/time/civil_time.cc deleted file mode 100644 index bdfe9ce0efb3..000000000000 --- a/third_party/abseil_cpp/absl/time/civil_time.cc +++ /dev/null @@ -1,175 +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/time/civil_time.h" - -#include <cstdlib> -#include <string> - -#include "absl/strings/str_cat.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -// Since a civil time has a larger year range than absl::Time (64-bit years vs -// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years -// around the year 2400, which will produce an equivalent year in a range that -// absl::Time can handle. -inline civil_year_t NormalizeYear(civil_year_t year) { - return 2400 + year % 400; -} - -// Formats the given CivilSecond according to the given format. -std::string FormatYearAnd(string_view fmt, CivilSecond cs) { - const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(), - cs.hour(), cs.minute(), cs.second()); - const TimeZone utc = UTCTimeZone(); - // TODO(absl-team): Avoid conversion of fmt string. - return StrCat(cs.year(), - FormatTime(std::string(fmt), FromCivil(ncs, utc), utc)); -} - -template <typename CivilT> -bool ParseYearAnd(string_view fmt, string_view s, CivilT* c) { - // Civil times support a larger year range than absl::Time, so we need to - // parse the year separately, normalize it, then use absl::ParseTime on the - // normalized string. - const std::string ss = std::string(s); // TODO(absl-team): Avoid conversion. - const char* const np = ss.c_str(); - char* endp; - errno = 0; - const civil_year_t y = - std::strtoll(np, &endp, 10); // NOLINT(runtime/deprecated_fn) - if (endp == np || errno == ERANGE) return false; - const std::string norm = StrCat(NormalizeYear(y), endp); - - const TimeZone utc = UTCTimeZone(); - Time t; - if (ParseTime(StrCat("%Y", fmt), norm, utc, &t, nullptr)) { - const auto cs = ToCivilSecond(t, utc); - *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second()); - return true; - } - - return false; -} - -// Tries to parse the type as a CivilT1, but then assigns the result to the -// argument of type CivilT2. -template <typename CivilT1, typename CivilT2> -bool ParseAs(string_view s, CivilT2* c) { - CivilT1 t1; - if (ParseCivilTime(s, &t1)) { - *c = CivilT2(t1); - return true; - } - return false; -} - -template <typename CivilT> -bool ParseLenient(string_view s, CivilT* c) { - // A fastpath for when the given string data parses exactly into the given - // type T (e.g., s="YYYY-MM-DD" and CivilT=CivilDay). - if (ParseCivilTime(s, c)) return true; - // Try parsing as each of the 6 types, trying the most common types first - // (based on csearch results). - if (ParseAs<CivilDay>(s, c)) return true; - if (ParseAs<CivilSecond>(s, c)) return true; - if (ParseAs<CivilHour>(s, c)) return true; - if (ParseAs<CivilMonth>(s, c)) return true; - if (ParseAs<CivilMinute>(s, c)) return true; - if (ParseAs<CivilYear>(s, c)) return true; - return false; -} -} // namespace - -std::string FormatCivilTime(CivilSecond c) { - return FormatYearAnd("-%m-%d%ET%H:%M:%S", c); -} -std::string FormatCivilTime(CivilMinute c) { - return FormatYearAnd("-%m-%d%ET%H:%M", c); -} -std::string FormatCivilTime(CivilHour c) { - return FormatYearAnd("-%m-%d%ET%H", c); -} -std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); } -std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); } -std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); } - -bool ParseCivilTime(string_view s, CivilSecond* c) { - return ParseYearAnd("-%m-%d%ET%H:%M:%S", s, c); -} -bool ParseCivilTime(string_view s, CivilMinute* c) { - return ParseYearAnd("-%m-%d%ET%H:%M", s, c); -} -bool ParseCivilTime(string_view s, CivilHour* c) { - return ParseYearAnd("-%m-%d%ET%H", s, c); -} -bool ParseCivilTime(string_view s, CivilDay* c) { - return ParseYearAnd("-%m-%d", s, c); -} -bool ParseCivilTime(string_view s, CivilMonth* c) { - return ParseYearAnd("-%m", s, c); -} -bool ParseCivilTime(string_view s, CivilYear* c) { - return ParseYearAnd("", s, c); -} - -bool ParseLenientCivilTime(string_view s, CivilSecond* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilMinute* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilHour* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilDay* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilMonth* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilYear* c) { - return ParseLenient(s, c); -} - -namespace time_internal { - -std::ostream& operator<<(std::ostream& os, CivilYear y) { - return os << FormatCivilTime(y); -} -std::ostream& operator<<(std::ostream& os, CivilMonth m) { - return os << FormatCivilTime(m); -} -std::ostream& operator<<(std::ostream& os, CivilDay d) { - return os << FormatCivilTime(d); -} -std::ostream& operator<<(std::ostream& os, CivilHour h) { - return os << FormatCivilTime(h); -} -std::ostream& operator<<(std::ostream& os, CivilMinute m) { - return os << FormatCivilTime(m); -} -std::ostream& operator<<(std::ostream& os, CivilSecond s) { - return os << FormatCivilTime(s); -} - -} // namespace time_internal - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/civil_time.h b/third_party/abseil_cpp/absl/time/civil_time.h deleted file mode 100644 index bb4600443445..000000000000 --- a/third_party/abseil_cpp/absl/time/civil_time.h +++ /dev/null @@ -1,538 +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: civil_time.h -// ----------------------------------------------------------------------------- -// -// This header file defines abstractions for computing with "civil time". -// The term "civil time" refers to the legally recognized human-scale time -// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date" -// is perhaps the most common example of a civil time (represented here as -// an `absl::CivilDay`). -// -// Modern-day civil time follows the Gregorian Calendar and is a -// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for -// example, is not tied to a time zone. Put another way, a civil time does not -// map to a unique point in time; a civil time must be mapped to an absolute -// time *through* a time zone. -// -// Because a civil time is what most people think of as "time," it is common to -// map absolute times to civil times to present to users. -// -// Time zones define the relationship between absolute and civil times. Given an -// absolute or civil time and a time zone, you can compute the other time: -// -// Civil Time = F(Absolute Time, Time Zone) -// Absolute Time = G(Civil Time, Time Zone) -// -// The Abseil time library allows you to construct such civil times from -// absolute times; consult time.h for such functionality. -// -// This library provides six classes for constructing civil-time objects, and -// provides several helper functions for rounding, iterating, and performing -// arithmetic on civil-time objects, while avoiding complications like -// daylight-saving time (DST): -// -// * `absl::CivilSecond` -// * `absl::CivilMinute` -// * `absl::CivilHour` -// * `absl::CivilDay` -// * `absl::CivilMonth` -// * `absl::CivilYear` -// -// Example: -// -// // Construct a civil-time object for a specific day -// const absl::CivilDay cd(1969, 07, 20); -// -// // Construct a civil-time object for a specific second -// const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1); -// -// Note: In C++14 and later, this library is usable in a constexpr context. -// -// Example: -// -// // Valid in C++14 -// constexpr absl::CivilDay cd(1969, 07, 20); - -#ifndef ABSL_TIME_CIVIL_TIME_H_ -#define ABSL_TIME_CIVIL_TIME_H_ - -#include <string> - -#include "absl/strings/string_view.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace time_internal { -struct second_tag : cctz::detail::second_tag {}; -struct minute_tag : second_tag, cctz::detail::minute_tag {}; -struct hour_tag : minute_tag, cctz::detail::hour_tag {}; -struct day_tag : hour_tag, cctz::detail::day_tag {}; -struct month_tag : day_tag, cctz::detail::month_tag {}; -struct year_tag : month_tag, cctz::detail::year_tag {}; -} // namespace time_internal - -// ----------------------------------------------------------------------------- -// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear -// ----------------------------------------------------------------------------- -// -// Each of these civil-time types is a simple value type with the same -// interface for construction and the same six accessors for each of the civil -// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These -// classes differ only in their alignment, which is indicated by the type name -// and specifies the field on which arithmetic operates. -// -// CONSTRUCTION -// -// Each of the civil-time types can be constructed in two ways: by directly -// passing to the constructor up to six integers representing the YMDHMS fields, -// or by copying the YMDHMS fields from a differently aligned civil-time type. -// Omitted fields are assigned their minimum valid value. Hours, minutes, and -// seconds will be set to 0, month and day will be set to 1. Since there is no -// minimum year, the default is 1970. -// -// Examples: -// -// absl::CivilDay default_value; // 1970-01-01 00:00:00 -// -// absl::CivilDay a(2015, 2, 3); // 2015-02-03 00:00:00 -// absl::CivilDay b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 -// absl::CivilDay c(2015); // 2015-01-01 00:00:00 -// -// absl::CivilSecond ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 -// absl::CivilMinute mm(ss); // 2015-02-03 04:05:00 -// absl::CivilHour hh(mm); // 2015-02-03 04:00:00 -// absl::CivilDay d(hh); // 2015-02-03 00:00:00 -// absl::CivilMonth m(d); // 2015-02-01 00:00:00 -// absl::CivilYear y(m); // 2015-01-01 00:00:00 -// -// m = absl::CivilMonth(y); // 2015-01-01 00:00:00 -// d = absl::CivilDay(m); // 2015-01-01 00:00:00 -// hh = absl::CivilHour(d); // 2015-01-01 00:00:00 -// mm = absl::CivilMinute(hh); // 2015-01-01 00:00:00 -// ss = absl::CivilSecond(mm); // 2015-01-01 00:00:00 -// -// Each civil-time class is aligned to the civil-time field indicated in the -// class's name after normalization. Alignment is performed by setting all the -// inferior fields to their minimum valid value (as described above). The -// following are examples of how each of the six types would align the fields -// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the -// string format used here is not important; it's just a shorthand way of -// showing the six YMDHMS fields.) -// -// absl::CivilSecond : 2015-11-22 12:34:56 -// absl::CivilMinute : 2015-11-22 12:34:00 -// absl::CivilHour : 2015-11-22 12:00:00 -// absl::CivilDay : 2015-11-22 00:00:00 -// absl::CivilMonth : 2015-11-01 00:00:00 -// absl::CivilYear : 2015-01-01 00:00:00 -// -// Each civil-time type performs arithmetic on the field to which it is -// aligned. This means that adding 1 to an absl::CivilDay increments the day -// field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth -// operates on the month field (normalizing as necessary). All arithmetic -// produces a valid civil time. Difference requires two similarly aligned -// civil-time objects and returns the scalar answer in units of the objects' -// alignment. For example, the difference between two absl::CivilHour objects -// will give an answer in units of civil hours. -// -// ALIGNMENT CONVERSION -// -// The alignment of a civil-time object cannot change, but the object may be -// used to construct a new object with a different alignment. This is referred -// to as "realigning". When realigning to a type with the same or more -// precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be -// performed implicitly since no information is lost. However, if information -// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must -// be explicit at the call site. -// -// Examples: -// -// void UseDay(absl::CivilDay day); -// -// absl::CivilSecond cs; -// UseDay(cs); // Won't compile because data may be discarded -// UseDay(absl::CivilDay(cs)); // OK: explicit conversion -// -// absl::CivilDay cd; -// UseDay(cd); // OK: no conversion needed -// -// absl::CivilMonth cm; -// UseDay(cm); // OK: implicit conversion to absl::CivilDay -// -// NORMALIZATION -// -// Normalization takes invalid values and adjusts them to produce valid values. -// Within the civil-time library, integer arguments passed to the Civil* -// constructors may be out-of-range, in which case they are normalized by -// carrying overflow into a field of courser granularity to produce valid -// civil-time objects. This normalization enables natural arithmetic on -// constructor arguments without worrying about the field's range. -// -// Examples: -// -// // Out-of-range; normalized to 2016-11-01 -// absl::CivilDay d(2016, 10, 32); -// // Out-of-range, negative: normalized to 2016-10-30T23 -// absl::CivilHour h1(2016, 10, 31, -1); -// // Normalization is cumulative: normalized to 2016-10-30T23 -// absl::CivilHour h2(2016, 10, 32, -25); -// -// Note: If normalization is undesired, you can signal an error by comparing -// the constructor arguments to the normalized values returned by the YMDHMS -// properties. -// -// COMPARISON -// -// Comparison between civil-time objects considers all six YMDHMS fields, -// regardless of the type's alignment. Comparison between differently aligned -// civil-time types is allowed. -// -// Examples: -// -// absl::CivilDay feb_3(2015, 2, 3); // 2015-02-03 00:00:00 -// absl::CivilDay mar_4(2015, 3, 4); // 2015-03-04 00:00:00 -// // feb_3 < mar_4 -// // absl::CivilYear(feb_3) == absl::CivilYear(mar_4) -// -// absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 -// // feb_3 < feb_3_noon -// // feb_3 == absl::CivilDay(feb_3_noon) -// -// // Iterates all the days of February 2015. -// for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) { -// // ... -// } -// -// ARITHMETIC -// -// Civil-time types support natural arithmetic operators such as addition, -// subtraction, and difference. Arithmetic operates on the civil-time field -// indicated in the type's name. Difference operators require arguments with -// the same alignment and return the answer in units of the alignment. -// -// Example: -// -// absl::CivilDay a(2015, 2, 3); -// ++a; // 2015-02-04 00:00:00 -// --a; // 2015-02-03 00:00:00 -// absl::CivilDay b = a + 1; // 2015-02-04 00:00:00 -// absl::CivilDay c = 1 + b; // 2015-02-05 00:00:00 -// int n = c - a; // n = 2 (civil days) -// int m = c - absl::CivilMonth(c); // Won't compile: different types. -// -// ACCESSORS -// -// Each civil-time type has accessors for all six of the civil-time fields: -// year, month, day, hour, minute, and second. -// -// civil_year_t year() -// int month() -// int day() -// int hour() -// int minute() -// int second() -// -// Recall that fields inferior to the type's alignment will be set to their -// minimum valid value. -// -// Example: -// -// absl::CivilDay d(2015, 6, 28); -// // d.year() == 2015 -// // d.month() == 6 -// // d.day() == 28 -// // d.hour() == 0 -// // d.minute() == 0 -// // d.second() == 0 -// -// CASE STUDY: Adding a month to January 31. -// -// One of the classic questions that arises when considering a civil time -// library (or a date library or a date/time library) is this: -// "What is the result of adding a month to January 31?" -// This is an interesting question because it is unclear what is meant by a -// "month", and several different answers are possible, depending on context: -// -// 1. March 3 (or 2 if a leap year), if "add a month" means to add a month to -// the current month, and adjust the date to overflow the extra days into -// March. In this case the result of "February 31" would be normalized as -// within the civil-time library. -// 2. February 28 (or 29 if a leap year), if "add a month" means to add a -// month, and adjust the date while holding the resulting month constant. -// In this case, the result of "February 31" would be truncated to the last -// day in February. -// 3. An error. The caller may get some error, an exception, an invalid date -// object, or perhaps return `false`. This may make sense because there is -// no single unambiguously correct answer to the question. -// -// Practically speaking, any answer that is not what the programmer intended -// is the wrong answer. -// -// The Abseil time library avoids this problem by making it impossible to -// ask ambiguous questions. All civil-time objects are aligned to a particular -// civil-field boundary (such as aligned to a year, month, day, hour, minute, -// or second), and arithmetic operates on the field to which the object is -// aligned. This means that in order to "add a month" the object must first be -// aligned to a month boundary, which is equivalent to the first day of that -// month. -// -// Of course, there are ways to compute an answer the question at hand using -// this Abseil time library, but they require the programmer to be explicit -// about the answer they expect. To illustrate, let's see how to compute all -// three of the above possible answers to the question of "Jan 31 plus 1 -// month": -// -// Example: -// -// const absl::CivilDay d(2015, 1, 31); -// -// // Answer 1: -// // Add 1 to the month field in the constructor, and rely on normalization. -// const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day()); -// // normalized == 2015-03-03 (aka Feb 31) -// -// // Answer 2: -// // Add 1 to month field, capping to the end of next month. -// const auto next_month = absl::CivilMonth(d) + 1; -// const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1; -// const auto capped = std::min(normalized, last_day_of_next_month); -// // capped == 2015-02-28 -// -// // Answer 3: -// // Signal an error if the normalized answer is not in next month. -// if (absl::CivilMonth(normalized) != next_month) { -// // error, month overflow -// } -// -using CivilSecond = - time_internal::cctz::detail::civil_time<time_internal::second_tag>; -using CivilMinute = - time_internal::cctz::detail::civil_time<time_internal::minute_tag>; -using CivilHour = - time_internal::cctz::detail::civil_time<time_internal::hour_tag>; -using CivilDay = - time_internal::cctz::detail::civil_time<time_internal::day_tag>; -using CivilMonth = - time_internal::cctz::detail::civil_time<time_internal::month_tag>; -using CivilYear = - time_internal::cctz::detail::civil_time<time_internal::year_tag>; - -// civil_year_t -// -// Type alias of a civil-time year value. This type is guaranteed to (at least) -// support any year value supported by `time_t`. -// -// Example: -// -// absl::CivilSecond cs = ...; -// absl::civil_year_t y = cs.year(); -// cs = absl::CivilSecond(y, 1, 1, 0, 0, 0); // CivilSecond(CivilYear(cs)) -// -using civil_year_t = time_internal::cctz::year_t; - -// civil_diff_t -// -// Type alias of the difference between two civil-time values. -// This type is used to indicate arguments that are not -// normalized (such as parameters to the civil-time constructors), the results -// of civil-time subtraction, or the operand to civil-time addition. -// -// Example: -// -// absl::civil_diff_t n_sec = cs1 - cs2; // cs1 == cs2 + n_sec; -// -using civil_diff_t = time_internal::cctz::diff_t; - -// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday, -// Weekday::friday, Weekday::saturday, Weekday::sunday -// -// The Weekday enum class represents the civil-time concept of a "weekday" with -// members for all days of the week. -// -// absl::Weekday wd = absl::Weekday::thursday; -// -using Weekday = time_internal::cctz::weekday; - -// GetWeekday() -// -// Returns the absl::Weekday for the given (realigned) civil-time value. -// -// Example: -// -// absl::CivilDay a(2015, 8, 13); -// absl::Weekday wd = absl::GetWeekday(a); // wd == absl::Weekday::thursday -// -inline Weekday GetWeekday(CivilSecond cs) { - return time_internal::cctz::get_weekday(cs); -} - -// NextWeekday() -// PrevWeekday() -// -// Returns the absl::CivilDay that strictly follows or precedes a given -// absl::CivilDay, and that falls on the given absl::Weekday. -// -// Example, given the following month: -// -// August 2015 -// Su Mo Tu We Th Fr Sa -// 1 -// 2 3 4 5 6 7 8 -// 9 10 11 12 13 14 15 -// 16 17 18 19 20 21 22 -// 23 24 25 26 27 28 29 -// 30 31 -// -// absl::CivilDay a(2015, 8, 13); -// // absl::GetWeekday(a) == absl::Weekday::thursday -// absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday); -// // b = 2015-08-20 -// absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday); -// // c = 2015-08-06 -// -// absl::CivilDay d = ... -// // Gets the following Thursday if d is not already Thursday -// absl::CivilDay thurs1 = absl::NextWeekday(d - 1, absl::Weekday::thursday); -// // Gets the previous Thursday if d is not already Thursday -// absl::CivilDay thurs2 = absl::PrevWeekday(d + 1, absl::Weekday::thursday); -// -inline CivilDay NextWeekday(CivilDay cd, Weekday wd) { - return CivilDay(time_internal::cctz::next_weekday(cd, wd)); -} -inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { - return CivilDay(time_internal::cctz::prev_weekday(cd, wd)); -} - -// GetYearDay() -// -// Returns the day-of-year for the given (realigned) civil-time value. -// -// Example: -// -// absl::CivilDay a(2015, 1, 1); -// int yd_jan_1 = absl::GetYearDay(a); // yd_jan_1 = 1 -// absl::CivilDay b(2015, 12, 31); -// int yd_dec_31 = absl::GetYearDay(b); // yd_dec_31 = 365 -// -inline int GetYearDay(CivilSecond cs) { - return time_internal::cctz::get_yearday(cs); -} - -// FormatCivilTime() -// -// Formats the given civil-time value into a string value of the following -// format: -// -// Type | Format -// --------------------------------- -// CivilSecond | YYYY-MM-DDTHH:MM:SS -// CivilMinute | YYYY-MM-DDTHH:MM -// CivilHour | YYYY-MM-DDTHH -// CivilDay | YYYY-MM-DD -// CivilMonth | YYYY-MM -// CivilYear | YYYY -// -// Example: -// -// absl::CivilDay d = absl::CivilDay(1969, 7, 20); -// std::string day_string = absl::FormatCivilTime(d); // "1969-07-20" -// -std::string FormatCivilTime(CivilSecond c); -std::string FormatCivilTime(CivilMinute c); -std::string FormatCivilTime(CivilHour c); -std::string FormatCivilTime(CivilDay c); -std::string FormatCivilTime(CivilMonth c); -std::string FormatCivilTime(CivilYear c); - -// absl::ParseCivilTime() -// -// Parses a civil-time value from the specified `absl::string_view` into the -// passed output parameter. Returns `true` upon successful parsing. -// -// The expected form of the input string is as follows: -// -// Type | Format -// --------------------------------- -// CivilSecond | YYYY-MM-DDTHH:MM:SS -// CivilMinute | YYYY-MM-DDTHH:MM -// CivilHour | YYYY-MM-DDTHH -// CivilDay | YYYY-MM-DD -// CivilMonth | YYYY-MM -// CivilYear | YYYY -// -// Example: -// -// absl::CivilDay d; -// bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK -// -// Note that parsing will fail if the string's format does not match the -// expected type exactly. `ParseLenientCivilTime()` below is more lenient. -// -bool ParseCivilTime(absl::string_view s, CivilSecond* c); -bool ParseCivilTime(absl::string_view s, CivilMinute* c); -bool ParseCivilTime(absl::string_view s, CivilHour* c); -bool ParseCivilTime(absl::string_view s, CivilDay* c); -bool ParseCivilTime(absl::string_view s, CivilMonth* c); -bool ParseCivilTime(absl::string_view s, CivilYear* c); - -// ParseLenientCivilTime() -// -// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more -// lenient if the format of the string does not exactly match the associated -// type. -// -// Example: -// -// absl::CivilDay d; -// bool ok = absl::ParseLenientCivilTime("1969-07-20", &d); // OK -// ok = absl::ParseLenientCivilTime("1969-07-20T10", &d); // OK: T10 floored -// ok = absl::ParseLenientCivilTime("1969-07", &d); // OK: day defaults to 1 -// -bool ParseLenientCivilTime(absl::string_view s, CivilSecond* c); -bool ParseLenientCivilTime(absl::string_view s, CivilMinute* c); -bool ParseLenientCivilTime(absl::string_view s, CivilHour* c); -bool ParseLenientCivilTime(absl::string_view s, CivilDay* c); -bool ParseLenientCivilTime(absl::string_view s, CivilMonth* c); -bool ParseLenientCivilTime(absl::string_view s, CivilYear* c); - -namespace time_internal { // For functions found via ADL on civil-time tags. - -// Streaming Operators -// -// Each civil-time type may be sent to an output stream using operator<<(). -// The result matches the string produced by `FormatCivilTime()`. -// -// Example: -// -// absl::CivilDay d = absl::CivilDay(1969, 7, 20); -// std::cout << "Date is: " << d << "\n"; -// -std::ostream& operator<<(std::ostream& os, CivilYear y); -std::ostream& operator<<(std::ostream& os, CivilMonth m); -std::ostream& operator<<(std::ostream& os, CivilDay d); -std::ostream& operator<<(std::ostream& os, CivilHour h); -std::ostream& operator<<(std::ostream& os, CivilMinute m); -std::ostream& operator<<(std::ostream& os, CivilSecond s); - -} // namespace time_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_CIVIL_TIME_H_ diff --git a/third_party/abseil_cpp/absl/time/civil_time_benchmark.cc b/third_party/abseil_cpp/absl/time/civil_time_benchmark.cc deleted file mode 100644 index f04dbe200ed2..000000000000 --- a/third_party/abseil_cpp/absl/time/civil_time_benchmark.cc +++ /dev/null @@ -1,127 +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/time/civil_time.h" - -#include <numeric> -#include <vector> - -#include "absl/hash/hash.h" -#include "benchmark/benchmark.h" - -namespace { - -// Run on (12 X 3492 MHz CPUs); 2018-11-05T13:44:29.814239103-08:00 -// CPU: Intel Haswell with HyperThreading (6 cores) dL1:32KB dL2:256KB dL3:15MB -// Benchmark Time(ns) CPU(ns) Iterations -// ---------------------------------------------------------------- -// BM_Difference_Days 14.5 14.5 48531105 -// BM_Step_Days 12.6 12.6 54876006 -// BM_Format 587 587 1000000 -// BM_Parse 692 692 1000000 -// BM_RoundTripFormatParse 1309 1309 532075 -// BM_CivilYearAbslHash 0.710 0.710 976400000 -// BM_CivilMonthAbslHash 1.13 1.13 619500000 -// BM_CivilDayAbslHash 1.70 1.70 426000000 -// BM_CivilHourAbslHash 2.45 2.45 287600000 -// BM_CivilMinuteAbslHash 3.21 3.21 226200000 -// BM_CivilSecondAbslHash 4.10 4.10 171800000 - -void BM_Difference_Days(benchmark::State& state) { - const absl::CivilDay c(2014, 8, 22); - const absl::CivilDay epoch(1970, 1, 1); - while (state.KeepRunning()) { - const absl::civil_diff_t n = c - epoch; - benchmark::DoNotOptimize(n); - } -} -BENCHMARK(BM_Difference_Days); - -void BM_Step_Days(benchmark::State& state) { - const absl::CivilDay kStart(2014, 8, 22); - absl::CivilDay c = kStart; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(++c); - } -} -BENCHMARK(BM_Step_Days); - -void BM_Format(benchmark::State& state) { - const absl::CivilSecond c(2014, 1, 2, 3, 4, 5); - while (state.KeepRunning()) { - const std::string s = absl::FormatCivilTime(c); - benchmark::DoNotOptimize(s); - } -} -BENCHMARK(BM_Format); - -void BM_Parse(benchmark::State& state) { - const std::string f = "2014-01-02T03:04:05"; - absl::CivilSecond c; - while (state.KeepRunning()) { - const bool b = absl::ParseCivilTime(f, &c); - benchmark::DoNotOptimize(b); - } -} -BENCHMARK(BM_Parse); - -void BM_RoundTripFormatParse(benchmark::State& state) { - const absl::CivilSecond c(2014, 1, 2, 3, 4, 5); - absl::CivilSecond out; - while (state.KeepRunning()) { - const bool b = absl::ParseCivilTime(absl::FormatCivilTime(c), &out); - benchmark::DoNotOptimize(b); - } -} -BENCHMARK(BM_RoundTripFormatParse); - -template <typename T> -void BM_CivilTimeAbslHash(benchmark::State& state) { - const int kSize = 100000; - std::vector<T> civil_times(kSize); - std::iota(civil_times.begin(), civil_times.end(), T(2018)); - - absl::Hash<T> absl_hasher; - while (state.KeepRunningBatch(kSize)) { - for (const T civil_time : civil_times) { - benchmark::DoNotOptimize(absl_hasher(civil_time)); - } - } -} -void BM_CivilYearAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilYear>(state); -} -void BM_CivilMonthAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilMonth>(state); -} -void BM_CivilDayAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilDay>(state); -} -void BM_CivilHourAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilHour>(state); -} -void BM_CivilMinuteAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilMinute>(state); -} -void BM_CivilSecondAbslHash(benchmark::State& state) { - BM_CivilTimeAbslHash<absl::CivilSecond>(state); -} -BENCHMARK(BM_CivilYearAbslHash); -BENCHMARK(BM_CivilMonthAbslHash); -BENCHMARK(BM_CivilDayAbslHash); -BENCHMARK(BM_CivilHourAbslHash); -BENCHMARK(BM_CivilMinuteAbslHash); -BENCHMARK(BM_CivilSecondAbslHash); - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/civil_time_test.cc b/third_party/abseil_cpp/absl/time/civil_time_test.cc deleted file mode 100644 index 0ebd97adbc56..000000000000 --- a/third_party/abseil_cpp/absl/time/civil_time_test.cc +++ /dev/null @@ -1,1243 +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/time/civil_time.h" - -#include <limits> -#include <sstream> -#include <type_traits> - -#include "absl/base/macros.h" -#include "gtest/gtest.h" - -namespace { - -TEST(CivilTime, DefaultConstruction) { - absl::CivilSecond ss; - EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss)); - - absl::CivilMinute mm; - EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm)); - - absl::CivilHour hh; - EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh)); - - absl::CivilDay d; - EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d)); - - absl::CivilMonth m; - EXPECT_EQ("1970-01", absl::FormatCivilTime(m)); - - absl::CivilYear y; - EXPECT_EQ("1970", absl::FormatCivilTime(y)); -} - -TEST(CivilTime, StructMember) { - struct S { - absl::CivilDay day; - }; - S s = {}; - EXPECT_EQ(absl::CivilDay{}, s.day); -} - -TEST(CivilTime, FieldsConstruction) { - EXPECT_EQ("2015-01-02T03:04:05", - absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03:04:00", - absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03:00:00", - absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00:00:00", - absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00:00:00", - absl::FormatCivilTime(absl::CivilSecond(2015, 1))); - EXPECT_EQ("2015-01-01T00:00:00", - absl::FormatCivilTime(absl::CivilSecond(2015))); - - EXPECT_EQ("2015-01-02T03:04", - absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03:04", - absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03:00", - absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00:00", - absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00:00", - absl::FormatCivilTime(absl::CivilMinute(2015, 1))); - EXPECT_EQ("2015-01-01T00:00", - absl::FormatCivilTime(absl::CivilMinute(2015))); - - EXPECT_EQ("2015-01-02T03", - absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03", - absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03", - absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00", - absl::FormatCivilTime(absl::CivilHour(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00", - absl::FormatCivilTime(absl::CivilHour(2015, 1))); - EXPECT_EQ("2015-01-01T00", - absl::FormatCivilTime(absl::CivilHour(2015))); - - EXPECT_EQ("2015-01-02", - absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02", - absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02", - absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02", - absl::FormatCivilTime(absl::CivilDay(2015, 1, 2))); - EXPECT_EQ("2015-01-01", - absl::FormatCivilTime(absl::CivilDay(2015, 1))); - EXPECT_EQ("2015-01-01", - absl::FormatCivilTime(absl::CivilDay(2015))); - - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3))); - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2))); - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015, 1))); - EXPECT_EQ("2015-01", - absl::FormatCivilTime(absl::CivilMonth(2015))); - - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3))); - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015, 1, 2))); - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015, 1))); - EXPECT_EQ("2015", - absl::FormatCivilTime(absl::CivilYear(2015))); -} - -TEST(CivilTime, FieldsConstructionLimits) { - const int kIntMax = std::numeric_limits<int>::max(); - EXPECT_EQ("2038-01-19T03:14:07", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, 0, 0, kIntMax))); - EXPECT_EQ("6121-02-11T05:21:07", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, 0, kIntMax, kIntMax))); - EXPECT_EQ("251104-11-20T12:21:07", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, kIntMax, kIntMax, kIntMax))); - EXPECT_EQ("6130715-05-30T12:21:07", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, kIntMax, kIntMax, kIntMax, kIntMax))); - EXPECT_EQ("185087685-11-26T12:21:07", - absl::FormatCivilTime(absl::CivilSecond( - 1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax))); - - const int kIntMin = std::numeric_limits<int>::min(); - EXPECT_EQ("1901-12-13T20:45:52", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, 0, 0, kIntMin))); - EXPECT_EQ("-2182-11-20T18:37:52", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, 0, kIntMin, kIntMin))); - EXPECT_EQ("-247165-02-11T10:37:52", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, 1, kIntMin, kIntMin, kIntMin))); - EXPECT_EQ("-6126776-08-01T10:37:52", - absl::FormatCivilTime(absl::CivilSecond( - 1970, 1, kIntMin, kIntMin, kIntMin, kIntMin))); - EXPECT_EQ("-185083747-10-31T10:37:52", - absl::FormatCivilTime(absl::CivilSecond( - 1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin))); -} - -TEST(CivilTime, RangeLimits) { - const absl::civil_year_t kYearMax = - std::numeric_limits<absl::civil_year_t>::max(); - EXPECT_EQ(absl::CivilYear(kYearMax), - absl::CivilYear::max()); - EXPECT_EQ(absl::CivilMonth(kYearMax, 12), - absl::CivilMonth::max()); - EXPECT_EQ(absl::CivilDay(kYearMax, 12, 31), - absl::CivilDay::max()); - EXPECT_EQ(absl::CivilHour(kYearMax, 12, 31, 23), - absl::CivilHour::max()); - EXPECT_EQ(absl::CivilMinute(kYearMax, 12, 31, 23, 59), - absl::CivilMinute::max()); - EXPECT_EQ(absl::CivilSecond(kYearMax, 12, 31, 23, 59, 59), - absl::CivilSecond::max()); - - const absl::civil_year_t kYearMin = - std::numeric_limits<absl::civil_year_t>::min(); - EXPECT_EQ(absl::CivilYear(kYearMin), - absl::CivilYear::min()); - EXPECT_EQ(absl::CivilMonth(kYearMin, 1), - absl::CivilMonth::min()); - EXPECT_EQ(absl::CivilDay(kYearMin, 1, 1), - absl::CivilDay::min()); - EXPECT_EQ(absl::CivilHour(kYearMin, 1, 1, 0), - absl::CivilHour::min()); - EXPECT_EQ(absl::CivilMinute(kYearMin, 1, 1, 0, 0), - absl::CivilMinute::min()); - EXPECT_EQ(absl::CivilSecond(kYearMin, 1, 1, 0, 0, 0), - absl::CivilSecond::min()); -} - -TEST(CivilTime, ImplicitCrossAlignment) { - absl::CivilYear year(2015); - absl::CivilMonth month = year; - absl::CivilDay day = month; - absl::CivilHour hour = day; - absl::CivilMinute minute = hour; - absl::CivilSecond second = minute; - - second = year; - EXPECT_EQ(second, year); - second = month; - EXPECT_EQ(second, month); - second = day; - EXPECT_EQ(second, day); - second = hour; - EXPECT_EQ(second, hour); - second = minute; - EXPECT_EQ(second, minute); - - minute = year; - EXPECT_EQ(minute, year); - minute = month; - EXPECT_EQ(minute, month); - minute = day; - EXPECT_EQ(minute, day); - minute = hour; - EXPECT_EQ(minute, hour); - - hour = year; - EXPECT_EQ(hour, year); - hour = month; - EXPECT_EQ(hour, month); - hour = day; - EXPECT_EQ(hour, day); - - day = year; - EXPECT_EQ(day, year); - day = month; - EXPECT_EQ(day, month); - - month = year; - EXPECT_EQ(month, year); - - // Ensures unsafe conversions are not allowed. - EXPECT_FALSE( - (std::is_convertible<absl::CivilSecond, absl::CivilMinute>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilSecond, absl::CivilHour>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilSecond, absl::CivilDay>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilSecond, absl::CivilMonth>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilSecond, absl::CivilYear>::value)); - - EXPECT_FALSE( - (std::is_convertible<absl::CivilMinute, absl::CivilHour>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilMinute, absl::CivilDay>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilMinute, absl::CivilMonth>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilMinute, absl::CivilYear>::value)); - - EXPECT_FALSE( - (std::is_convertible<absl::CivilHour, absl::CivilDay>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilHour, absl::CivilMonth>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilHour, absl::CivilYear>::value)); - - EXPECT_FALSE( - (std::is_convertible<absl::CivilDay, absl::CivilMonth>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::CivilDay, absl::CivilYear>::value)); - - EXPECT_FALSE( - (std::is_convertible<absl::CivilMonth, absl::CivilYear>::value)); -} - -TEST(CivilTime, ExplicitCrossAlignment) { - // - // Assign from smaller units -> larger units - // - - absl::CivilSecond second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second)); - - absl::CivilMinute minute(second); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute)); - - absl::CivilHour hour(minute); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour)); - - absl::CivilDay day(hour); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day)); - - absl::CivilMonth month(day); - EXPECT_EQ("2015-01", absl::FormatCivilTime(month)); - - absl::CivilYear year(month); - EXPECT_EQ("2015", absl::FormatCivilTime(year)); - - // - // Now assign from larger units -> smaller units - // - - month = absl::CivilMonth(year); - EXPECT_EQ("2015-01", absl::FormatCivilTime(month)); - - day = absl::CivilDay(month); - EXPECT_EQ("2015-01-01", absl::FormatCivilTime(day)); - - hour = absl::CivilHour(day); - EXPECT_EQ("2015-01-01T00", absl::FormatCivilTime(hour)); - - minute = absl::CivilMinute(hour); - EXPECT_EQ("2015-01-01T00:00", absl::FormatCivilTime(minute)); - - second = absl::CivilSecond(minute); - EXPECT_EQ("2015-01-01T00:00:00", absl::FormatCivilTime(second)); -} - -// Metafunction to test whether difference is allowed between two types. -template <typename T1, typename T2> -struct HasDiff { - template <typename U1, typename U2> - static std::false_type test(...); - template <typename U1, typename U2> - static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>())); - static constexpr bool value = decltype(test<T1, T2>(0))::value; -}; - -TEST(CivilTime, DisallowCrossAlignedDifference) { - // Difference is allowed between types with the same alignment. - static_assert(HasDiff<absl::CivilSecond, absl::CivilSecond>::value, ""); - static_assert(HasDiff<absl::CivilMinute, absl::CivilMinute>::value, ""); - static_assert(HasDiff<absl::CivilHour, absl::CivilHour>::value, ""); - static_assert(HasDiff<absl::CivilDay, absl::CivilDay>::value, ""); - static_assert(HasDiff<absl::CivilMonth, absl::CivilMonth>::value, ""); - static_assert(HasDiff<absl::CivilYear, absl::CivilYear>::value, ""); - - // Difference is disallowed between types with different alignments. - static_assert(!HasDiff<absl::CivilSecond, absl::CivilMinute>::value, ""); - static_assert(!HasDiff<absl::CivilSecond, absl::CivilHour>::value, ""); - static_assert(!HasDiff<absl::CivilSecond, absl::CivilDay>::value, ""); - static_assert(!HasDiff<absl::CivilSecond, absl::CivilMonth>::value, ""); - static_assert(!HasDiff<absl::CivilSecond, absl::CivilYear>::value, ""); - - static_assert(!HasDiff<absl::CivilMinute, absl::CivilHour>::value, ""); - static_assert(!HasDiff<absl::CivilMinute, absl::CivilDay>::value, ""); - static_assert(!HasDiff<absl::CivilMinute, absl::CivilMonth>::value, ""); - static_assert(!HasDiff<absl::CivilMinute, absl::CivilYear>::value, ""); - - static_assert(!HasDiff<absl::CivilHour, absl::CivilDay>::value, ""); - static_assert(!HasDiff<absl::CivilHour, absl::CivilMonth>::value, ""); - static_assert(!HasDiff<absl::CivilHour, absl::CivilYear>::value, ""); - - static_assert(!HasDiff<absl::CivilDay, absl::CivilMonth>::value, ""); - static_assert(!HasDiff<absl::CivilDay, absl::CivilYear>::value, ""); - - static_assert(!HasDiff<absl::CivilMonth, absl::CivilYear>::value, ""); -} - -TEST(CivilTime, ValueSemantics) { - const absl::CivilHour a(2015, 1, 2, 3); - const absl::CivilHour b = a; - const absl::CivilHour c(b); - absl::CivilHour d; - d = c; - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(d)); -} - -TEST(CivilTime, Relational) { - // Tests that the alignment unit is ignored in comparison. - const absl::CivilYear year(2014); - const absl::CivilMonth month(year); - EXPECT_EQ(year, month); - -#define TEST_RELATIONAL(OLDER, YOUNGER) \ - do { \ - EXPECT_FALSE(OLDER < OLDER); \ - EXPECT_FALSE(OLDER > OLDER); \ - EXPECT_TRUE(OLDER >= OLDER); \ - EXPECT_TRUE(OLDER <= OLDER); \ - EXPECT_FALSE(YOUNGER < YOUNGER); \ - EXPECT_FALSE(YOUNGER > YOUNGER); \ - EXPECT_TRUE(YOUNGER >= YOUNGER); \ - EXPECT_TRUE(YOUNGER <= YOUNGER); \ - EXPECT_EQ(OLDER, OLDER); \ - EXPECT_NE(OLDER, YOUNGER); \ - EXPECT_LT(OLDER, YOUNGER); \ - EXPECT_LE(OLDER, YOUNGER); \ - EXPECT_GT(YOUNGER, OLDER); \ - EXPECT_GE(YOUNGER, OLDER); \ - } while (0) - - // Alignment is ignored in comparison (verified above), so CivilSecond is - // used to test comparison in all field positions. - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0), - absl::CivilSecond(2015, 1, 1, 0, 0, 0)); - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0), - absl::CivilSecond(2014, 2, 1, 0, 0, 0)); - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0), - absl::CivilSecond(2014, 1, 2, 0, 0, 0)); - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0), - absl::CivilSecond(2014, 1, 1, 1, 0, 0)); - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 0, 0), - absl::CivilSecond(2014, 1, 1, 1, 1, 0)); - TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 1, 0), - absl::CivilSecond(2014, 1, 1, 1, 1, 1)); - - // Tests the relational operators of two different civil-time types. - TEST_RELATIONAL(absl::CivilDay(2014, 1, 1), - absl::CivilMinute(2014, 1, 1, 1, 1)); - TEST_RELATIONAL(absl::CivilDay(2014, 1, 1), - absl::CivilMonth(2014, 2)); - -#undef TEST_RELATIONAL -} - -TEST(CivilTime, Arithmetic) { - absl::CivilSecond second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ("2015-01-02T03:04:06", absl::FormatCivilTime(second += 1)); - EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second + 1)); - EXPECT_EQ("2015-01-02T03:04:08", absl::FormatCivilTime(2 + second)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second - 1)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second -= 1)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second++)); - EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(++second)); - EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second--)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(--second)); - - absl::CivilMinute minute(2015, 1, 2, 3, 4); - EXPECT_EQ("2015-01-02T03:05", absl::FormatCivilTime(minute += 1)); - EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute + 1)); - EXPECT_EQ("2015-01-02T03:07", absl::FormatCivilTime(2 + minute)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute - 1)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute -= 1)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute++)); - EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(++minute)); - EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute--)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(--minute)); - - absl::CivilHour hour(2015, 1, 2, 3); - EXPECT_EQ("2015-01-02T04", absl::FormatCivilTime(hour += 1)); - EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour + 1)); - EXPECT_EQ("2015-01-02T06", absl::FormatCivilTime(2 + hour)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour - 1)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour -= 1)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour++)); - EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(++hour)); - EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour--)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(--hour)); - - absl::CivilDay day(2015, 1, 2); - EXPECT_EQ("2015-01-03", absl::FormatCivilTime(day += 1)); - EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day + 1)); - EXPECT_EQ("2015-01-05", absl::FormatCivilTime(2 + day)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day - 1)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day -= 1)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day++)); - EXPECT_EQ("2015-01-04", absl::FormatCivilTime(++day)); - EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day--)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(--day)); - - absl::CivilMonth month(2015, 1); - EXPECT_EQ("2015-02", absl::FormatCivilTime(month += 1)); - EXPECT_EQ("2015-03", absl::FormatCivilTime(month + 1)); - EXPECT_EQ("2015-04", absl::FormatCivilTime(2 + month)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(month - 1)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(month -= 1)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(month++)); - EXPECT_EQ("2015-03", absl::FormatCivilTime(++month)); - EXPECT_EQ("2015-03", absl::FormatCivilTime(month--)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(--month)); - - absl::CivilYear year(2015); - EXPECT_EQ("2016", absl::FormatCivilTime(year += 1)); - EXPECT_EQ("2017", absl::FormatCivilTime(year + 1)); - EXPECT_EQ("2018", absl::FormatCivilTime(2 + year)); - EXPECT_EQ("2015", absl::FormatCivilTime(year - 1)); - EXPECT_EQ("2015", absl::FormatCivilTime(year -= 1)); - EXPECT_EQ("2015", absl::FormatCivilTime(year++)); - EXPECT_EQ("2017", absl::FormatCivilTime(++year)); - EXPECT_EQ("2017", absl::FormatCivilTime(year--)); - EXPECT_EQ("2015", absl::FormatCivilTime(--year)); -} - -TEST(CivilTime, ArithmeticLimits) { - const int kIntMax = std::numeric_limits<int>::max(); - const int kIntMin = std::numeric_limits<int>::min(); - - absl::CivilSecond second(1970, 1, 1, 0, 0, 0); - second += kIntMax; - EXPECT_EQ("2038-01-19T03:14:07", absl::FormatCivilTime(second)); - second -= kIntMax; - EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second)); - second += kIntMin; - EXPECT_EQ("1901-12-13T20:45:52", absl::FormatCivilTime(second)); - second -= kIntMin; - EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second)); - - absl::CivilMinute minute(1970, 1, 1, 0, 0); - minute += kIntMax; - EXPECT_EQ("6053-01-23T02:07", absl::FormatCivilTime(minute)); - minute -= kIntMax; - EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute)); - minute += kIntMin; - EXPECT_EQ("-2114-12-08T21:52", absl::FormatCivilTime(minute)); - minute -= kIntMin; - EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute)); - - absl::CivilHour hour(1970, 1, 1, 0); - hour += kIntMax; - EXPECT_EQ("246953-10-09T07", absl::FormatCivilTime(hour)); - hour -= kIntMax; - EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour)); - hour += kIntMin; - EXPECT_EQ("-243014-03-24T16", absl::FormatCivilTime(hour)); - hour -= kIntMin; - EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour)); - - absl::CivilDay day(1970, 1, 1); - day += kIntMax; - EXPECT_EQ("5881580-07-11", absl::FormatCivilTime(day)); - day -= kIntMax; - EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day)); - day += kIntMin; - EXPECT_EQ("-5877641-06-23", absl::FormatCivilTime(day)); - day -= kIntMin; - EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day)); - - absl::CivilMonth month(1970, 1); - month += kIntMax; - EXPECT_EQ("178958940-08", absl::FormatCivilTime(month)); - month -= kIntMax; - EXPECT_EQ("1970-01", absl::FormatCivilTime(month)); - month += kIntMin; - EXPECT_EQ("-178955001-05", absl::FormatCivilTime(month)); - month -= kIntMin; - EXPECT_EQ("1970-01", absl::FormatCivilTime(month)); - - absl::CivilYear year(0); - year += kIntMax; - EXPECT_EQ("2147483647", absl::FormatCivilTime(year)); - year -= kIntMax; - EXPECT_EQ("0", absl::FormatCivilTime(year)); - year += kIntMin; - EXPECT_EQ("-2147483648", absl::FormatCivilTime(year)); - year -= kIntMin; - EXPECT_EQ("0", absl::FormatCivilTime(year)); -} - -TEST(CivilTime, Difference) { - absl::CivilSecond second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ(0, second - second); - EXPECT_EQ(10, (second + 10) - second); - EXPECT_EQ(-10, (second - 10) - second); - - absl::CivilMinute minute(2015, 1, 2, 3, 4); - EXPECT_EQ(0, minute - minute); - EXPECT_EQ(10, (minute + 10) - minute); - EXPECT_EQ(-10, (minute - 10) - minute); - - absl::CivilHour hour(2015, 1, 2, 3); - EXPECT_EQ(0, hour - hour); - EXPECT_EQ(10, (hour + 10) - hour); - EXPECT_EQ(-10, (hour - 10) - hour); - - absl::CivilDay day(2015, 1, 2); - EXPECT_EQ(0, day - day); - EXPECT_EQ(10, (day + 10) - day); - EXPECT_EQ(-10, (day - 10) - day); - - absl::CivilMonth month(2015, 1); - EXPECT_EQ(0, month - month); - EXPECT_EQ(10, (month + 10) - month); - EXPECT_EQ(-10, (month - 10) - month); - - absl::CivilYear year(2015); - EXPECT_EQ(0, year - year); - EXPECT_EQ(10, (year + 10) - year); - EXPECT_EQ(-10, (year - 10) - year); -} - -TEST(CivilTime, DifferenceLimits) { - const absl::civil_diff_t kDiffMax = - std::numeric_limits<absl::civil_diff_t>::max(); - const absl::civil_diff_t kDiffMin = - std::numeric_limits<absl::civil_diff_t>::min(); - - // Check day arithmetic at the end of the year range. - const absl::CivilDay max_day(kDiffMax, 12, 31); - EXPECT_EQ(1, max_day - (max_day - 1)); - EXPECT_EQ(-1, (max_day - 1) - max_day); - - // Check day arithmetic at the start of the year range. - const absl::CivilDay min_day(kDiffMin, 1, 1); - EXPECT_EQ(1, (min_day + 1) - min_day); - EXPECT_EQ(-1, min_day - (min_day + 1)); - - // Check the limits of the return value. - const absl::CivilDay d1(1970, 1, 1); - const absl::CivilDay d2(25252734927768524, 7, 27); - EXPECT_EQ(kDiffMax, d2 - d1); - EXPECT_EQ(kDiffMin, d1 - (d2 + 1)); -} - -TEST(CivilTime, Properties) { - absl::CivilSecond ss(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, ss.year()); - EXPECT_EQ(2, ss.month()); - EXPECT_EQ(3, ss.day()); - EXPECT_EQ(4, ss.hour()); - EXPECT_EQ(5, ss.minute()); - EXPECT_EQ(6, ss.second()); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ss)); - EXPECT_EQ(34, absl::GetYearDay(ss)); - - absl::CivilMinute mm(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, mm.year()); - EXPECT_EQ(2, mm.month()); - EXPECT_EQ(3, mm.day()); - EXPECT_EQ(4, mm.hour()); - EXPECT_EQ(5, mm.minute()); - EXPECT_EQ(0, mm.second()); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(mm)); - EXPECT_EQ(34, absl::GetYearDay(mm)); - - absl::CivilHour hh(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, hh.year()); - EXPECT_EQ(2, hh.month()); - EXPECT_EQ(3, hh.day()); - EXPECT_EQ(4, hh.hour()); - EXPECT_EQ(0, hh.minute()); - EXPECT_EQ(0, hh.second()); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(hh)); - EXPECT_EQ(34, absl::GetYearDay(hh)); - - absl::CivilDay d(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, d.year()); - EXPECT_EQ(2, d.month()); - EXPECT_EQ(3, d.day()); - EXPECT_EQ(0, d.hour()); - EXPECT_EQ(0, d.minute()); - EXPECT_EQ(0, d.second()); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(d)); - EXPECT_EQ(34, absl::GetYearDay(d)); - - absl::CivilMonth m(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, m.year()); - EXPECT_EQ(2, m.month()); - EXPECT_EQ(1, m.day()); - EXPECT_EQ(0, m.hour()); - EXPECT_EQ(0, m.minute()); - EXPECT_EQ(0, m.second()); - EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(m)); - EXPECT_EQ(32, absl::GetYearDay(m)); - - absl::CivilYear y(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, y.year()); - EXPECT_EQ(1, y.month()); - EXPECT_EQ(1, y.day()); - EXPECT_EQ(0, y.hour()); - EXPECT_EQ(0, y.minute()); - EXPECT_EQ(0, y.second()); - EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(y)); - EXPECT_EQ(1, absl::GetYearDay(y)); -} - -TEST(CivilTime, Format) { - absl::CivilSecond ss; - EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss)); - - absl::CivilMinute mm; - EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm)); - - absl::CivilHour hh; - EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh)); - - absl::CivilDay d; - EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d)); - - absl::CivilMonth m; - EXPECT_EQ("1970-01", absl::FormatCivilTime(m)); - - absl::CivilYear y; - EXPECT_EQ("1970", absl::FormatCivilTime(y)); -} - -TEST(CivilTime, Parse) { - absl::CivilSecond ss; - absl::CivilMinute mm; - absl::CivilHour hh; - absl::CivilDay d; - absl::CivilMonth m; - absl::CivilYear y; - - // CivilSecond OK; others fail - EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04:05", &ss)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &mm)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &hh)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &d)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &m)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &y)); - - // CivilMinute OK; others fail - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &ss)); - EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04", &mm)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &hh)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &d)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &m)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &y)); - - // CivilHour OK; others fail - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &ss)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &mm)); - EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03", &hh)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &d)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &m)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &y)); - - // CivilDay OK; others fail - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &ss)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &mm)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &hh)); - EXPECT_TRUE(absl::ParseCivilTime("2015-01-02", &d)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &m)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &y)); - - // CivilMonth OK; others fail - EXPECT_FALSE(absl::ParseCivilTime("2015-01", &ss)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01", &mm)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01", &hh)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01", &d)); - EXPECT_TRUE(absl::ParseCivilTime("2015-01", &m)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(m)); - EXPECT_FALSE(absl::ParseCivilTime("2015-01", &y)); - - // CivilYear OK; others fail - EXPECT_FALSE(absl::ParseCivilTime("2015", &ss)); - EXPECT_FALSE(absl::ParseCivilTime("2015", &mm)); - EXPECT_FALSE(absl::ParseCivilTime("2015", &hh)); - EXPECT_FALSE(absl::ParseCivilTime("2015", &d)); - EXPECT_FALSE(absl::ParseCivilTime("2015", &m)); - EXPECT_TRUE(absl::ParseCivilTime("2015", &y)); - EXPECT_EQ("2015", absl::FormatCivilTime(y)); -} - -TEST(CivilTime, FormatAndParseLenient) { - absl::CivilSecond ss; - EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss)); - - absl::CivilMinute mm; - EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm)); - - absl::CivilHour hh; - EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh)); - - absl::CivilDay d; - EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d)); - - absl::CivilMonth m; - EXPECT_EQ("1970-01", absl::FormatCivilTime(m)); - - absl::CivilYear y; - EXPECT_EQ("1970", absl::FormatCivilTime(y)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &ss)); - EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &mm)); - EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &hh)); - EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &d)); - EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &m)); - EXPECT_EQ("2015-01", absl::FormatCivilTime(m)); - - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &y)); - EXPECT_EQ("2015", absl::FormatCivilTime(y)); -} - -TEST(CivilTime, ParseEdgeCases) { - absl::CivilSecond ss; - EXPECT_TRUE( - absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59:59", &ss)); - EXPECT_EQ("9223372036854775807-12-31T23:59:59", absl::FormatCivilTime(ss)); - EXPECT_TRUE( - absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00:00", &ss)); - EXPECT_EQ("-9223372036854775808-01-01T00:00:00", absl::FormatCivilTime(ss)); - - absl::CivilMinute mm; - EXPECT_TRUE( - absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59", &mm)); - EXPECT_EQ("9223372036854775807-12-31T23:59", absl::FormatCivilTime(mm)); - EXPECT_TRUE( - absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00", &mm)); - EXPECT_EQ("-9223372036854775808-01-01T00:00", absl::FormatCivilTime(mm)); - - absl::CivilHour hh; - EXPECT_TRUE( - absl::ParseLenientCivilTime("9223372036854775807-12-31T23", &hh)); - EXPECT_EQ("9223372036854775807-12-31T23", absl::FormatCivilTime(hh)); - EXPECT_TRUE( - absl::ParseLenientCivilTime("-9223372036854775808-01-01T00", &hh)); - EXPECT_EQ("-9223372036854775808-01-01T00", absl::FormatCivilTime(hh)); - - absl::CivilDay d; - EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12-31", &d)); - EXPECT_EQ("9223372036854775807-12-31", absl::FormatCivilTime(d)); - EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01-01", &d)); - EXPECT_EQ("-9223372036854775808-01-01", absl::FormatCivilTime(d)); - - absl::CivilMonth m; - EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12", &m)); - EXPECT_EQ("9223372036854775807-12", absl::FormatCivilTime(m)); - EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01", &m)); - EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(m)); - - absl::CivilYear y; - EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807", &y)); - EXPECT_EQ("9223372036854775807", absl::FormatCivilTime(y)); - EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808", &y)); - EXPECT_EQ("-9223372036854775808", absl::FormatCivilTime(y)); - - // Tests some valid, but interesting, cases - EXPECT_TRUE(absl::ParseLenientCivilTime("0", &ss)) << ss; - EXPECT_EQ(absl::CivilYear(0), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime("0-1", &ss)) << ss; - EXPECT_EQ(absl::CivilMonth(0, 1), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015 ", &ss)) << ss; - EXPECT_EQ(absl::CivilYear(2015), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6 ", &ss)) << ss; - EXPECT_EQ(absl::CivilMonth(2015, 6), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-6-7", &ss)) << ss; - EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6-7 ", &ss)) << ss; - EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime("2015-06-07T10:11:12 ", &ss)) << ss; - EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-06-07T10:11:12 ", &ss)) << ss; - EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss); - EXPECT_TRUE(absl::ParseLenientCivilTime("-01-01", &ss)) << ss; - EXPECT_EQ(absl::CivilMonth(-1, 1), ss); - - // Tests some invalid cases - EXPECT_FALSE(absl::ParseLenientCivilTime("01-01-2015", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015-", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("0xff-01", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-30T04:05:06", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:96", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("X2015-02-03T04:05:06", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:003", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015 -02-03T04:05:06", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03-04:05:06", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("2015:02:03T04-05-06", &ss)) << ss; - EXPECT_FALSE(absl::ParseLenientCivilTime("9223372036854775808", &y)) << y; -} - -TEST(CivilTime, OutputStream) { - absl::CivilSecond cs(2016, 2, 3, 4, 5, 6); - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilYear(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016.................X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilMonth(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02..............X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilDay(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03...........X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilHour(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04........X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilMinute(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04:05.....X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::CivilSecond(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04:05:06..X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << absl::Weekday::wednesday; - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..Wednesday............X..", ss.str()); - } -} - -TEST(CivilTime, Weekday) { - absl::CivilDay d(1970, 1, 1); - EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(d)) << d; - - // We used to get this wrong for years < -30. - d = absl::CivilDay(-31, 12, 24); - EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(d)) << d; -} - -TEST(CivilTime, NextPrevWeekday) { - // Jan 1, 1970 was a Thursday. - const absl::CivilDay thursday(1970, 1, 1); - - // Thursday -> Thursday - absl::CivilDay d = absl::NextWeekday(thursday, absl::Weekday::thursday); - EXPECT_EQ(7, d - thursday) << d; - EXPECT_EQ(d - 14, absl::PrevWeekday(thursday, absl::Weekday::thursday)); - - // Thursday -> Friday - d = absl::NextWeekday(thursday, absl::Weekday::friday); - EXPECT_EQ(1, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::friday)); - - // Thursday -> Saturday - d = absl::NextWeekday(thursday, absl::Weekday::saturday); - EXPECT_EQ(2, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::saturday)); - - // Thursday -> Sunday - d = absl::NextWeekday(thursday, absl::Weekday::sunday); - EXPECT_EQ(3, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::sunday)); - - // Thursday -> Monday - d = absl::NextWeekday(thursday, absl::Weekday::monday); - EXPECT_EQ(4, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::monday)); - - // Thursday -> Tuesday - d = absl::NextWeekday(thursday, absl::Weekday::tuesday); - EXPECT_EQ(5, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::tuesday)); - - // Thursday -> Wednesday - d = absl::NextWeekday(thursday, absl::Weekday::wednesday); - EXPECT_EQ(6, d - thursday) << d; - EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::wednesday)); -} - -// NOTE: Run this with --copt=-ftrapv to detect overflow problems. -TEST(CivilTime, DifferenceWithHugeYear) { - absl::CivilDay d1(9223372036854775807, 1, 1); - absl::CivilDay d2(9223372036854775807, 12, 31); - EXPECT_EQ(364, d2 - d1); - - d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1); - d2 = absl::CivilDay(-9223372036854775807 - 1, 12, 31); - EXPECT_EQ(365, d2 - d1); - - // Check the limits of the return value at the end of the year range. - d1 = absl::CivilDay(9223372036854775807, 1, 1); - d2 = absl::CivilDay(9198119301927009252, 6, 6); - EXPECT_EQ(9223372036854775807, d1 - d2); - d2 = d2 - 1; - EXPECT_EQ(-9223372036854775807 - 1, d2 - d1); - - // Check the limits of the return value at the start of the year range. - d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1); - d2 = absl::CivilDay(-9198119301927009254, 7, 28); - EXPECT_EQ(9223372036854775807, d2 - d1); - d2 = d2 + 1; - EXPECT_EQ(-9223372036854775807 - 1, d1 - d2); - - // Check the limits of the return value from either side of year 0. - d1 = absl::CivilDay(-12626367463883278, 9, 3); - d2 = absl::CivilDay(12626367463883277, 3, 28); - EXPECT_EQ(9223372036854775807, d2 - d1); - d2 = d2 + 1; - EXPECT_EQ(-9223372036854775807 - 1, d1 - d2); -} - -// NOTE: Run this with --copt=-ftrapv to detect overflow problems. -TEST(CivilTime, DifferenceNoIntermediateOverflow) { - // The difference up to the minute field would be below the minimum - // int64_t, but the 52 extra seconds brings us back to the minimum. - absl::CivilSecond s1(-292277022657, 1, 27, 8, 29 - 1, 52); - absl::CivilSecond s2(1970, 1, 1, 0, 0 - 1, 0); - EXPECT_EQ(-9223372036854775807 - 1, s1 - s2); - - // The difference up to the minute field would be above the maximum - // int64_t, but the -53 extra seconds brings us back to the maximum. - s1 = absl::CivilSecond(292277026596, 12, 4, 15, 30, 7 - 7); - s2 = absl::CivilSecond(1970, 1, 1, 0, 0, 0 - 7); - EXPECT_EQ(9223372036854775807, s1 - s2); -} - -TEST(CivilTime, NormalizeSimpleOverflow) { - absl::CivilSecond cs; - cs = absl::CivilSecond(2013, 11, 15, 16, 32, 59 + 1); - EXPECT_EQ("2013-11-15T16:33:00", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16, 59 + 1, 14); - EXPECT_EQ("2013-11-15T17:00:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 23 + 1, 32, 14); - EXPECT_EQ("2013-11-16T00:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 30 + 1, 16, 32, 14); - EXPECT_EQ("2013-12-01T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 12 + 1, 15, 16, 32, 14); - EXPECT_EQ("2014-01-15T16:32:14", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeSimpleUnderflow) { - absl::CivilSecond cs; - cs = absl::CivilSecond(2013, 11, 15, 16, 32, 0 - 1); - EXPECT_EQ("2013-11-15T16:31:59", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16, 0 - 1, 14); - EXPECT_EQ("2013-11-15T15:59:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 0 - 1, 32, 14); - EXPECT_EQ("2013-11-14T23:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 1 - 1, 16, 32, 14); - EXPECT_EQ("2013-10-31T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 1 - 1, 15, 16, 32, 14); - EXPECT_EQ("2012-12-15T16:32:14", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeMultipleOverflow) { - absl::CivilSecond cs(2013, 12, 31, 23, 59, 59 + 1); - EXPECT_EQ("2014-01-01T00:00:00", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeMultipleUnderflow) { - absl::CivilSecond cs(2014, 1, 1, 0, 0, 0 - 1); - EXPECT_EQ("2013-12-31T23:59:59", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeOverflowLimits) { - absl::CivilSecond cs; - - const int kintmax = std::numeric_limits<int>::max(); - cs = absl::CivilSecond(0, kintmax, kintmax, kintmax, kintmax, kintmax); - EXPECT_EQ("185085715-11-27T12:21:07", absl::FormatCivilTime(cs)); - - const int kintmin = std::numeric_limits<int>::min(); - cs = absl::CivilSecond(0, kintmin, kintmin, kintmin, kintmin, kintmin); - EXPECT_EQ("-185085717-10-31T10:37:52", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeComplexOverflow) { - absl::CivilSecond cs; - cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 + 123456789); - EXPECT_EQ("2017-10-14T14:05:23", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16, 32 + 1234567, 14); - EXPECT_EQ("2016-03-22T00:39:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16 + 123456, 32, 14); - EXPECT_EQ("2027-12-16T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15 + 1234, 16, 32, 14); - EXPECT_EQ("2017-04-02T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11 + 123, 15, 16, 32, 14); - EXPECT_EQ("2024-02-15T16:32:14", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeComplexUnderflow) { - absl::CivilSecond cs; - cs = absl::CivilSecond(1999, 3, 0, 0, 0, 0); // year 400 - EXPECT_EQ("1999-02-28T00:00:00", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 - 123456789); - EXPECT_EQ("2009-12-17T18:59:05", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16, 32 - 1234567, 14); - EXPECT_EQ("2011-07-12T08:25:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15, 16 - 123456, 32, 14); - EXPECT_EQ("1999-10-16T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11, 15 - 1234, 16, 32, 14); - EXPECT_EQ("2010-06-30T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11 - 123, 15, 16, 32, 14); - EXPECT_EQ("2003-08-15T16:32:14", absl::FormatCivilTime(cs)); -} - -TEST(CivilTime, NormalizeMishmash) { - absl::CivilSecond cs; - cs = absl::CivilSecond(2013, 11 - 123, 15 + 1234, 16 - 123456, 32 + 1234567, - 14 - 123456789); - EXPECT_EQ("1991-05-09T03:06:05", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11 + 123, 15 - 1234, 16 + 123456, 32 - 1234567, - 14 + 123456789); - EXPECT_EQ("2036-05-24T05:58:23", absl::FormatCivilTime(cs)); - - cs = absl::CivilSecond(2013, 11, -146097 + 1, 16, 32, 14); - EXPECT_EQ("1613-11-01T16:32:14", absl::FormatCivilTime(cs)); - cs = absl::CivilSecond(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14); - EXPECT_EQ("2013-11-01T16:32:14", absl::FormatCivilTime(cs)); -} - -// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31) -// and check that they normalize to the expected time. 146097 days span -// the 400-year Gregorian cycle used during normalization. -TEST(CivilTime, NormalizeAllTheDays) { - absl::CivilDay expected(1970, 1, 1); - for (int day = 1; day <= 146097; ++day) { - absl::CivilSecond cs(1970, 1, day, 0, 0, 0); - EXPECT_EQ(expected, cs); - ++expected; - } -} - -TEST(CivilTime, NormalizeWithHugeYear) { - absl::CivilMonth c(9223372036854775807, 1); - EXPECT_EQ("9223372036854775807-01", absl::FormatCivilTime(c)); - c = c - 1; // Causes normalization - EXPECT_EQ("9223372036854775806-12", absl::FormatCivilTime(c)); - - c = absl::CivilMonth(-9223372036854775807 - 1, 1); - EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(c)); - c = c + 12; // Causes normalization - EXPECT_EQ("-9223372036854775807-01", absl::FormatCivilTime(c)); -} - -TEST(CivilTime, LeapYears) { - const absl::CivilSecond s1(2013, 2, 28 + 1, 0, 0, 0); - EXPECT_EQ("2013-03-01T00:00:00", absl::FormatCivilTime(s1)); - - const absl::CivilSecond s2(2012, 2, 28 + 1, 0, 0, 0); - EXPECT_EQ("2012-02-29T00:00:00", absl::FormatCivilTime(s2)); - - const absl::CivilSecond s3(1900, 2, 28 + 1, 0, 0, 0); - EXPECT_EQ("1900-03-01T00:00:00", absl::FormatCivilTime(s3)); - - const struct { - int year; - int days; - struct { - int month; - int day; - } leap_day; // The date of the day after Feb 28. - } kLeapYearTable[]{ - {1900, 365, {3, 1}}, - {1999, 365, {3, 1}}, - {2000, 366, {2, 29}}, // leap year - {2001, 365, {3, 1}}, - {2002, 365, {3, 1}}, - {2003, 365, {3, 1}}, - {2004, 366, {2, 29}}, // leap year - {2005, 365, {3, 1}}, - {2006, 365, {3, 1}}, - {2007, 365, {3, 1}}, - {2008, 366, {2, 29}}, // leap year - {2009, 365, {3, 1}}, - {2100, 365, {3, 1}}, - }; - - for (int i = 0; i < ABSL_ARRAYSIZE(kLeapYearTable); ++i) { - const int y = kLeapYearTable[i].year; - const int m = kLeapYearTable[i].leap_day.month; - const int d = kLeapYearTable[i].leap_day.day; - const int n = kLeapYearTable[i].days; - - // Tests incrementing through the leap day. - const absl::CivilDay feb28(y, 2, 28); - const absl::CivilDay next_day = feb28 + 1; - EXPECT_EQ(m, next_day.month()); - EXPECT_EQ(d, next_day.day()); - - // Tests difference in days of leap years. - const absl::CivilYear year(feb28); - const absl::CivilYear next_year = year + 1; - EXPECT_EQ(n, absl::CivilDay(next_year) - absl::CivilDay(year)); - } -} - -TEST(CivilTime, FirstThursdayInMonth) { - const absl::CivilDay nov1(2014, 11, 1); - const absl::CivilDay thursday = - absl::NextWeekday(nov1 - 1, absl::Weekday::thursday); - EXPECT_EQ("2014-11-06", absl::FormatCivilTime(thursday)); - - // Bonus: Date of Thanksgiving in the United States - // Rule: Fourth Thursday of November - const absl::CivilDay thanksgiving = thursday + 7 * 3; - EXPECT_EQ("2014-11-27", absl::FormatCivilTime(thanksgiving)); -} - -TEST(CivilTime, DocumentationExample) { - absl::CivilSecond second(2015, 6, 28, 1, 2, 3); // 2015-06-28 01:02:03 - absl::CivilMinute minute(second); // 2015-06-28 01:02:00 - absl::CivilDay day(minute); // 2015-06-28 00:00:00 - - second -= 1; // 2015-06-28 01:02:02 - --second; // 2015-06-28 01:02:01 - EXPECT_EQ(minute, second - 1); // Comparison between types - EXPECT_LT(minute, second); - - // int diff = second - minute; // ERROR: Mixed types, won't compile - - absl::CivilDay june_1(2015, 6, 1); // Pass fields to c'tor. - int diff = day - june_1; // Num days between 'day' and June 1 - EXPECT_EQ(27, diff); - - // Fields smaller than alignment are floored to their minimum value. - absl::CivilDay day_floor(2015, 1, 2, 9, 9, 9); - EXPECT_EQ(0, day_floor.hour()); // 09:09:09 is floored - EXPECT_EQ(absl::CivilDay(2015, 1, 2), day_floor); - - // Unspecified fields default to their minium value - absl::CivilDay day_default(2015); // Defaults to Jan 1 - EXPECT_EQ(absl::CivilDay(2015, 1, 1), day_default); - - // Iterates all the days of June. - absl::CivilMonth june(day); // CivilDay -> CivilMonth - absl::CivilMonth july = june + 1; - for (absl::CivilDay day = june_1; day < july; ++day) { - // ... - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/clock.cc b/third_party/abseil_cpp/absl/time/clock.cc deleted file mode 100644 index 6862e011be1f..000000000000 --- a/third_party/abseil_cpp/absl/time/clock.cc +++ /dev/null @@ -1,567 +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/time/clock.h" - -#include "absl/base/attributes.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include <algorithm> -#include <atomic> -#include <cerrno> -#include <cstdint> -#include <ctime> -#include <limits> - -#include "absl/base/internal/spinlock.h" -#include "absl/base/internal/unscaledcycleclock.h" -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/base/thread_annotations.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -Time Now() { - // TODO(bww): Get a timespec instead so we don't have to divide. - int64_t n = absl::GetCurrentTimeNanos(); - if (n >= 0) { - return time_internal::FromUnixDuration( - time_internal::MakeDuration(n / 1000000000, n % 1000000000 * 4)); - } - return time_internal::FromUnixDuration(absl::Nanoseconds(n)); -} -ABSL_NAMESPACE_END -} // namespace absl - -// Decide if we should use the fast GetCurrentTimeNanos() algorithm -// based on the cyclecounter, otherwise just get the time directly -// from the OS on every call. This can be chosen at compile-time via -// -DABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS=[0|1] -#ifndef ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS -#if ABSL_USE_UNSCALED_CYCLECLOCK -#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 1 -#else -#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 0 -#endif -#endif - -#if defined(__APPLE__) || defined(_WIN32) -#include "absl/time/internal/get_current_time_chrono.inc" -#else -#include "absl/time/internal/get_current_time_posix.inc" -#endif - -// Allows override by test. -#ifndef GET_CURRENT_TIME_NANOS_FROM_SYSTEM -#define GET_CURRENT_TIME_NANOS_FROM_SYSTEM() \ - ::absl::time_internal::GetCurrentTimeNanosFromSystem() -#endif - -#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS -namespace absl { -ABSL_NAMESPACE_BEGIN -int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); } -ABSL_NAMESPACE_END -} // namespace absl -#else // Use the cyclecounter-based implementation below. - -// Allows override by test. -#ifndef GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW -#define GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW() \ - ::absl::time_internal::UnscaledCycleClockWrapperForGetCurrentTime::Now() -#endif - -// The following counters are used only by the test code. -static int64_t stats_initializations; -static int64_t stats_reinitializations; -static int64_t stats_calibrations; -static int64_t stats_slow_paths; -static int64_t stats_fast_slow_paths; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -// This is a friend wrapper around UnscaledCycleClock::Now() -// (needed to access UnscaledCycleClock). -class UnscaledCycleClockWrapperForGetCurrentTime { - public: - static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); } -}; -} // namespace time_internal - -// 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 -// clock. Increment a word on each write acquisition, using the low-order bit -// as a spinlock; the word is the high word of the "clock". Readers read the -// high word, then all other data, then the high word again, and repeat the -// read if the reads of the high words yields different answers, or an odd -// value (either case suggests possible interference from a writer). -// Here we use a spinlock to ensure only one writer at a time, rather than -// spinning on the bottom bit of the word to benefit from SpinLock -// spin-delay tuning. - -// Acquire seqlock (*seq) and return the value to be written to unlock. -static inline uint64_t SeqAcquire(std::atomic<uint64_t> *seq) { - uint64_t x = seq->fetch_add(1, std::memory_order_relaxed); - - // We put a release fence between update to *seq and writes to shared data. - // Thus all stores to shared data are effectively release operations and - // update to *seq 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); - - return x + 2; // original word plus 2 -} - -// Release seqlock (*seq) by writing x to it---a value previously returned by -// SeqAcquire. -static inline void SeqRelease(std::atomic<uint64_t> *seq, uint64_t x) { - // The unlock store to *seq must have release ordering so that all - // updates to shared data must finish before this store. - seq->store(x, std::memory_order_release); // release lock for readers -} - -// --------------------------------------------------------------------- - -// "nsscaled" is unit of time equal to a (2**kScale)th of a nanosecond. -enum { kScale = 30 }; - -// The minimum interval between samples of the time base. -// We pick enough time to amortize the cost of the sample, -// to get a reasonably accurate cycle counter rate reading, -// and not so much that calculations will overflow 64-bits. -static const uint64_t kMinNSBetweenSamples = 2000 << 20; - -// We require that kMinNSBetweenSamples shifted by kScale -// have at least a bit left over for 64-bit calculations. -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. -ABSL_CONST_INIT static absl::base_internal::SpinLock lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); -ABSL_CONST_INIT static std::atomic<uint64_t> seq(0); - -// data from a sample of the kernel's time value -struct TimeSampleAtomic { - std::atomic<uint64_t> raw_ns; // raw kernel time - std::atomic<uint64_t> base_ns; // our estimate of time - std::atomic<uint64_t> base_cycles; // cycle counter reading - std::atomic<uint64_t> nsscaled_per_cycle; // cycle period - // 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; -}; -// Same again, but with non-atomic types -struct TimeSample { - uint64_t raw_ns; // raw kernel time - uint64_t base_ns; // our estimate of time - uint64_t base_cycles; // cycle counter reading - uint64_t nsscaled_per_cycle; // cycle period - uint64_t min_cycles_per_sample; // approx cycles before next sample -}; - -static struct TimeSampleAtomic last_sample; // the last sample; under seq - -static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD; - -// Read the contents of *atomic into *sample. -// Each field is read atomically, but to maintain atomicity between fields, -// the access must be done under a lock. -static void ReadTimeSampleAtomic(const struct TimeSampleAtomic *atomic, - struct TimeSample *sample) { - sample->base_ns = atomic->base_ns.load(std::memory_order_relaxed); - sample->base_cycles = atomic->base_cycles.load(std::memory_order_relaxed); - sample->nsscaled_per_cycle = - atomic->nsscaled_per_cycle.load(std::memory_order_relaxed); - sample->min_cycles_per_sample = - atomic->min_cycles_per_sample.load(std::memory_order_relaxed); - sample->raw_ns = atomic->raw_ns.load(std::memory_order_relaxed); -} - -// Public routine. -// Algorithm: We wish to compute real time from a cycle counter. In normal -// operation, we construct a piecewise linear approximation to the kernel time -// source, using the cycle counter value. The start of each line segment is at -// the same point as the end of the last, but may have a different slope (that -// is, a different idea of the cycle counter frequency). Every couple of -// seconds, the kernel time source is sampled and compared with the current -// approximation. A new slope is chosen that, if followed for another couple -// of seconds, will correct the error at the current position. The information -// for a sample is in the "last_sample" struct. The linear approximation is -// estimated_time = last_sample.base_ns + -// last_sample.ns_per_cycle * (counter_reading - last_sample.base_cycles) -// (ns_per_cycle is actually stored in different units and scaled, to avoid -// overflow). The base_ns of the next linear approximation is the -// estimated_time using the last approximation; the base_cycles is the cycle -// counter value at that time; the ns_per_cycle is the number of ns per cycle -// measured since the last sample, but adjusted so that most of the difference -// between the estimated_time and the kernel time will be corrected by the -// estimated time to the next sample. In normal operation, this algorithm -// relies on: -// - the cycle counter and kernel time rates not changing a lot in a few -// seconds. -// - the client calling into the code often compared to a couple of seconds, so -// the time to the next correction can be estimated. -// Any time ns_per_cycle is not known, a major error is detected, or the -// assumption about frequent calls is violated, the implementation returns the -// kernel time. It records sufficient data that a linear approximation can -// resume a little later. - -int64_t GetCurrentTimeNanos() { - // read the data from the "last_sample" struct (but don't need raw_ns yet) - // The reads of "seq" and test of the values emulate a reader lock. - uint64_t base_ns; - uint64_t base_cycles; - uint64_t nsscaled_per_cycle; - uint64_t min_cycles_per_sample; - uint64_t seq_read0; - uint64_t seq_read1; - - // If we have enough information to interpolate, the value returned will be - // derived from this cycleclock-derived time estimate. On some platforms - // (POWER) the function to retrieve this value has enough complexity to - // contribute to register pressure - reading it early before initializing - // the other pieces of the calculation minimizes spill/restore instructions, - // minimizing icache cost. - uint64_t now_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW(); - - // Acquire pairs with the barrier in SeqRelease - if this load sees that - // store, the shared-data reads necessarily see that SeqRelease's updates - // to the same shared data. - seq_read0 = seq.load(std::memory_order_acquire); - - 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 = - 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 - // shared data are effectively acquiring. - std::atomic_thread_fence(std::memory_order_acquire); - - // The shared-data reads are effectively acquire ordered, and the - // shared-data writes are effectively release ordered. Therefore if our - // shared-data reads see any of a particular update's shared-data writes, - // seq_read1 is guaranteed to see that update's SeqAcquire. - seq_read1 = seq.load(std::memory_order_relaxed); - - // 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 - // only when min_cycles_per_sample is non-zero, which happens when we get an - // estimate for the cycle time. The predicate will fail if now_cycles < - // base_cycles, or if some other thread is in the slow path. - // - // Since we now read now_cycles before base_ns, it is possible for now_cycles - // to be less than base_cycles (if we were interrupted between those loads and - // last_sample was updated). This is harmless, because delta_cycles will wrap - // and report a time much much bigger than min_cycles_per_sample. In that case - // we will take the slow path. - uint64_t delta_cycles = now_cycles - base_cycles; - if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 && - delta_cycles < min_cycles_per_sample) { - return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale); - } - return GetCurrentTimeNanosSlowPath(); -} - -// Return (a << kScale)/b. -// Zero is returned if b==0. Scaling is performed internally to -// preserve precision without overflow. -static uint64_t SafeDivideAndScale(uint64_t a, uint64_t b) { - // Find maximum safe_shift so that - // 0 <= safe_shift <= kScale and (a << safe_shift) does not overflow. - int safe_shift = kScale; - while (((a << safe_shift) >> safe_shift) != a) { - safe_shift--; - } - uint64_t scaled_b = b >> (kScale - safe_shift); - uint64_t quotient = 0; - if (scaled_b != 0) { - quotient = (a << safe_shift) / scaled_b; - } - return quotient; -} - -static uint64_t UpdateLastSample( - uint64_t now_cycles, uint64_t now_ns, uint64_t delta_cycles, - const struct TimeSample *sample) ABSL_ATTRIBUTE_COLD; - -// The slow path of GetCurrentTimeNanos(). This is taken while gathering -// initial samples, when enough time has elapsed since the last sample, and if -// any other thread is writing to last_sample. -// -// Manually mark this 'noinline' to minimize stack frame size of the fast -// path. Without this, sometimes a compiler may inline this big block of code -// into the fast path. That causes lots of register spills and reloads that -// are unnecessary unless the slow path is taken. -// -// TODO(absl-team): Remove this attribute when our compiler is smart enough -// to do the right thing. -ABSL_ATTRIBUTE_NOINLINE -static int64_t GetCurrentTimeNanosSlowPath() 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. - lock.Lock(); - - // Sample the kernel time base. This is the definition of - // "now" if we take the slow path. - static uint64_t last_now_cycles; // protected by lock - uint64_t now_cycles; - uint64_t now_ns = GetCurrentTimeNanosFromKernel(last_now_cycles, &now_cycles); - last_now_cycles = now_cycles; - - uint64_t estimated_base_ns; - - // ---------- - // Read the "last_sample" values again; this time holding the write lock. - struct TimeSample sample; - ReadTimeSampleAtomic(&last_sample, &sample); - - // ---------- - // Try running the fast path again; another thread may have updated the - // sample between our run of the fast path and the sample we just read. - uint64_t delta_cycles = now_cycles - sample.base_cycles; - if (delta_cycles < sample.min_cycles_per_sample) { - // Another thread updated the sample. This path does not take the seqlock - // so that blocked readers can make progress without blocking new readers. - estimated_base_ns = sample.base_ns + - ((delta_cycles * sample.nsscaled_per_cycle) >> kScale); - stats_fast_slow_paths++; - } else { - estimated_base_ns = - UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample); - } - - lock.Unlock(); - - return estimated_base_ns; -} - -// Main part of the algorithm. Locks out readers, updates the approximation -// using the new sample from the kernel, and stores the result in last_sample -// for readers. Returns the new estimated time. -static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, - uint64_t delta_cycles, - const struct TimeSample *sample) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock) { - uint64_t estimated_base_ns = now_ns; - 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. - // Errors in the rate of the source clock can be multiplied by the ratio - // between this limit and kMinNSBetweenSamples. - if (sample->raw_ns == 0 || // no recent sample, or clock went backwards - sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns || - now_ns < sample->raw_ns || now_cycles < sample->base_cycles) { - // record this sample, and forget any previously known slope. - last_sample.raw_ns.store(now_ns, std::memory_order_relaxed); - last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed); - last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed); - last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed); - last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed); - stats_initializations++; - } 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. - if (sample->nsscaled_per_cycle != 0) { // Have a cycle time estimate. - // Compute time from counter reading, but avoiding overflow - // delta_cycles may be larger than on the fast path. - uint64_t estimated_scaled_ns; - int s = -1; - do { - s++; - estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle; - } while (estimated_scaled_ns / sample->nsscaled_per_cycle != - (delta_cycles >> s)); - estimated_base_ns = sample->base_ns + - (estimated_scaled_ns >> (kScale - s)); - } - - // Compute the assumed cycle time kMinNSBetweenSamples ns into the future - // assuming the cycle counter rate stays the same as the last interval. - uint64_t ns = now_ns - sample->raw_ns; - uint64_t measured_nsscaled_per_cycle = SafeDivideAndScale(ns, delta_cycles); - - uint64_t assumed_next_sample_delta_cycles = - SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle); - - int64_t diff_ns = now_ns - estimated_base_ns; // estimate low by this much - - // We want to set nsscaled_per_cycle so that our estimate of the ns time - // at the assumed cycle time is the assumed ns time. - // That is, we want to set nsscaled_per_cycle so: - // kMinNSBetweenSamples + diff_ns == - // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale - // But we wish to damp oscillations, so instead correct only most - // of our current error, by solving: - // kMinNSBetweenSamples + diff_ns - (diff_ns / 16) == - // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale - ns = kMinNSBetweenSamples + diff_ns - (diff_ns / 16); - uint64_t new_nsscaled_per_cycle = - SafeDivideAndScale(ns, assumed_next_sample_delta_cycles); - if (new_nsscaled_per_cycle != 0 && - diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) { - // record the cycle time measurement - last_sample.nsscaled_per_cycle.store( - new_nsscaled_per_cycle, std::memory_order_relaxed); - uint64_t new_min_cycles_per_sample = - SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle); - last_sample.min_cycles_per_sample.store( - new_min_cycles_per_sample, std::memory_order_relaxed); - stats_calibrations++; - } else { // something went wrong; forget the slope - last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed); - last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed); - estimated_base_ns = now_ns; - stats_reinitializations++; - } - last_sample.raw_ns.store(now_ns, std::memory_order_relaxed); - last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed); - last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed); - } else { - // have a sample, but no slope; waiting for enough time for a calibration - stats_slow_paths++; - } - - SeqRelease(&seq, lock_value); // release the readers - - return estimated_base_ns; -} -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -// Returns the maximum duration that SleepOnce() can sleep for. -constexpr absl::Duration MaxSleep() { -#ifdef _WIN32 - // Windows Sleep() takes unsigned long argument in milliseconds. - return absl::Milliseconds( - std::numeric_limits<unsigned long>::max()); // NOLINT(runtime/int) -#else - return absl::Seconds(std::numeric_limits<time_t>::max()); -#endif -} - -// Sleeps for the given duration. -// REQUIRES: to_sleep <= MaxSleep(). -void SleepOnce(absl::Duration to_sleep) { -#ifdef _WIN32 - Sleep(to_sleep / absl::Milliseconds(1)); -#else - struct timespec sleep_time = absl::ToTimespec(to_sleep); - while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) { - // Ignore signals and wait for the full interval to elapse. - } -#endif -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -extern "C" { - -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); - duration -= to_sleep; - } -} - -} // extern "C" diff --git a/third_party/abseil_cpp/absl/time/clock.h b/third_party/abseil_cpp/absl/time/clock.h deleted file mode 100644 index 27764a922d5e..000000000000 --- a/third_party/abseil_cpp/absl/time/clock.h +++ /dev/null @@ -1,74 +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. -// -// ----------------------------------------------------------------------------- -// File: clock.h -// ----------------------------------------------------------------------------- -// -// This header file contains utility functions for working with the system-wide -// realtime clock. For descriptions of the main time abstractions used within -// this header file, consult the time.h header file. -#ifndef ABSL_TIME_CLOCK_H_ -#define ABSL_TIME_CLOCK_H_ - -#include "absl/base/macros.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Now() -// -// Returns the current time, expressed as an `absl::Time` absolute time value. -absl::Time Now(); - -// GetCurrentTimeNanos() -// -// Returns the current time, expressed as a count of nanoseconds since the Unix -// Epoch (https://en.wikipedia.org/wiki/Unix_time). Prefer `absl::Now()` instead -// for all but the most performance-sensitive cases (i.e. when you are calling -// this function hundreds of thousands of times per second). -int64_t GetCurrentTimeNanos(); - -// SleepFor() -// -// Sleeps for the specified duration, expressed as an `absl::Duration`. -// -// Notes: -// * Signal interruptions will not reduce the sleep duration. -// * Returns immediately when passed a nonpositive duration. -void SleepFor(absl::Duration duration); - -ABSL_NAMESPACE_END -} // namespace absl - -// ----------------------------------------------------------------------------- -// Implementation Details -// ----------------------------------------------------------------------------- - -// In some build configurations we pass --detect-odr-violations to the -// gold linker. This causes it to flag weak symbol overrides as ODR -// violations. Because ODR only applies to C++ and not C, -// --detect-odr-violations ignores symbols not mangled with C++ names. -// By changing our extension points to be extern "C", we dodge this -// check. -extern "C" { -void AbslInternalSleepFor(absl::Duration duration); -} // extern "C" - -inline void absl::SleepFor(absl::Duration duration) { - AbslInternalSleepFor(duration); -} - -#endif // ABSL_TIME_CLOCK_H_ diff --git a/third_party/abseil_cpp/absl/time/clock_benchmark.cc b/third_party/abseil_cpp/absl/time/clock_benchmark.cc deleted file mode 100644 index c5c795ecbd23..000000000000 --- a/third_party/abseil_cpp/absl/time/clock_benchmark.cc +++ /dev/null @@ -1,74 +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/time/clock.h" - -#if !defined(_WIN32) -#include <sys/time.h> -#else -#include <winsock2.h> -#endif // _WIN32 -#include <cstdio> - -#include "absl/base/internal/cycleclock.h" -#include "benchmark/benchmark.h" - -namespace { - -void BM_Clock_Now_AbslTime(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Now()); - } -} -BENCHMARK(BM_Clock_Now_AbslTime); - -void BM_Clock_Now_GetCurrentTimeNanos(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::GetCurrentTimeNanos()); - } -} -BENCHMARK(BM_Clock_Now_GetCurrentTimeNanos); - -void BM_Clock_Now_AbslTime_ToUnixNanos(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToUnixNanos(absl::Now())); - } -} -BENCHMARK(BM_Clock_Now_AbslTime_ToUnixNanos); - -void BM_Clock_Now_CycleClock(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::base_internal::CycleClock::Now()); - } -} -BENCHMARK(BM_Clock_Now_CycleClock); - -#if !defined(_WIN32) -static void BM_Clock_Now_gettimeofday(benchmark::State& state) { - struct timeval tv; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(gettimeofday(&tv, nullptr)); - } -} -BENCHMARK(BM_Clock_Now_gettimeofday); - -static void BM_Clock_Now_clock_gettime(benchmark::State& state) { - struct timespec ts; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(clock_gettime(CLOCK_REALTIME, &ts)); - } -} -BENCHMARK(BM_Clock_Now_clock_gettime); -#endif // _WIN32 - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/clock_test.cc b/third_party/abseil_cpp/absl/time/clock_test.cc deleted file mode 100644 index 4bcfc6bc7272..000000000000 --- a/third_party/abseil_cpp/absl/time/clock_test.cc +++ /dev/null @@ -1,118 +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/time/clock.h" - -#include "absl/base/config.h" -#if defined(ABSL_HAVE_ALARM) -#include <signal.h> -#include <unistd.h> -#elif defined(__linux__) || defined(__APPLE__) -#error all known Linux and Apple targets have alarm -#endif - -#include "gtest/gtest.h" -#include "absl/time/time.h" - -namespace { - -TEST(Time, Now) { - const absl::Time before = absl::FromUnixNanos(absl::GetCurrentTimeNanos()); - const absl::Time now = absl::Now(); - const absl::Time after = absl::FromUnixNanos(absl::GetCurrentTimeNanos()); - EXPECT_GE(now, before); - EXPECT_GE(after, now); -} - -enum class AlarmPolicy { kWithoutAlarm, kWithAlarm }; - -#if defined(ABSL_HAVE_ALARM) -bool alarm_handler_invoked = false; - -void AlarmHandler(int signo) { - ASSERT_EQ(signo, SIGALRM); - alarm_handler_invoked = true; -} -#endif - -// Does SleepFor(d) take between lower_bound and upper_bound at least -// once between now and (now + timeout)? If requested (and supported), -// add an alarm for the middle of the sleep period and expect it to fire. -bool SleepForBounded(absl::Duration d, absl::Duration lower_bound, - absl::Duration upper_bound, absl::Duration timeout, - AlarmPolicy alarm_policy, int* attempts) { - const absl::Time deadline = absl::Now() + timeout; - while (absl::Now() < deadline) { -#if defined(ABSL_HAVE_ALARM) - sig_t old_alarm = SIG_DFL; - if (alarm_policy == AlarmPolicy::kWithAlarm) { - alarm_handler_invoked = false; - old_alarm = signal(SIGALRM, AlarmHandler); - alarm(absl::ToInt64Seconds(d / 2)); - } -#else - EXPECT_EQ(alarm_policy, AlarmPolicy::kWithoutAlarm); -#endif - ++*attempts; - absl::Time start = absl::Now(); - absl::SleepFor(d); - absl::Duration actual = absl::Now() - start; -#if defined(ABSL_HAVE_ALARM) - if (alarm_policy == AlarmPolicy::kWithAlarm) { - signal(SIGALRM, old_alarm); - if (!alarm_handler_invoked) continue; - } -#endif - if (lower_bound <= actual && actual <= upper_bound) { - return true; // yes, the SleepFor() was correctly bounded - } - } - return false; -} - -testing::AssertionResult AssertSleepForBounded(absl::Duration d, - absl::Duration early, - absl::Duration late, - absl::Duration timeout, - AlarmPolicy alarm_policy) { - const absl::Duration lower_bound = d - early; - const absl::Duration upper_bound = d + late; - int attempts = 0; - if (SleepForBounded(d, lower_bound, upper_bound, timeout, alarm_policy, - &attempts)) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "SleepFor(" << d << ") did not return within [" << lower_bound - << ":" << upper_bound << "] in " << attempts << " attempt" - << (attempts == 1 ? "" : "s") << " over " << timeout - << (alarm_policy == AlarmPolicy::kWithAlarm ? " with" : " without") - << " an alarm"; -} - -// Tests that SleepFor() returns neither too early nor too late. -TEST(SleepFor, Bounded) { - const absl::Duration d = absl::Milliseconds(2500); - const absl::Duration early = absl::Milliseconds(100); - const absl::Duration late = absl::Milliseconds(300); - const absl::Duration timeout = 48 * d; - EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout, - AlarmPolicy::kWithoutAlarm)); -#if defined(ABSL_HAVE_ALARM) - EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout, - AlarmPolicy::kWithAlarm)); -#endif -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/duration.cc b/third_party/abseil_cpp/absl/time/duration.cc deleted file mode 100644 index 4443109a5121..000000000000 --- a/third_party/abseil_cpp/absl/time/duration.cc +++ /dev/null @@ -1,954 +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. - -// The implementation of the absl::Duration class, which is declared in -// //absl/time.h. This class behaves like a numeric type; it has no public -// methods and is used only through the operators defined here. -// -// Implementation notes: -// -// An absl::Duration is represented as -// -// rep_hi_ : (int64_t) Whole seconds -// rep_lo_ : (uint32_t) Fractions of a second -// -// The seconds value (rep_hi_) may be positive or negative as appropriate. -// The fractional seconds (rep_lo_) is always a positive offset from rep_hi_. -// The API for Duration guarantees at least nanosecond resolution, which -// means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds. -// However, to utilize more of the available 32 bits of space in rep_lo_, -// we instead store quarters of a nanosecond in rep_lo_ resulting in a max -// value of 4B - 1. This allows us to correctly handle calculations like -// 0.5 nanos + 0.5 nanos = 1 nano. The following example shows the actual -// Duration rep using quarters of a nanosecond. -// -// 2.5 sec = {rep_hi_=2, rep_lo_=2000000000} // lo = 4 * 500000000 -// -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000} -// -// Infinite durations are represented as Durations with the rep_lo_ field set -// to all 1s. -// -// +InfiniteDuration: -// rep_hi_ : kint64max -// rep_lo_ : ~0U -// -// -InfiniteDuration: -// rep_hi_ : kint64min -// rep_lo_ : ~0U -// -// Arithmetic overflows/underflows to +/- infinity and saturates. - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <algorithm> -#include <cassert> -#include <cctype> -#include <cerrno> -#include <cmath> -#include <cstdint> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <functional> -#include <limits> -#include <string> - -#include "absl/base/casts.h" -#include "absl/base/macros.h" -#include "absl/numeric/int128.h" -#include "absl/strings/string_view.h" -#include "absl/strings/strip.h" -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -using time_internal::kTicksPerNanosecond; -using time_internal::kTicksPerSecond; - -constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); -constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); - -// Can't use std::isinfinite() because it doesn't exist on windows. -inline bool IsFinite(double d) { - if (std::isnan(d)) return false; - return d != std::numeric_limits<double>::infinity() && - d != -std::numeric_limits<double>::infinity(); -} - -inline bool IsValidDivisor(double d) { - if (std::isnan(d)) return false; - return d != 0.0; -} - -// Can't use std::round() because it is only available in C++11. -// Note that we ignore the possibility of floating-point over/underflow. -template <typename Double> -inline double Round(Double d) { - return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5); -} - -// *sec may be positive or negative. *ticks must be in the range -// -kTicksPerSecond < *ticks < kTicksPerSecond. If *ticks is negative it -// will be normalized to a positive value by adjusting *sec accordingly. -inline void NormalizeTicks(int64_t* sec, int64_t* ticks) { - if (*ticks < 0) { - --*sec; - *ticks += kTicksPerSecond; - } -} - -// Makes a uint128 from the absolute value of the given scalar. -inline uint128 MakeU128(int64_t a) { - uint128 u128 = 0; - if (a < 0) { - ++u128; - ++a; // Makes it safe to negate 'a' - a = -a; - } - u128 += static_cast<uint64_t>(a); - return u128; -} - -// Makes a uint128 count of ticks out of the absolute value of the Duration. -inline uint128 MakeU128Ticks(Duration d) { - int64_t rep_hi = time_internal::GetRepHi(d); - uint32_t rep_lo = time_internal::GetRepLo(d); - if (rep_hi < 0) { - ++rep_hi; - rep_hi = -rep_hi; - rep_lo = kTicksPerSecond - rep_lo; - } - uint128 u128 = static_cast<uint64_t>(rep_hi); - u128 *= static_cast<uint64_t>(kTicksPerSecond); - u128 += rep_lo; - return u128; -} - -// Breaks a uint128 of ticks into a Duration. -inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) { - int64_t rep_hi; - uint32_t rep_lo; - const uint64_t h64 = Uint128High64(u128); - const uint64_t l64 = Uint128Low64(u128); - if (h64 == 0) { // fastpath - const uint64_t hi = l64 / kTicksPerSecond; - rep_hi = static_cast<int64_t>(hi); - rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond); - } else { - // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond). - // Any positive tick count whose high 64 bits are >= kMaxRepHi64 - // is not representable as a Duration. A negative tick count can - // have its high 64 bits == kMaxRepHi64 but only when the low 64 - // bits are all zero, otherwise it is not representable either. - const uint64_t kMaxRepHi64 = 0x77359400UL; - if (h64 >= kMaxRepHi64) { - if (is_neg && h64 == kMaxRepHi64 && l64 == 0) { - // Avoid trying to represent -kint64min below. - return time_internal::MakeDuration(kint64min); - } - return is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond); - const uint128 hi = u128 / kTicksPerSecond128; - rep_hi = static_cast<int64_t>(Uint128Low64(hi)); - rep_lo = - static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128)); - } - if (is_neg) { - rep_hi = -rep_hi; - if (rep_lo != 0) { - --rep_hi; - rep_lo = kTicksPerSecond - rep_lo; - } - } - return time_internal::MakeDuration(rep_hi, rep_lo); -} - -// Convert between int64_t and uint64_t, preserving representation. This -// allows us to do arithmetic in the unsigned domain, where overflow has -// well-defined behavior. See operator+=() and operator-=(). -// -// C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef -// name intN_t designates a signed integer type with width N, no padding -// bits, and a two's complement representation." So, we can convert to -// and from the corresponding uint64_t value using a bit cast. -inline uint64_t EncodeTwosComp(int64_t v) { - return absl::bit_cast<uint64_t>(v); -} -inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); } - -// Note: The overflow detection in this function is done using greater/less *or -// equal* because kint64max/min is too large to be represented exactly in a -// double (which only has 53 bits of precision). In order to avoid assigning to -// rep->hi a double value that is too large for an int64_t (and therefore is -// undefined), we must consider computations that equal kint64max/min as a -// double as overflow cases. -inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) { - double c = a_hi + b_hi; - if (c >= static_cast<double>(kint64max)) { - *d = InfiniteDuration(); - return false; - } - if (c <= static_cast<double>(kint64min)) { - *d = -InfiniteDuration(); - return false; - } - *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d)); - return true; -} - -// A functor that's similar to std::multiplies<T>, except this returns the max -// T value instead of overflowing. This is only defined for uint128. -template <typename Ignored> -struct SafeMultiply { - uint128 operator()(uint128 a, uint128 b) const { - // b hi is always zero because it originated as an int64_t. - assert(Uint128High64(b) == 0); - // Fastpath to avoid the expensive overflow check with division. - if (Uint128High64(a) == 0) { - return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0) - ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b)) - : a * b; - } - return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b; - } -}; - -// Scales (i.e., multiplies or divides, depending on the Operation template) -// the Duration d by the int64_t r. -template <template <typename> class Operation> -inline Duration ScaleFixed(Duration d, int64_t r) { - const uint128 a = MakeU128Ticks(d); - const uint128 b = MakeU128(r); - const uint128 q = Operation<uint128>()(a, b); - const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0); - return MakeDurationFromU128(q, is_neg); -} - -// Scales (i.e., multiplies or divides, depending on the Operation template) -// the Duration d by the double r. -template <template <typename> class Operation> -inline Duration ScaleDouble(Duration d, double r) { - Operation<double> op; - double hi_doub = op(time_internal::GetRepHi(d), r); - double lo_doub = op(time_internal::GetRepLo(d), r); - - double hi_int = 0; - double hi_frac = std::modf(hi_doub, &hi_int); - - // Moves hi's fractional bits to lo. - lo_doub /= kTicksPerSecond; - lo_doub += hi_frac; - - double lo_int = 0; - double lo_frac = std::modf(lo_doub, &lo_int); - - // Rolls lo into hi if necessary. - int64_t lo64 = Round(lo_frac * kTicksPerSecond); - - Duration ans; - if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans; - int64_t hi64 = time_internal::GetRepHi(ans); - if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans; - hi64 = time_internal::GetRepHi(ans); - lo64 %= kTicksPerSecond; - NormalizeTicks(&hi64, &lo64); - return time_internal::MakeDuration(hi64, lo64); -} - -// Tries to divide num by den as fast as possible by looking for common, easy -// cases. If the division was done, the quotient is in *q and the remainder is -// in *rem and true will be returned. -inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q, - Duration* rem) { - // Bail if num or den is an infinity. - if (time_internal::IsInfiniteDuration(num) || - time_internal::IsInfiniteDuration(den)) - return false; - - int64_t num_hi = time_internal::GetRepHi(num); - uint32_t num_lo = time_internal::GetRepLo(num); - int64_t den_hi = time_internal::GetRepHi(den); - uint32_t den_lo = time_internal::GetRepLo(den); - - if (den_hi == 0 && den_lo == kTicksPerNanosecond) { - // Dividing by 1ns - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) { - *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond; - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) { - // Dividing by 100ns (common when converting to Universal time) - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) { - *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) { - // Dividing by 1us - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) { - *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) { - // Dividing by 1ms - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) { - *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi > 0 && den_lo == 0) { - // Dividing by positive multiple of 1s - if (num_hi >= 0) { - if (den_hi == 1) { - *q = num_hi; - *rem = time_internal::MakeDuration(0, num_lo); - return true; - } - *q = num_hi / den_hi; - *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo); - return true; - } - if (num_lo != 0) { - num_hi += 1; - } - int64_t quotient = num_hi / den_hi; - int64_t rem_sec = num_hi % den_hi; - if (rem_sec > 0) { - rem_sec -= den_hi; - quotient += 1; - } - if (num_lo != 0) { - rem_sec -= 1; - } - *q = quotient; - *rem = time_internal::MakeDuration(rem_sec, num_lo); - return true; - } - - return false; -} - -} // namespace - -namespace time_internal { - -// The 'satq' argument indicates whether the quotient should saturate at the -// bounds of int64_t. If it does saturate, the difference will spill over to -// 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) { - int64_t q = 0; - if (IDivFastPath(num, den, &q, rem)) { - return q; - } - - const bool num_neg = num < ZeroDuration(); - const bool den_neg = den < ZeroDuration(); - const bool quotient_neg = num_neg != den_neg; - - if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { - *rem = num_neg ? -InfiniteDuration() : InfiniteDuration(); - return quotient_neg ? kint64min : kint64max; - } - if (time_internal::IsInfiniteDuration(den)) { - *rem = num; - return 0; - } - - const uint128 a = MakeU128Ticks(num); - const uint128 b = MakeU128Ticks(den); - uint128 quotient128 = a / b; - - if (satq) { - // Limits the quotient to the range of int64_t. - if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) { - quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min)) - : uint128(static_cast<uint64_t>(kint64max)); - } - } - - const uint128 remainder128 = a - quotient128 * b; - *rem = MakeDurationFromU128(remainder128, num_neg); - - if (!quotient_neg || quotient128 == 0) { - return Uint128Low64(quotient128) & kint64max; - } - // The quotient needs to be negated, but we need to carefully handle - // quotient128s with the top bit on. - return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1; -} - -} // namespace time_internal - -// -// Additive operators. -// - -Duration& Duration::operator+=(Duration rhs) { - if (time_internal::IsInfiniteDuration(*this)) return *this; - if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs; - const int64_t orig_rep_hi = rep_hi_; - rep_hi_ = - DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_)); - if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) { - rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1); - rep_lo_ -= kTicksPerSecond; - } - rep_lo_ += rhs.rep_lo_; - if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) { - return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration(); - } - return *this; -} - -Duration& Duration::operator-=(Duration rhs) { - if (time_internal::IsInfiniteDuration(*this)) return *this; - if (time_internal::IsInfiniteDuration(rhs)) { - return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); - } - const int64_t orig_rep_hi = rep_hi_; - rep_hi_ = - DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_)); - if (rep_lo_ < rhs.rep_lo_) { - rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1); - rep_lo_ += kTicksPerSecond; - } - rep_lo_ -= rhs.rep_lo_; - if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) { - return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); - } - return *this; -} - -// -// Multiplicative operators. -// - -Duration& Duration::operator*=(int64_t r) { - if (time_internal::IsInfiniteDuration(*this)) { - const bool is_neg = (r < 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleFixed<SafeMultiply>(*this, r); -} - -Duration& Duration::operator*=(double r) { - if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { - const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleDouble<std::multiplies>(*this, r); -} - -Duration& Duration::operator/=(int64_t r) { - if (time_internal::IsInfiniteDuration(*this) || r == 0) { - const bool is_neg = (r < 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleFixed<std::divides>(*this, r); -} - -Duration& Duration::operator/=(double r) { - if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { - const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleDouble<std::divides>(*this, r); -} - -Duration& Duration::operator%=(Duration rhs) { - time_internal::IDivDuration(false, *this, rhs, this); - return *this; -} - -double FDivDuration(Duration num, Duration den) { - // Arithmetic with infinity is sticky. - if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { - return (num < ZeroDuration()) == (den < ZeroDuration()) - ? std::numeric_limits<double>::infinity() - : -std::numeric_limits<double>::infinity(); - } - if (time_internal::IsInfiniteDuration(den)) return 0.0; - - double a = - static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond + - time_internal::GetRepLo(num); - double b = - static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond + - time_internal::GetRepLo(den); - return a / b; -} - -// -// Trunc/Floor/Ceil. -// - -Duration Trunc(Duration d, Duration unit) { - return d - (d % unit); -} - -Duration Floor(const Duration d, const Duration unit) { - const absl::Duration td = Trunc(d, unit); - return td <= d ? td : td - AbsDuration(unit); -} - -Duration Ceil(const Duration d, const Duration unit) { - const absl::Duration td = Trunc(d, unit); - return td >= d ? td : td + AbsDuration(unit); -} - -// -// Factory functions. -// - -Duration DurationFromTimespec(timespec ts) { - if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) { - int64_t ticks = ts.tv_nsec * kTicksPerNanosecond; - return time_internal::MakeDuration(ts.tv_sec, ticks); - } - return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec); -} - -Duration DurationFromTimeval(timeval tv) { - if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) { - int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond; - return time_internal::MakeDuration(tv.tv_sec, ticks); - } - return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec); -} - -// -// Conversion to other duration types. -// - -int64_t ToInt64Nanoseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 33 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) + - (time_internal::GetRepLo(d) / kTicksPerNanosecond); - } - return d / Nanoseconds(1); -} -int64_t ToInt64Microseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 43 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000)); - } - return d / Microseconds(1); -} -int64_t ToInt64Milliseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 53 == 0) { - return (time_internal::GetRepHi(d) * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000)); - } - return d / Milliseconds(1); -} -int64_t ToInt64Seconds(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi; -} -int64_t ToInt64Minutes(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / 60; -} -int64_t ToInt64Hours(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / (60 * 60); -} - -double ToDoubleNanoseconds(Duration d) { - return FDivDuration(d, Nanoseconds(1)); -} -double ToDoubleMicroseconds(Duration d) { - return FDivDuration(d, Microseconds(1)); -} -double ToDoubleMilliseconds(Duration d) { - return FDivDuration(d, Milliseconds(1)); -} -double ToDoubleSeconds(Duration d) { - return FDivDuration(d, Seconds(1)); -} -double ToDoubleMinutes(Duration d) { - return FDivDuration(d, Minutes(1)); -} -double ToDoubleHours(Duration d) { - return FDivDuration(d, Hours(1)); -} - -timespec ToTimespec(Duration d) { - timespec ts; - if (!time_internal::IsInfiniteDuration(d)) { - int64_t rep_hi = time_internal::GetRepHi(d); - uint32_t rep_lo = time_internal::GetRepLo(d); - if (rep_hi < 0) { - // Tweak the fields so that unsigned division of rep_lo - // maps to truncation (towards zero) for the timespec. - rep_lo += kTicksPerNanosecond - 1; - if (rep_lo >= kTicksPerSecond) { - rep_hi += 1; - rep_lo -= kTicksPerSecond; - } - } - ts.tv_sec = rep_hi; - if (ts.tv_sec == rep_hi) { // no time_t narrowing - ts.tv_nsec = rep_lo / kTicksPerNanosecond; - return ts; - } - } - if (d >= ZeroDuration()) { - ts.tv_sec = std::numeric_limits<time_t>::max(); - ts.tv_nsec = 1000 * 1000 * 1000 - 1; - } else { - ts.tv_sec = std::numeric_limits<time_t>::min(); - ts.tv_nsec = 0; - } - return ts; -} - -timeval ToTimeval(Duration d) { - timeval tv; - timespec ts = ToTimespec(d); - if (ts.tv_sec < 0) { - // Tweak the fields so that positive division of tv_nsec - // maps to truncation (towards zero) for the timeval. - ts.tv_nsec += 1000 - 1; - if (ts.tv_nsec >= 1000 * 1000 * 1000) { - ts.tv_sec += 1; - ts.tv_nsec -= 1000 * 1000 * 1000; - } - } - tv.tv_sec = ts.tv_sec; - if (tv.tv_sec != ts.tv_sec) { // narrowing - if (ts.tv_sec < 0) { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); - tv.tv_usec = 0; - } else { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); - tv.tv_usec = 1000 * 1000 - 1; - } - return tv; - } - tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t - return tv; -} - -std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d); -} -std::chrono::microseconds ToChronoMicroseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::microseconds>(d); -} -std::chrono::milliseconds ToChronoMilliseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::milliseconds>(d); -} -std::chrono::seconds ToChronoSeconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::seconds>(d); -} -std::chrono::minutes ToChronoMinutes(Duration d) { - return time_internal::ToChronoDuration<std::chrono::minutes>(d); -} -std::chrono::hours ToChronoHours(Duration d) { - return time_internal::ToChronoDuration<std::chrono::hours>(d); -} - -// -// To/From string formatting. -// - -namespace { - -// Formats a positive 64-bit integer in the given field width. Note that -// it is up to the caller of Format64() to ensure that there is sufficient -// space before ep to hold the conversion. -char* Format64(char* ep, int width, int64_t v) { - do { - --width; - *--ep = '0' + (v % 10); // contiguous digits - } while (v /= 10); - while (--width >= 0) *--ep = '0'; // zero pad - return ep; -} - -// Helpers for FormatDuration() that format 'n' and append it to 'out' -// followed by the given 'unit'. If 'n' formats to "0", nothing is -// appended (not even the unit). - -// A type that encapsulates how to display a value of a particular unit. For -// values that are displayed with fractional parts, the precision indicates -// where to round the value. The precision varies with the display unit because -// a Duration can hold only quarters of a nanosecond, so displaying information -// beyond that is just noise. -// -// For example, a microsecond value of 42.00025xxxxx should not display beyond 5 -// fractional digits, because it is in the noise of what a Duration can -// represent. -struct DisplayUnit { - absl::string_view 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 - -void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) { - char buf[sizeof("2562047788015216")]; // hours in max duration - char* const ep = buf + sizeof(buf); - char* bp = Format64(ep, 0, n); - if (*bp != '0' || bp + 1 != ep) { - out->append(bp, ep - bp); - out->append(unit.abbr.data(), unit.abbr.size()); - } -} - -// Note: unit.prec is limited to double's digits10 value (typically 15) so it -// always fits in buf[]. -void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) { - constexpr int kBufferSize = std::numeric_limits<double>::digits10; - const int prec = std::min(kBufferSize, unit.prec); - char buf[kBufferSize]; // also large enough to hold integer part - char* ep = buf + sizeof(buf); - double d = 0; - int64_t frac_part = Round(std::modf(n, &d) * unit.pow10); - int64_t int_part = d; - if (int_part != 0 || frac_part != 0) { - char* bp = Format64(ep, 0, int_part); // always < 1000 - out->append(bp, ep - bp); - if (frac_part != 0) { - out->push_back('.'); - bp = Format64(ep, prec, frac_part); - while (ep[-1] == '0') --ep; - out->append(bp, ep - bp); - } - out->append(unit.abbr.data(), unit.abbr.size()); - } -} - -} // namespace - -// From Go's doc at https://golang.org/pkg/time/#Duration.String -// [FormatDuration] returns a string representing the duration in the -// form "72h3m0.5s". Leading zero units are omitted. As a special -// 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. -std::string FormatDuration(Duration d) { - const Duration min_duration = Seconds(kint64min); - if (d == min_duration) { - // Avoid needing to negate kint64min by directly returning what the - // following code should produce in that case. - return "-2562047788015215h30m8s"; - } - std::string s; - if (d < ZeroDuration()) { - s.append("-"); - d = -d; - } - if (d == InfiniteDuration()) { - s.append("inf"); - } else if (d < Seconds(1)) { - // Special case for durations with a magnitude < 1 second. The duration - // is printed as a fraction of a single unit, e.g., "1.2ms". - if (d < Microseconds(1)) { - AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano); - } else if (d < Milliseconds(1)) { - AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro); - } else { - AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli); - } - } else { - AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour); - AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin); - AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec); - } - if (s.empty() || s == "-") { - s = "0"; - } - return s; -} - -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, - 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) { - 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) { - const int d = **dpp - '0'; // contiguous digits - if (d < 0 || 10 <= d) break; - if (*frac_scale <= kint64max / 10) { - *frac_part *= 10; - *frac_part += d; - *frac_scale *= 10; - } - } - return !int_part_empty || *frac_scale != 1; -} - -// A helper for ParseDuration() that parses a leading unit designator (e.g., -// 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; - } - } -} - -} // namespace - -// From Go's doc at https://golang.org/pkg/time/#ParseDuration -// [ParseDuration] parses a duration string. A duration string is -// a possibly signed sequence of decimal numbers, each with optional -// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". -// Valid time units are "ns", "us" "ms", "s", "m", "h". -bool ParseDuration(absl::string_view dur_sv, Duration* d) { - int sign = 1; - if (absl::ConsumePrefix(&dur_sv, "-")) { - sign = -1; - } else { - absl::ConsumePrefix(&dur_sv, "+"); - } - if (dur_sv.empty()) return false; - - // Special case for a string of "0". - if (dur_sv == "0") { - *d = ZeroDuration(); - return true; - } - - if (dur_sv == "inf") { - *d = sign * InfiniteDuration(); - return true; - } - - const char* start = dur_sv.data(); - const char* end = start + dur_sv.size(); - - Duration dur; - while (start != end) { - 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)) { - return false; - } - if (int_part != 0) dur += sign * int_part * unit; - if (frac_part != 0) dur += sign * frac_part * unit / frac_scale; - } - *d = dur; - return true; -} - -bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) { - return ParseDuration(text, dst); -} - -std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); } -bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { - return ParseDuration(text, dst); -} - -std::string UnparseFlag(Duration d) { return FormatDuration(d); } - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/duration_benchmark.cc b/third_party/abseil_cpp/absl/time/duration_benchmark.cc deleted file mode 100644 index 83a836c8c8a2..000000000000 --- a/third_party/abseil_cpp/absl/time/duration_benchmark.cc +++ /dev/null @@ -1,428 +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 <cmath> -#include <cstddef> -#include <cstdint> -#include <ctime> -#include <string> - -#include "absl/base/attributes.h" -#include "absl/time/time.h" -#include "benchmark/benchmark.h" - -namespace { - -// -// Factory functions -// - -void BM_Duration_Factory_Nanoseconds(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Nanoseconds(i)); - i += 314159; - } -} -BENCHMARK(BM_Duration_Factory_Nanoseconds); - -void BM_Duration_Factory_Microseconds(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Microseconds(i)); - i += 314; - } -} -BENCHMARK(BM_Duration_Factory_Microseconds); - -void BM_Duration_Factory_Milliseconds(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Milliseconds(i)); - i += 1; - } -} -BENCHMARK(BM_Duration_Factory_Milliseconds); - -void BM_Duration_Factory_Seconds(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Seconds(i)); - i += 1; - } -} -BENCHMARK(BM_Duration_Factory_Seconds); - -void BM_Duration_Factory_Minutes(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Minutes(i)); - i += 1; - } -} -BENCHMARK(BM_Duration_Factory_Minutes); - -void BM_Duration_Factory_Hours(benchmark::State& state) { - int64_t i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Hours(i)); - i += 1; - } -} -BENCHMARK(BM_Duration_Factory_Hours); - -void BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) { - double d = 1; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Nanoseconds(d)); - d = d * 1.00000001 + 1; - } -} -BENCHMARK(BM_Duration_Factory_DoubleNanoseconds); - -void BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) { - double d = 1e-3; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Microseconds(d)); - d = d * 1.00000001 + 1e-3; - } -} -BENCHMARK(BM_Duration_Factory_DoubleMicroseconds); - -void BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) { - double d = 1e-6; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Milliseconds(d)); - d = d * 1.00000001 + 1e-6; - } -} -BENCHMARK(BM_Duration_Factory_DoubleMilliseconds); - -void BM_Duration_Factory_DoubleSeconds(benchmark::State& state) { - double d = 1e-9; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Seconds(d)); - d = d * 1.00000001 + 1e-9; - } -} -BENCHMARK(BM_Duration_Factory_DoubleSeconds); - -void BM_Duration_Factory_DoubleMinutes(benchmark::State& state) { - double d = 1e-9; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Minutes(d)); - d = d * 1.00000001 + 1e-9; - } -} -BENCHMARK(BM_Duration_Factory_DoubleMinutes); - -void BM_Duration_Factory_DoubleHours(benchmark::State& state) { - double d = 1e-9; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Hours(d)); - d = d * 1.00000001 + 1e-9; - } -} -BENCHMARK(BM_Duration_Factory_DoubleHours); - -// -// Arithmetic -// - -void BM_Duration_Addition(benchmark::State& state) { - absl::Duration d = absl::Nanoseconds(1); - absl::Duration step = absl::Milliseconds(1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(d += step); - } -} -BENCHMARK(BM_Duration_Addition); - -void BM_Duration_Subtraction(benchmark::State& state) { - absl::Duration d = absl::Seconds(std::numeric_limits<int64_t>::max()); - absl::Duration step = absl::Milliseconds(1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(d -= step); - } -} -BENCHMARK(BM_Duration_Subtraction); - -void BM_Duration_Multiplication_Fixed(benchmark::State& state) { - absl::Duration d = absl::Milliseconds(1); - absl::Duration s; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(s += d * (i + 1)); - ++i; - } -} -BENCHMARK(BM_Duration_Multiplication_Fixed); - -void BM_Duration_Multiplication_Double(benchmark::State& state) { - absl::Duration d = absl::Milliseconds(1); - absl::Duration s; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(s += d * (i + 1.0)); - ++i; - } -} -BENCHMARK(BM_Duration_Multiplication_Double); - -void BM_Duration_Division_Fixed(benchmark::State& state) { - absl::Duration d = absl::Seconds(1); - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(d /= i + 1); - ++i; - } -} -BENCHMARK(BM_Duration_Division_Fixed); - -void BM_Duration_Division_Double(benchmark::State& state) { - absl::Duration d = absl::Seconds(1); - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(d /= i + 1.0); - ++i; - } -} -BENCHMARK(BM_Duration_Division_Double); - -void BM_Duration_FDivDuration_Nanoseconds(benchmark::State& state) { - double d = 1; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize( - d += absl::FDivDuration(absl::Milliseconds(i), absl::Nanoseconds(1))); - ++i; - } -} -BENCHMARK(BM_Duration_FDivDuration_Nanoseconds); - -void BM_Duration_IDivDuration_Nanoseconds(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(a += - absl::IDivDuration(absl::Nanoseconds(i), - absl::Nanoseconds(1), &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Nanoseconds); - -void BM_Duration_IDivDuration_Microseconds(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Microseconds(i), - absl::Microseconds(1), - &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Microseconds); - -void BM_Duration_IDivDuration_Milliseconds(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Milliseconds(i), - absl::Milliseconds(1), - &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Milliseconds); - -void BM_Duration_IDivDuration_Seconds(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize( - a += absl::IDivDuration(absl::Seconds(i), absl::Seconds(1), &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Seconds); - -void BM_Duration_IDivDuration_Minutes(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize( - a += absl::IDivDuration(absl::Minutes(i), absl::Minutes(1), &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Minutes); - -void BM_Duration_IDivDuration_Hours(benchmark::State& state) { - int64_t a = 1; - absl::Duration ignore; - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize( - a += absl::IDivDuration(absl::Hours(i), absl::Hours(1), &ignore)); - ++i; - } -} -BENCHMARK(BM_Duration_IDivDuration_Hours); - -void BM_Duration_ToInt64Nanoseconds(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Nanoseconds); - -void BM_Duration_ToInt64Microseconds(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Microseconds(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Microseconds); - -void BM_Duration_ToInt64Milliseconds(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Milliseconds); - -void BM_Duration_ToInt64Seconds(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Seconds(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Seconds); - -void BM_Duration_ToInt64Minutes(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Minutes(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Minutes); - -void BM_Duration_ToInt64Hours(benchmark::State& state) { - absl::Duration d = absl::Seconds(100000); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToInt64Hours(d)); - } -} -BENCHMARK(BM_Duration_ToInt64Hours); - -// -// To/FromTimespec -// - -void BM_Duration_ToTimespec_AbslTime(benchmark::State& state) { - absl::Duration d = absl::Seconds(1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToTimespec(d)); - } -} -BENCHMARK(BM_Duration_ToTimespec_AbslTime); - -ABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) { - timespec ts; - ts.tv_sec = seconds; - ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000); - return ts; -} - -void BM_Duration_ToTimespec_Double(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(DoubleToTimespec(1.0)); - } -} -BENCHMARK(BM_Duration_ToTimespec_Double); - -void BM_Duration_FromTimespec_AbslTime(benchmark::State& state) { - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 0; - while (state.KeepRunning()) { - if (++ts.tv_nsec == 1000 * 1000 * 1000) { - ++ts.tv_sec; - ts.tv_nsec = 0; - } - benchmark::DoNotOptimize(absl::DurationFromTimespec(ts)); - } -} -BENCHMARK(BM_Duration_FromTimespec_AbslTime); - -ABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) { - return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000)); -} - -void BM_Duration_FromTimespec_Double(benchmark::State& state) { - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 0; - while (state.KeepRunning()) { - if (++ts.tv_nsec == 1000 * 1000 * 1000) { - ++ts.tv_sec; - ts.tv_nsec = 0; - } - benchmark::DoNotOptimize(TimespecToDouble(ts)); - } -} -BENCHMARK(BM_Duration_FromTimespec_Double); - -// -// String conversions -// - -const char* const kDurations[] = { - "0", // 0 - "123ns", // 1 - "1h2m3s", // 2 - "-2h3m4.005006007s", // 3 - "2562047788015215h30m7.99999999975s", // 4 -}; -const int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]); - -void BM_Duration_FormatDuration(benchmark::State& state) { - const std::string s = kDurations[state.range(0)]; - state.SetLabel(s); - absl::Duration d; - absl::ParseDuration(kDurations[state.range(0)], &d); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::FormatDuration(d)); - } -} -BENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1); - -void BM_Duration_ParseDuration(benchmark::State& state) { - const std::string s = kDurations[state.range(0)]; - state.SetLabel(s); - absl::Duration d; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ParseDuration(s, &d)); - } -} -BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1); - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/duration_test.cc b/third_party/abseil_cpp/absl/time/duration_test.cc deleted file mode 100644 index 4d85a2c4f455..000000000000 --- a/third_party/abseil_cpp/absl/time/duration_test.cc +++ /dev/null @@ -1,1808 +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. - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <chrono> // NOLINT(build/c++11) -#include <cmath> -#include <cstdint> -#include <ctime> -#include <iomanip> -#include <limits> -#include <random> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" - -namespace { - -constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); -constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); - -// Approximates the given number of years. This is only used to make some test -// code more readable. -absl::Duration ApproxYears(int64_t n) { return absl::Hours(n) * 365 * 24; } - -// A gMock matcher to match timespec values. Use this matcher like: -// 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; - *result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} "; - *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}"; - return false; -} - -// A gMock matcher to match timeval values. Use this matcher like: -// 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; - *result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} "; - *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}"; - return false; -} - -TEST(Duration, ConstExpr) { - constexpr absl::Duration d0 = absl::ZeroDuration(); - static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()"); - constexpr absl::Duration d1 = absl::Seconds(1); - static_assert(d1 == absl::Seconds(1), "Seconds(1)"); - static_assert(d1 != absl::ZeroDuration(), "Seconds(1)"); - constexpr absl::Duration d2 = absl::InfiniteDuration(); - static_assert(d2 == absl::InfiniteDuration(), "InfiniteDuration()"); - static_assert(d2 != absl::ZeroDuration(), "InfiniteDuration()"); -} - -TEST(Duration, ValueSemantics) { - // If this compiles, the test passes. - constexpr absl::Duration a; // Default construction - constexpr absl::Duration b = a; // Copy construction - constexpr absl::Duration c(b); // Copy construction (again) - - absl::Duration d; - d = c; // Assignment -} - -TEST(Duration, Factories) { - constexpr absl::Duration zero = absl::ZeroDuration(); - constexpr absl::Duration nano = absl::Nanoseconds(1); - constexpr absl::Duration micro = absl::Microseconds(1); - constexpr absl::Duration milli = absl::Milliseconds(1); - constexpr absl::Duration sec = absl::Seconds(1); - constexpr absl::Duration min = absl::Minutes(1); - constexpr absl::Duration hour = absl::Hours(1); - - EXPECT_EQ(zero, absl::Duration()); - EXPECT_EQ(zero, absl::Seconds(0)); - EXPECT_EQ(nano, absl::Nanoseconds(1)); - EXPECT_EQ(micro, absl::Nanoseconds(1000)); - EXPECT_EQ(milli, absl::Microseconds(1000)); - EXPECT_EQ(sec, absl::Milliseconds(1000)); - EXPECT_EQ(min, absl::Seconds(60)); - EXPECT_EQ(hour, absl::Minutes(60)); - - // Tests factory limits - const absl::Duration inf = absl::InfiniteDuration(); - - EXPECT_GT(inf, absl::Seconds(kint64max)); - EXPECT_LT(-inf, absl::Seconds(kint64min)); - EXPECT_LT(-inf, absl::Seconds(-kint64max)); - - EXPECT_EQ(inf, absl::Minutes(kint64max)); - EXPECT_EQ(-inf, absl::Minutes(kint64min)); - EXPECT_EQ(-inf, absl::Minutes(-kint64max)); - EXPECT_GT(inf, absl::Minutes(kint64max / 60)); - EXPECT_LT(-inf, absl::Minutes(kint64min / 60)); - EXPECT_LT(-inf, absl::Minutes(-kint64max / 60)); - - EXPECT_EQ(inf, absl::Hours(kint64max)); - EXPECT_EQ(-inf, absl::Hours(kint64min)); - EXPECT_EQ(-inf, absl::Hours(-kint64max)); - EXPECT_GT(inf, absl::Hours(kint64max / 3600)); - EXPECT_LT(-inf, absl::Hours(kint64min / 3600)); - EXPECT_LT(-inf, absl::Hours(-kint64max / 3600)); -} - -TEST(Duration, ToConversion) { -#define TEST_DURATION_CONVERSION(UNIT) \ - do { \ - const absl::Duration d = absl::UNIT(1.5); \ - constexpr absl::Duration z = absl::ZeroDuration(); \ - constexpr absl::Duration inf = absl::InfiniteDuration(); \ - constexpr double dbl_inf = std::numeric_limits<double>::infinity(); \ - EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf)); \ - EXPECT_EQ(-1, absl::ToInt64##UNIT(-d)); \ - EXPECT_EQ(0, absl::ToInt64##UNIT(z)); \ - EXPECT_EQ(1, absl::ToInt64##UNIT(d)); \ - EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf)); \ - EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf)); \ - EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d)); \ - EXPECT_EQ(0, absl::ToDouble##UNIT(z)); \ - EXPECT_EQ(1.5, absl::ToDouble##UNIT(d)); \ - EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf)); \ - } while (0) - - TEST_DURATION_CONVERSION(Nanoseconds); - TEST_DURATION_CONVERSION(Microseconds); - TEST_DURATION_CONVERSION(Milliseconds); - TEST_DURATION_CONVERSION(Seconds); - TEST_DURATION_CONVERSION(Minutes); - TEST_DURATION_CONVERSION(Hours); - -#undef TEST_DURATION_CONVERSION -} - -template <int64_t N> -void TestToConversion() { - constexpr absl::Duration nano = absl::Nanoseconds(N); - EXPECT_EQ(N, absl::ToInt64Nanoseconds(nano)); - EXPECT_EQ(0, absl::ToInt64Microseconds(nano)); - EXPECT_EQ(0, absl::ToInt64Milliseconds(nano)); - EXPECT_EQ(0, absl::ToInt64Seconds(nano)); - EXPECT_EQ(0, absl::ToInt64Minutes(nano)); - EXPECT_EQ(0, absl::ToInt64Hours(nano)); - const absl::Duration micro = absl::Microseconds(N); - EXPECT_EQ(N * 1000, absl::ToInt64Nanoseconds(micro)); - EXPECT_EQ(N, absl::ToInt64Microseconds(micro)); - EXPECT_EQ(0, absl::ToInt64Milliseconds(micro)); - EXPECT_EQ(0, absl::ToInt64Seconds(micro)); - EXPECT_EQ(0, absl::ToInt64Minutes(micro)); - EXPECT_EQ(0, absl::ToInt64Hours(micro)); - const absl::Duration milli = absl::Milliseconds(N); - EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Nanoseconds(milli)); - EXPECT_EQ(N * 1000, absl::ToInt64Microseconds(milli)); - EXPECT_EQ(N, absl::ToInt64Milliseconds(milli)); - EXPECT_EQ(0, absl::ToInt64Seconds(milli)); - EXPECT_EQ(0, absl::ToInt64Minutes(milli)); - EXPECT_EQ(0, absl::ToInt64Hours(milli)); - const absl::Duration sec = absl::Seconds(N); - EXPECT_EQ(N * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(sec)); - EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Microseconds(sec)); - EXPECT_EQ(N * 1000, absl::ToInt64Milliseconds(sec)); - EXPECT_EQ(N, absl::ToInt64Seconds(sec)); - EXPECT_EQ(0, absl::ToInt64Minutes(sec)); - EXPECT_EQ(0, absl::ToInt64Hours(sec)); - const absl::Duration min = absl::Minutes(N); - EXPECT_EQ(N * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(min)); - EXPECT_EQ(N * 60 * 1000 * 1000, absl::ToInt64Microseconds(min)); - EXPECT_EQ(N * 60 * 1000, absl::ToInt64Milliseconds(min)); - EXPECT_EQ(N * 60, absl::ToInt64Seconds(min)); - EXPECT_EQ(N, absl::ToInt64Minutes(min)); - EXPECT_EQ(0, absl::ToInt64Hours(min)); - const absl::Duration hour = absl::Hours(N); - EXPECT_EQ(N * 60 * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(hour)); - EXPECT_EQ(N * 60 * 60 * 1000 * 1000, absl::ToInt64Microseconds(hour)); - EXPECT_EQ(N * 60 * 60 * 1000, absl::ToInt64Milliseconds(hour)); - EXPECT_EQ(N * 60 * 60, absl::ToInt64Seconds(hour)); - EXPECT_EQ(N * 60, absl::ToInt64Minutes(hour)); - EXPECT_EQ(N, absl::ToInt64Hours(hour)); -} - -TEST(Duration, ToConversionDeprecated) { - TestToConversion<43>(); - TestToConversion<1>(); - TestToConversion<0>(); - TestToConversion<-1>(); - TestToConversion<-43>(); -} - -template <int64_t N> -void TestFromChronoBasicEquality() { - using std::chrono::nanoseconds; - using std::chrono::microseconds; - using std::chrono::milliseconds; - using std::chrono::seconds; - using std::chrono::minutes; - using std::chrono::hours; - - static_assert(absl::Nanoseconds(N) == absl::FromChrono(nanoseconds(N)), ""); - static_assert(absl::Microseconds(N) == absl::FromChrono(microseconds(N)), ""); - static_assert(absl::Milliseconds(N) == absl::FromChrono(milliseconds(N)), ""); - static_assert(absl::Seconds(N) == absl::FromChrono(seconds(N)), ""); - static_assert(absl::Minutes(N) == absl::FromChrono(minutes(N)), ""); - static_assert(absl::Hours(N) == absl::FromChrono(hours(N)), ""); -} - -TEST(Duration, FromChrono) { - TestFromChronoBasicEquality<-123>(); - TestFromChronoBasicEquality<-1>(); - TestFromChronoBasicEquality<0>(); - TestFromChronoBasicEquality<1>(); - TestFromChronoBasicEquality<123>(); - - // Minutes (might, depending on the platform) saturate at +inf. - const auto chrono_minutes_max = std::chrono::minutes::max(); - const auto minutes_max = absl::FromChrono(chrono_minutes_max); - const int64_t minutes_max_count = chrono_minutes_max.count(); - if (minutes_max_count > kint64max / 60) { - EXPECT_EQ(absl::InfiniteDuration(), minutes_max); - } else { - EXPECT_EQ(absl::Minutes(minutes_max_count), minutes_max); - } - - // Minutes (might, depending on the platform) saturate at -inf. - const auto chrono_minutes_min = std::chrono::minutes::min(); - const auto minutes_min = absl::FromChrono(chrono_minutes_min); - const int64_t minutes_min_count = chrono_minutes_min.count(); - if (minutes_min_count < kint64min / 60) { - EXPECT_EQ(-absl::InfiniteDuration(), minutes_min); - } else { - EXPECT_EQ(absl::Minutes(minutes_min_count), minutes_min); - } - - // Hours (might, depending on the platform) saturate at +inf. - const auto chrono_hours_max = std::chrono::hours::max(); - const auto hours_max = absl::FromChrono(chrono_hours_max); - const int64_t hours_max_count = chrono_hours_max.count(); - if (hours_max_count > kint64max / 3600) { - EXPECT_EQ(absl::InfiniteDuration(), hours_max); - } else { - EXPECT_EQ(absl::Hours(hours_max_count), hours_max); - } - - // Hours (might, depending on the platform) saturate at -inf. - const auto chrono_hours_min = std::chrono::hours::min(); - const auto hours_min = absl::FromChrono(chrono_hours_min); - const int64_t hours_min_count = chrono_hours_min.count(); - if (hours_min_count < kint64min / 3600) { - EXPECT_EQ(-absl::InfiniteDuration(), hours_min); - } else { - EXPECT_EQ(absl::Hours(hours_min_count), hours_min); - } -} - -template <int64_t N> -void TestToChrono() { - using std::chrono::nanoseconds; - using std::chrono::microseconds; - using std::chrono::milliseconds; - using std::chrono::seconds; - using std::chrono::minutes; - using std::chrono::hours; - - EXPECT_EQ(nanoseconds(N), absl::ToChronoNanoseconds(absl::Nanoseconds(N))); - EXPECT_EQ(microseconds(N), absl::ToChronoMicroseconds(absl::Microseconds(N))); - EXPECT_EQ(milliseconds(N), absl::ToChronoMilliseconds(absl::Milliseconds(N))); - EXPECT_EQ(seconds(N), absl::ToChronoSeconds(absl::Seconds(N))); - - constexpr auto absl_minutes = absl::Minutes(N); - auto chrono_minutes = minutes(N); - if (absl_minutes == -absl::InfiniteDuration()) { - chrono_minutes = minutes::min(); - } else if (absl_minutes == absl::InfiniteDuration()) { - chrono_minutes = minutes::max(); - } - EXPECT_EQ(chrono_minutes, absl::ToChronoMinutes(absl_minutes)); - - constexpr auto absl_hours = absl::Hours(N); - auto chrono_hours = hours(N); - if (absl_hours == -absl::InfiniteDuration()) { - chrono_hours = hours::min(); - } else if (absl_hours == absl::InfiniteDuration()) { - chrono_hours = hours::max(); - } - EXPECT_EQ(chrono_hours, absl::ToChronoHours(absl_hours)); -} - -TEST(Duration, ToChrono) { - using std::chrono::nanoseconds; - using std::chrono::microseconds; - using std::chrono::milliseconds; - using std::chrono::seconds; - using std::chrono::minutes; - using std::chrono::hours; - - TestToChrono<kint64min>(); - TestToChrono<-1>(); - TestToChrono<0>(); - TestToChrono<1>(); - TestToChrono<kint64max>(); - - // Verify truncation toward zero. - const auto tick = absl::Nanoseconds(1) / 4; - EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(tick)); - EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(-tick)); - EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(tick)); - EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(-tick)); - EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(tick)); - EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(-tick)); - EXPECT_EQ(seconds(0), absl::ToChronoSeconds(tick)); - EXPECT_EQ(seconds(0), absl::ToChronoSeconds(-tick)); - EXPECT_EQ(minutes(0), absl::ToChronoMinutes(tick)); - EXPECT_EQ(minutes(0), absl::ToChronoMinutes(-tick)); - EXPECT_EQ(hours(0), absl::ToChronoHours(tick)); - EXPECT_EQ(hours(0), absl::ToChronoHours(-tick)); - - // Verifies +/- infinity saturation at max/min. - constexpr auto inf = absl::InfiniteDuration(); - EXPECT_EQ(nanoseconds::min(), absl::ToChronoNanoseconds(-inf)); - EXPECT_EQ(nanoseconds::max(), absl::ToChronoNanoseconds(inf)); - EXPECT_EQ(microseconds::min(), absl::ToChronoMicroseconds(-inf)); - EXPECT_EQ(microseconds::max(), absl::ToChronoMicroseconds(inf)); - EXPECT_EQ(milliseconds::min(), absl::ToChronoMilliseconds(-inf)); - EXPECT_EQ(milliseconds::max(), absl::ToChronoMilliseconds(inf)); - EXPECT_EQ(seconds::min(), absl::ToChronoSeconds(-inf)); - EXPECT_EQ(seconds::max(), absl::ToChronoSeconds(inf)); - EXPECT_EQ(minutes::min(), absl::ToChronoMinutes(-inf)); - EXPECT_EQ(minutes::max(), absl::ToChronoMinutes(inf)); - EXPECT_EQ(hours::min(), absl::ToChronoHours(-inf)); - EXPECT_EQ(hours::max(), absl::ToChronoHours(inf)); -} - -TEST(Duration, FactoryOverloads) { - enum E { kOne = 1 }; -#define TEST_FACTORY_OVERLOADS(NAME) \ - EXPECT_EQ(1, NAME(kOne) / NAME(kOne)); \ - EXPECT_EQ(1, NAME(static_cast<int8_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<int16_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<int32_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<int64_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<uint8_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<uint16_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<uint32_t>(1)) / NAME(1)); \ - EXPECT_EQ(1, NAME(static_cast<uint64_t>(1)) / NAME(1)); \ - EXPECT_EQ(NAME(1) / 2, NAME(static_cast<float>(0.5))); \ - EXPECT_EQ(NAME(1) / 2, NAME(static_cast<double>(0.5))); \ - EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<float>(1.5)), NAME(1))); \ - EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<double>(1.5)), NAME(1))); - - TEST_FACTORY_OVERLOADS(absl::Nanoseconds); - TEST_FACTORY_OVERLOADS(absl::Microseconds); - TEST_FACTORY_OVERLOADS(absl::Milliseconds); - TEST_FACTORY_OVERLOADS(absl::Seconds); - TEST_FACTORY_OVERLOADS(absl::Minutes); - TEST_FACTORY_OVERLOADS(absl::Hours); - -#undef TEST_FACTORY_OVERLOADS - - EXPECT_EQ(absl::Milliseconds(1500), absl::Seconds(1.5)); - EXPECT_LT(absl::Nanoseconds(1), absl::Nanoseconds(1.5)); - EXPECT_GT(absl::Nanoseconds(2), absl::Nanoseconds(1.5)); - - const double dbl_inf = std::numeric_limits<double>::infinity(); - EXPECT_EQ(absl::InfiniteDuration(), absl::Nanoseconds(dbl_inf)); - EXPECT_EQ(absl::InfiniteDuration(), absl::Microseconds(dbl_inf)); - EXPECT_EQ(absl::InfiniteDuration(), absl::Milliseconds(dbl_inf)); - EXPECT_EQ(absl::InfiniteDuration(), absl::Seconds(dbl_inf)); - EXPECT_EQ(absl::InfiniteDuration(), absl::Minutes(dbl_inf)); - EXPECT_EQ(absl::InfiniteDuration(), absl::Hours(dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Nanoseconds(-dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Microseconds(-dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Milliseconds(-dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Seconds(-dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Minutes(-dbl_inf)); - EXPECT_EQ(-absl::InfiniteDuration(), absl::Hours(-dbl_inf)); -} - -TEST(Duration, InfinityExamples) { - // These examples are used in the documentation in time.h. They are - // written so that they can be copy-n-pasted easily. - - constexpr absl::Duration inf = absl::InfiniteDuration(); - constexpr absl::Duration d = absl::Seconds(1); // Any finite duration - - EXPECT_TRUE(inf == inf + inf); - EXPECT_TRUE(inf == inf + d); - EXPECT_TRUE(inf == inf - inf); - EXPECT_TRUE(-inf == d - inf); - - EXPECT_TRUE(inf == d * 1e100); - EXPECT_TRUE(0 == d / inf); // NOLINT(readability/check) - - // Division by zero returns infinity, or kint64min/MAX where necessary. - EXPECT_TRUE(inf == d / 0); - EXPECT_TRUE(kint64max == d / absl::ZeroDuration()); -} - -TEST(Duration, InfinityComparison) { - const absl::Duration inf = absl::InfiniteDuration(); - const absl::Duration any_dur = absl::Seconds(1); - - // Equality - EXPECT_EQ(inf, inf); - EXPECT_EQ(-inf, -inf); - EXPECT_NE(inf, -inf); - EXPECT_NE(any_dur, inf); - EXPECT_NE(any_dur, -inf); - - // Relational - EXPECT_GT(inf, any_dur); - EXPECT_LT(-inf, any_dur); - EXPECT_LT(-inf, inf); - EXPECT_GT(inf, -inf); -} - -TEST(Duration, InfinityAddition) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration sec_min = absl::Seconds(kint64min); - const absl::Duration any_dur = absl::Seconds(1); - const absl::Duration inf = absl::InfiniteDuration(); - - // Addition - EXPECT_EQ(inf, inf + inf); - EXPECT_EQ(inf, inf + -inf); - EXPECT_EQ(-inf, -inf + inf); - EXPECT_EQ(-inf, -inf + -inf); - - EXPECT_EQ(inf, inf + any_dur); - EXPECT_EQ(inf, any_dur + inf); - EXPECT_EQ(-inf, -inf + any_dur); - EXPECT_EQ(-inf, any_dur + -inf); - - // Interesting case - absl::Duration almost_inf = sec_max + absl::Nanoseconds(999999999); - EXPECT_GT(inf, almost_inf); - almost_inf += -absl::Nanoseconds(999999999); - EXPECT_GT(inf, almost_inf); - - // Addition overflow/underflow - EXPECT_EQ(inf, sec_max + absl::Seconds(1)); - EXPECT_EQ(inf, sec_max + sec_max); - EXPECT_EQ(-inf, sec_min + -absl::Seconds(1)); - EXPECT_EQ(-inf, sec_min + -sec_max); - - // For reference: IEEE 754 behavior - const double dbl_inf = std::numeric_limits<double>::infinity(); - EXPECT_TRUE(std::isinf(dbl_inf + dbl_inf)); - EXPECT_TRUE(std::isnan(dbl_inf + -dbl_inf)); // We return inf - EXPECT_TRUE(std::isnan(-dbl_inf + dbl_inf)); // We return inf - EXPECT_TRUE(std::isinf(-dbl_inf + -dbl_inf)); -} - -TEST(Duration, InfinitySubtraction) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration sec_min = absl::Seconds(kint64min); - const absl::Duration any_dur = absl::Seconds(1); - const absl::Duration inf = absl::InfiniteDuration(); - - // Subtraction - EXPECT_EQ(inf, inf - inf); - EXPECT_EQ(inf, inf - -inf); - EXPECT_EQ(-inf, -inf - inf); - EXPECT_EQ(-inf, -inf - -inf); - - EXPECT_EQ(inf, inf - any_dur); - EXPECT_EQ(-inf, any_dur - inf); - EXPECT_EQ(-inf, -inf - any_dur); - EXPECT_EQ(inf, any_dur - -inf); - - // Subtraction overflow/underflow - EXPECT_EQ(inf, sec_max - -absl::Seconds(1)); - EXPECT_EQ(inf, sec_max - -sec_max); - EXPECT_EQ(-inf, sec_min - absl::Seconds(1)); - EXPECT_EQ(-inf, sec_min - sec_max); - - // Interesting case - absl::Duration almost_neg_inf = sec_min; - EXPECT_LT(-inf, almost_neg_inf); - almost_neg_inf -= -absl::Nanoseconds(1); - EXPECT_LT(-inf, almost_neg_inf); - - // For reference: IEEE 754 behavior - const double dbl_inf = std::numeric_limits<double>::infinity(); - EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf - EXPECT_TRUE(std::isinf(dbl_inf - -dbl_inf)); - EXPECT_TRUE(std::isinf(-dbl_inf - dbl_inf)); - EXPECT_TRUE(std::isnan(-dbl_inf - -dbl_inf)); // We return inf -} - -TEST(Duration, InfinityMultiplication) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration sec_min = absl::Seconds(kint64min); - const absl::Duration inf = absl::InfiniteDuration(); - -#define TEST_INF_MUL_WITH_TYPE(T) \ - EXPECT_EQ(inf, inf * static_cast<T>(2)); \ - EXPECT_EQ(-inf, inf * static_cast<T>(-2)); \ - EXPECT_EQ(-inf, -inf * static_cast<T>(2)); \ - EXPECT_EQ(inf, -inf * static_cast<T>(-2)); \ - EXPECT_EQ(inf, inf * static_cast<T>(0)); \ - EXPECT_EQ(-inf, -inf * static_cast<T>(0)); \ - EXPECT_EQ(inf, sec_max * static_cast<T>(2)); \ - EXPECT_EQ(inf, sec_min * static_cast<T>(-2)); \ - EXPECT_EQ(inf, (sec_max / static_cast<T>(2)) * static_cast<T>(3)); \ - EXPECT_EQ(-inf, sec_max * static_cast<T>(-2)); \ - EXPECT_EQ(-inf, sec_min * static_cast<T>(2)); \ - EXPECT_EQ(-inf, (sec_min / static_cast<T>(2)) * static_cast<T>(3)); - - TEST_INF_MUL_WITH_TYPE(int64_t); // NOLINT(readability/function) - TEST_INF_MUL_WITH_TYPE(double); // NOLINT(readability/function) - -#undef TEST_INF_MUL_WITH_TYPE - - const double dbl_inf = std::numeric_limits<double>::infinity(); - EXPECT_EQ(inf, inf * dbl_inf); - EXPECT_EQ(-inf, -inf * dbl_inf); - EXPECT_EQ(-inf, inf * -dbl_inf); - EXPECT_EQ(inf, -inf * -dbl_inf); - - const absl::Duration any_dur = absl::Seconds(1); - EXPECT_EQ(inf, any_dur * dbl_inf); - EXPECT_EQ(-inf, -any_dur * dbl_inf); - EXPECT_EQ(-inf, any_dur * -dbl_inf); - EXPECT_EQ(inf, -any_dur * -dbl_inf); - - // Fixed-point multiplication will produce a finite value, whereas floating - // point fuzziness will overflow to inf. - EXPECT_NE(absl::InfiniteDuration(), absl::Seconds(1) * kint64max); - EXPECT_EQ(inf, absl::Seconds(1) * static_cast<double>(kint64max)); - EXPECT_NE(-absl::InfiniteDuration(), absl::Seconds(1) * kint64min); - EXPECT_EQ(-inf, absl::Seconds(1) * static_cast<double>(kint64min)); - - // Note that sec_max * or / by 1.0 overflows to inf due to the 53-bit - // limitations of double. - EXPECT_NE(inf, sec_max); - EXPECT_NE(inf, sec_max / 1); - EXPECT_EQ(inf, sec_max / 1.0); - EXPECT_NE(inf, sec_max * 1); - EXPECT_EQ(inf, sec_max * 1.0); -} - -TEST(Duration, InfinityDivision) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration sec_min = absl::Seconds(kint64min); - const absl::Duration inf = absl::InfiniteDuration(); - - // Division of Duration by a double -#define TEST_INF_DIV_WITH_TYPE(T) \ - EXPECT_EQ(inf, inf / static_cast<T>(2)); \ - EXPECT_EQ(-inf, inf / static_cast<T>(-2)); \ - EXPECT_EQ(-inf, -inf / static_cast<T>(2)); \ - EXPECT_EQ(inf, -inf / static_cast<T>(-2)); - - TEST_INF_DIV_WITH_TYPE(int64_t); // NOLINT(readability/function) - TEST_INF_DIV_WITH_TYPE(double); // NOLINT(readability/function) - -#undef TEST_INF_DIV_WITH_TYPE - - // Division of Duration by a double overflow/underflow - EXPECT_EQ(inf, sec_max / 0.5); - EXPECT_EQ(inf, sec_min / -0.5); - EXPECT_EQ(inf, ((sec_max / 0.5) + absl::Seconds(1)) / 0.5); - EXPECT_EQ(-inf, sec_max / -0.5); - EXPECT_EQ(-inf, sec_min / 0.5); - EXPECT_EQ(-inf, ((sec_min / 0.5) - absl::Seconds(1)) / 0.5); - - const double dbl_inf = std::numeric_limits<double>::infinity(); - EXPECT_EQ(inf, inf / dbl_inf); - EXPECT_EQ(-inf, inf / -dbl_inf); - EXPECT_EQ(-inf, -inf / dbl_inf); - EXPECT_EQ(inf, -inf / -dbl_inf); - - const absl::Duration any_dur = absl::Seconds(1); - EXPECT_EQ(absl::ZeroDuration(), any_dur / dbl_inf); - EXPECT_EQ(absl::ZeroDuration(), any_dur / -dbl_inf); - EXPECT_EQ(absl::ZeroDuration(), -any_dur / dbl_inf); - EXPECT_EQ(absl::ZeroDuration(), -any_dur / -dbl_inf); -} - -TEST(Duration, InfinityModulus) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration any_dur = absl::Seconds(1); - const absl::Duration inf = absl::InfiniteDuration(); - - EXPECT_EQ(inf, inf % inf); - EXPECT_EQ(inf, inf % -inf); - EXPECT_EQ(-inf, -inf % -inf); - EXPECT_EQ(-inf, -inf % inf); - - EXPECT_EQ(any_dur, any_dur % inf); - EXPECT_EQ(any_dur, any_dur % -inf); - EXPECT_EQ(-any_dur, -any_dur % inf); - EXPECT_EQ(-any_dur, -any_dur % -inf); - - EXPECT_EQ(inf, inf % -any_dur); - EXPECT_EQ(inf, inf % any_dur); - EXPECT_EQ(-inf, -inf % -any_dur); - EXPECT_EQ(-inf, -inf % any_dur); - - // Remainder isn't affected by overflow. - EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Seconds(1)); - EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Milliseconds(1)); - EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Microseconds(1)); - EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1)); - EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1) / 4); -} - -TEST(Duration, InfinityIDiv) { - const absl::Duration sec_max = absl::Seconds(kint64max); - const absl::Duration any_dur = absl::Seconds(1); - const absl::Duration inf = absl::InfiniteDuration(); - const double dbl_inf = std::numeric_limits<double>::infinity(); - - // IDivDuration (int64_t return value + a remainer) - absl::Duration rem = absl::ZeroDuration(); - EXPECT_EQ(kint64max, absl::IDivDuration(inf, inf, &rem)); - EXPECT_EQ(inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -inf, &rem)); - EXPECT_EQ(-inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64max, absl::IDivDuration(inf, any_dur, &rem)); - EXPECT_EQ(inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(0, absl::IDivDuration(any_dur, inf, &rem)); - EXPECT_EQ(any_dur, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -any_dur, &rem)); - EXPECT_EQ(-inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(0, absl::IDivDuration(-any_dur, -inf, &rem)); - EXPECT_EQ(-any_dur, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64min, absl::IDivDuration(-inf, inf, &rem)); - EXPECT_EQ(-inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64min, absl::IDivDuration(inf, -inf, &rem)); - EXPECT_EQ(inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64min, absl::IDivDuration(-inf, any_dur, &rem)); - EXPECT_EQ(-inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(0, absl::IDivDuration(-any_dur, inf, &rem)); - EXPECT_EQ(-any_dur, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(kint64min, absl::IDivDuration(inf, -any_dur, &rem)); - EXPECT_EQ(inf, rem); - - rem = absl::ZeroDuration(); - EXPECT_EQ(0, absl::IDivDuration(any_dur, -inf, &rem)); - EXPECT_EQ(any_dur, rem); - - // IDivDuration overflow/underflow - rem = any_dur; - EXPECT_EQ(kint64max, - absl::IDivDuration(sec_max, absl::Nanoseconds(1) / 4, &rem)); - EXPECT_EQ(sec_max - absl::Nanoseconds(kint64max) / 4, rem); - - rem = any_dur; - EXPECT_EQ(kint64max, - absl::IDivDuration(sec_max, absl::Milliseconds(1), &rem)); - EXPECT_EQ(sec_max - absl::Milliseconds(kint64max), rem); - - rem = any_dur; - EXPECT_EQ(kint64max, - absl::IDivDuration(-sec_max, -absl::Milliseconds(1), &rem)); - EXPECT_EQ(-sec_max + absl::Milliseconds(kint64max), rem); - - rem = any_dur; - EXPECT_EQ(kint64min, - absl::IDivDuration(-sec_max, absl::Milliseconds(1), &rem)); - EXPECT_EQ(-sec_max - absl::Milliseconds(kint64min), rem); - - rem = any_dur; - EXPECT_EQ(kint64min, - absl::IDivDuration(sec_max, -absl::Milliseconds(1), &rem)); - EXPECT_EQ(sec_max + absl::Milliseconds(kint64min), rem); - - // - // operator/(Duration, Duration) is a wrapper for IDivDuration(). - // - - // IEEE 754 says inf / inf should be nan, but int64_t doesn't have - // nan so we'll return kint64max/kint64min instead. - EXPECT_TRUE(std::isnan(dbl_inf / dbl_inf)); - EXPECT_EQ(kint64max, inf / inf); - EXPECT_EQ(kint64max, -inf / -inf); - EXPECT_EQ(kint64min, -inf / inf); - EXPECT_EQ(kint64min, inf / -inf); - - EXPECT_TRUE(std::isinf(dbl_inf / 2.0)); - EXPECT_EQ(kint64max, inf / any_dur); - EXPECT_EQ(kint64max, -inf / -any_dur); - EXPECT_EQ(kint64min, -inf / any_dur); - EXPECT_EQ(kint64min, inf / -any_dur); - - EXPECT_EQ(0.0, 2.0 / dbl_inf); - EXPECT_EQ(0, any_dur / inf); - EXPECT_EQ(0, any_dur / -inf); - EXPECT_EQ(0, -any_dur / inf); - EXPECT_EQ(0, -any_dur / -inf); - EXPECT_EQ(0, absl::ZeroDuration() / inf); - - // Division of Duration by a Duration overflow/underflow - EXPECT_EQ(kint64max, sec_max / absl::Milliseconds(1)); - EXPECT_EQ(kint64max, -sec_max / -absl::Milliseconds(1)); - EXPECT_EQ(kint64min, -sec_max / absl::Milliseconds(1)); - EXPECT_EQ(kint64min, sec_max / -absl::Milliseconds(1)); -} - -TEST(Duration, InfinityFDiv) { - const absl::Duration any_dur = absl::Seconds(1); - const absl::Duration inf = absl::InfiniteDuration(); - const double dbl_inf = std::numeric_limits<double>::infinity(); - - EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, inf)); - EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -inf)); - EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, any_dur)); - EXPECT_EQ(0.0, absl::FDivDuration(any_dur, inf)); - EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -any_dur)); - EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, -inf)); - - EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, inf)); - EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -inf)); - EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, any_dur)); - EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, inf)); - EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -any_dur)); - EXPECT_EQ(0.0, absl::FDivDuration(any_dur, -inf)); -} - -TEST(Duration, DivisionByZero) { - const absl::Duration zero = absl::ZeroDuration(); - const absl::Duration inf = absl::InfiniteDuration(); - const absl::Duration any_dur = absl::Seconds(1); - const double dbl_inf = std::numeric_limits<double>::infinity(); - const double dbl_denorm = std::numeric_limits<double>::denorm_min(); - - // Operator/(Duration, double) - EXPECT_EQ(inf, zero / 0.0); - EXPECT_EQ(-inf, zero / -0.0); - EXPECT_EQ(inf, any_dur / 0.0); - EXPECT_EQ(-inf, any_dur / -0.0); - EXPECT_EQ(-inf, -any_dur / 0.0); - EXPECT_EQ(inf, -any_dur / -0.0); - - // Tests dividing by a number very close to, but not quite zero. - EXPECT_EQ(zero, zero / dbl_denorm); - EXPECT_EQ(zero, zero / -dbl_denorm); - EXPECT_EQ(inf, any_dur / dbl_denorm); - EXPECT_EQ(-inf, any_dur / -dbl_denorm); - EXPECT_EQ(-inf, -any_dur / dbl_denorm); - EXPECT_EQ(inf, -any_dur / -dbl_denorm); - - // IDiv - absl::Duration rem = zero; - EXPECT_EQ(kint64max, absl::IDivDuration(zero, zero, &rem)); - EXPECT_EQ(inf, rem); - - rem = zero; - EXPECT_EQ(kint64max, absl::IDivDuration(any_dur, zero, &rem)); - EXPECT_EQ(inf, rem); - - rem = zero; - EXPECT_EQ(kint64min, absl::IDivDuration(-any_dur, zero, &rem)); - EXPECT_EQ(-inf, rem); - - // Operator/(Duration, Duration) - EXPECT_EQ(kint64max, zero / zero); - EXPECT_EQ(kint64max, any_dur / zero); - EXPECT_EQ(kint64min, -any_dur / zero); - - // FDiv - EXPECT_EQ(dbl_inf, absl::FDivDuration(zero, zero)); - EXPECT_EQ(dbl_inf, absl::FDivDuration(any_dur, zero)); - EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero)); -} - -TEST(Duration, NaN) { - // Note that IEEE 754 does not define the behavior of a nan's sign when it is - // copied, so the code below allows for either + or - InfiniteDuration. -#define TEST_NAN_HANDLING(NAME, NAN) \ - do { \ - const auto inf = absl::InfiniteDuration(); \ - auto x = NAME(NAN); \ - EXPECT_TRUE(x == inf || x == -inf); \ - auto y = NAME(42); \ - y *= NAN; \ - EXPECT_TRUE(y == inf || y == -inf); \ - auto z = NAME(42); \ - z /= NAN; \ - EXPECT_TRUE(z == inf || z == -inf); \ - } while (0) - - const double nan = std::numeric_limits<double>::quiet_NaN(); - TEST_NAN_HANDLING(absl::Nanoseconds, nan); - TEST_NAN_HANDLING(absl::Microseconds, nan); - TEST_NAN_HANDLING(absl::Milliseconds, nan); - TEST_NAN_HANDLING(absl::Seconds, nan); - TEST_NAN_HANDLING(absl::Minutes, nan); - TEST_NAN_HANDLING(absl::Hours, nan); - - TEST_NAN_HANDLING(absl::Nanoseconds, -nan); - TEST_NAN_HANDLING(absl::Microseconds, -nan); - TEST_NAN_HANDLING(absl::Milliseconds, -nan); - TEST_NAN_HANDLING(absl::Seconds, -nan); - TEST_NAN_HANDLING(absl::Minutes, -nan); - TEST_NAN_HANDLING(absl::Hours, -nan); - -#undef TEST_NAN_HANDLING -} - -TEST(Duration, Range) { - const absl::Duration range = ApproxYears(100 * 1e9); - const absl::Duration range_future = range; - const absl::Duration range_past = -range; - - EXPECT_LT(range_future, absl::InfiniteDuration()); - EXPECT_GT(range_past, -absl::InfiniteDuration()); - - const absl::Duration full_range = range_future - range_past; - EXPECT_GT(full_range, absl::ZeroDuration()); - EXPECT_LT(full_range, absl::InfiniteDuration()); - - const absl::Duration neg_full_range = range_past - range_future; - EXPECT_LT(neg_full_range, absl::ZeroDuration()); - EXPECT_GT(neg_full_range, -absl::InfiniteDuration()); - - EXPECT_LT(neg_full_range, full_range); - EXPECT_EQ(neg_full_range, -full_range); -} - -TEST(Duration, RelationalOperators) { -#define TEST_REL_OPS(UNIT) \ - static_assert(UNIT(2) == UNIT(2), ""); \ - static_assert(UNIT(1) != UNIT(2), ""); \ - static_assert(UNIT(1) < UNIT(2), ""); \ - static_assert(UNIT(3) > UNIT(2), ""); \ - static_assert(UNIT(1) <= UNIT(2), ""); \ - static_assert(UNIT(2) <= UNIT(2), ""); \ - static_assert(UNIT(3) >= UNIT(2), ""); \ - static_assert(UNIT(2) >= UNIT(2), ""); - - TEST_REL_OPS(absl::Nanoseconds); - TEST_REL_OPS(absl::Microseconds); - TEST_REL_OPS(absl::Milliseconds); - TEST_REL_OPS(absl::Seconds); - TEST_REL_OPS(absl::Minutes); - TEST_REL_OPS(absl::Hours); - -#undef TEST_REL_OPS -} - -TEST(Duration, Addition) { -#define TEST_ADD_OPS(UNIT) \ - do { \ - EXPECT_EQ(UNIT(2), UNIT(1) + UNIT(1)); \ - EXPECT_EQ(UNIT(1), UNIT(2) - UNIT(1)); \ - EXPECT_EQ(UNIT(0), UNIT(2) - UNIT(2)); \ - EXPECT_EQ(UNIT(-1), UNIT(1) - UNIT(2)); \ - EXPECT_EQ(UNIT(-2), UNIT(0) - UNIT(2)); \ - EXPECT_EQ(UNIT(-2), UNIT(1) - UNIT(3)); \ - absl::Duration a = UNIT(1); \ - a += UNIT(1); \ - EXPECT_EQ(UNIT(2), a); \ - a -= UNIT(1); \ - EXPECT_EQ(UNIT(1), a); \ - } while (0) - - TEST_ADD_OPS(absl::Nanoseconds); - TEST_ADD_OPS(absl::Microseconds); - TEST_ADD_OPS(absl::Milliseconds); - TEST_ADD_OPS(absl::Seconds); - TEST_ADD_OPS(absl::Minutes); - TEST_ADD_OPS(absl::Hours); - -#undef TEST_ADD_OPS - - EXPECT_EQ(absl::Seconds(2), absl::Seconds(3) - 2 * absl::Milliseconds(500)); - EXPECT_EQ(absl::Seconds(2) + absl::Milliseconds(500), - absl::Seconds(3) - absl::Milliseconds(500)); - - EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(998), - absl::Milliseconds(999) + absl::Milliseconds(999)); - - EXPECT_EQ(absl::Milliseconds(-1), - absl::Milliseconds(998) - absl::Milliseconds(999)); - - // Tests fractions of a nanoseconds. These are implementation details only. - EXPECT_GT(absl::Nanoseconds(1), absl::Nanoseconds(1) / 2); - EXPECT_EQ(absl::Nanoseconds(1), - absl::Nanoseconds(1) / 2 + absl::Nanoseconds(1) / 2); - EXPECT_GT(absl::Nanoseconds(1) / 4, absl::Nanoseconds(0)); - EXPECT_EQ(absl::Nanoseconds(1) / 8, absl::Nanoseconds(0)); - - // Tests subtraction that will cause wrap around of the rep_lo_ bits. - absl::Duration d_7_5 = absl::Seconds(7) + absl::Milliseconds(500); - absl::Duration d_3_7 = absl::Seconds(3) + absl::Milliseconds(700); - absl::Duration ans_3_8 = absl::Seconds(3) + absl::Milliseconds(800); - EXPECT_EQ(ans_3_8, d_7_5 - d_3_7); - - // Subtracting min_duration - absl::Duration min_dur = absl::Seconds(kint64min); - EXPECT_EQ(absl::Seconds(0), min_dur - min_dur); - EXPECT_EQ(absl::Seconds(kint64max), absl::Seconds(-1) - min_dur); -} - -TEST(Duration, Negation) { - // By storing negations of various values in constexpr variables we - // verify that the initializers are constant expressions. - constexpr absl::Duration negated_zero_duration = -absl::ZeroDuration(); - EXPECT_EQ(negated_zero_duration, absl::ZeroDuration()); - - constexpr absl::Duration negated_infinite_duration = - -absl::InfiniteDuration(); - EXPECT_NE(negated_infinite_duration, absl::InfiniteDuration()); - EXPECT_EQ(-negated_infinite_duration, absl::InfiniteDuration()); - - // The public APIs to check if a duration is infinite depend on using - // -InfiniteDuration(), but we're trying to test operator- here, so we - // need to use the lower-level internal query IsInfiniteDuration. - EXPECT_TRUE( - absl::time_internal::IsInfiniteDuration(negated_infinite_duration)); - - // The largest Duration is kint64max seconds and kTicksPerSecond - 1 ticks. - // Using the absl::time_internal::MakeDuration API is the cleanest way to - // construct that Duration. - constexpr absl::Duration max_duration = absl::time_internal::MakeDuration( - kint64max, absl::time_internal::kTicksPerSecond - 1); - constexpr absl::Duration negated_max_duration = -max_duration; - // The largest negatable value is one tick above the minimum representable; - // it's the negation of max_duration. - constexpr absl::Duration nearly_min_duration = - absl::time_internal::MakeDuration(kint64min, int64_t{1}); - constexpr absl::Duration negated_nearly_min_duration = -nearly_min_duration; - - EXPECT_EQ(negated_max_duration, nearly_min_duration); - EXPECT_EQ(negated_nearly_min_duration, max_duration); - EXPECT_EQ(-(-max_duration), max_duration); - - constexpr absl::Duration min_duration = - absl::time_internal::MakeDuration(kint64min); - constexpr absl::Duration negated_min_duration = -min_duration; - EXPECT_EQ(negated_min_duration, absl::InfiniteDuration()); -} - -TEST(Duration, AbsoluteValue) { - EXPECT_EQ(absl::ZeroDuration(), AbsDuration(absl::ZeroDuration())); - EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(1))); - EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(-1))); - - EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(absl::InfiniteDuration())); - EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(-absl::InfiniteDuration())); - - absl::Duration max_dur = - absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4); - EXPECT_EQ(max_dur, AbsDuration(max_dur)); - - absl::Duration min_dur = absl::Seconds(kint64min); - EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(min_dur)); - EXPECT_EQ(max_dur, AbsDuration(min_dur + absl::Nanoseconds(1) / 4)); -} - -TEST(Duration, Multiplication) { -#define TEST_MUL_OPS(UNIT) \ - do { \ - EXPECT_EQ(UNIT(5), UNIT(2) * 2.5); \ - EXPECT_EQ(UNIT(2), UNIT(5) / 2.5); \ - EXPECT_EQ(UNIT(-5), UNIT(-2) * 2.5); \ - EXPECT_EQ(UNIT(-5), -UNIT(2) * 2.5); \ - EXPECT_EQ(UNIT(-5), UNIT(2) * -2.5); \ - EXPECT_EQ(UNIT(-2), UNIT(-5) / 2.5); \ - EXPECT_EQ(UNIT(-2), -UNIT(5) / 2.5); \ - EXPECT_EQ(UNIT(-2), UNIT(5) / -2.5); \ - EXPECT_EQ(UNIT(2), UNIT(11) % UNIT(3)); \ - absl::Duration a = UNIT(2); \ - a *= 2.5; \ - EXPECT_EQ(UNIT(5), a); \ - a /= 2.5; \ - EXPECT_EQ(UNIT(2), a); \ - a %= UNIT(1); \ - EXPECT_EQ(UNIT(0), a); \ - absl::Duration big = UNIT(1000000000); \ - big *= 3; \ - big /= 3; \ - EXPECT_EQ(UNIT(1000000000), big); \ - EXPECT_EQ(-UNIT(2), -UNIT(2)); \ - EXPECT_EQ(-UNIT(2), UNIT(2) * -1); \ - EXPECT_EQ(-UNIT(2), -1 * UNIT(2)); \ - EXPECT_EQ(-UNIT(-2), UNIT(2)); \ - EXPECT_EQ(2, UNIT(2) / UNIT(1)); \ - absl::Duration rem; \ - EXPECT_EQ(2, absl::IDivDuration(UNIT(2), UNIT(1), &rem)); \ - EXPECT_EQ(2.0, absl::FDivDuration(UNIT(2), UNIT(1))); \ - } while (0) - - TEST_MUL_OPS(absl::Nanoseconds); - TEST_MUL_OPS(absl::Microseconds); - TEST_MUL_OPS(absl::Milliseconds); - TEST_MUL_OPS(absl::Seconds); - TEST_MUL_OPS(absl::Minutes); - TEST_MUL_OPS(absl::Hours); - -#undef TEST_MUL_OPS - - // Ensures that multiplication and division by 1 with a maxed-out durations - // doesn't lose precision. - absl::Duration max_dur = - absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4); - absl::Duration min_dur = absl::Seconds(kint64min); - EXPECT_EQ(max_dur, max_dur * 1); - EXPECT_EQ(max_dur, max_dur / 1); - EXPECT_EQ(min_dur, min_dur * 1); - EXPECT_EQ(min_dur, min_dur / 1); - - // Tests division on a Duration with a large number of significant digits. - // Tests when the digits span hi and lo as well as only in hi. - absl::Duration sigfigs = absl::Seconds(2000000000) + absl::Nanoseconds(3); - EXPECT_EQ(absl::Seconds(666666666) + absl::Nanoseconds(666666667) + - absl::Nanoseconds(1) / 2, - sigfigs / 3); - sigfigs = absl::Seconds(int64_t{7000000000}); - EXPECT_EQ(absl::Seconds(2333333333) + absl::Nanoseconds(333333333) + - absl::Nanoseconds(1) / 4, - sigfigs / 3); - - EXPECT_EQ(absl::Seconds(7) + absl::Milliseconds(500), absl::Seconds(3) * 2.5); - EXPECT_EQ(absl::Seconds(8) * -1 + absl::Milliseconds(300), - (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5); - EXPECT_EQ(-absl::Seconds(8) + absl::Milliseconds(300), - (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5); - EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(875), - (absl::Seconds(7) + absl::Milliseconds(500)) / 4); - EXPECT_EQ(absl::Seconds(30), - (absl::Seconds(7) + absl::Milliseconds(500)) / 0.25); - EXPECT_EQ(absl::Seconds(3), - (absl::Seconds(7) + absl::Milliseconds(500)) / 2.5); - - // Tests division remainder. - EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(7) % absl::Nanoseconds(1)); - EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(0) % absl::Nanoseconds(10)); - EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(7) % absl::Nanoseconds(5)); - EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(2) % absl::Nanoseconds(5)); - - EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(10) % absl::Nanoseconds(3)); - EXPECT_EQ(absl::Nanoseconds(1), - absl::Nanoseconds(10) % absl::Nanoseconds(-3)); - EXPECT_EQ(absl::Nanoseconds(-1), - absl::Nanoseconds(-10) % absl::Nanoseconds(3)); - EXPECT_EQ(absl::Nanoseconds(-1), - absl::Nanoseconds(-10) % absl::Nanoseconds(-3)); - - EXPECT_EQ(absl::Milliseconds(100), - absl::Seconds(1) % absl::Milliseconds(300)); - EXPECT_EQ( - absl::Milliseconds(300), - (absl::Seconds(3) + absl::Milliseconds(800)) % absl::Milliseconds(500)); - - EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(1) % absl::Seconds(1)); - EXPECT_EQ(absl::Nanoseconds(-1), absl::Nanoseconds(-1) % absl::Seconds(1)); - EXPECT_EQ(0, absl::Nanoseconds(-1) / absl::Seconds(1)); // Actual -1e-9 - - // Tests identity a = (a/b)*b + a%b -#define TEST_MOD_IDENTITY(a, b) \ - EXPECT_EQ((a), ((a) / (b))*(b) + ((a)%(b))) - - TEST_MOD_IDENTITY(absl::Seconds(0), absl::Seconds(2)); - TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(1)); - TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(2)); - TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(1)); - - TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(1)); - TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(-1)); - TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(-1)); - - TEST_MOD_IDENTITY(absl::Nanoseconds(0), absl::Nanoseconds(2)); - TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(1)); - TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(2)); - TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(1)); - - TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(1)); - TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(-1)); - TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(-1)); - - // Mixed seconds + subseconds - absl::Duration mixed_a = absl::Seconds(1) + absl::Nanoseconds(2); - absl::Duration mixed_b = absl::Seconds(1) + absl::Nanoseconds(3); - - TEST_MOD_IDENTITY(absl::Seconds(0), mixed_a); - TEST_MOD_IDENTITY(mixed_a, mixed_a); - TEST_MOD_IDENTITY(mixed_a, mixed_b); - TEST_MOD_IDENTITY(mixed_b, mixed_a); - - TEST_MOD_IDENTITY(-mixed_a, mixed_b); - TEST_MOD_IDENTITY(mixed_a, -mixed_b); - TEST_MOD_IDENTITY(-mixed_a, -mixed_b); - -#undef TEST_MOD_IDENTITY -} - -TEST(Duration, Truncation) { - const absl::Duration d = absl::Nanoseconds(1234567890); - const absl::Duration inf = absl::InfiniteDuration(); - for (int unit_sign : {1, -1}) { // sign shouldn't matter - EXPECT_EQ(absl::Nanoseconds(1234567890), - Trunc(d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(1234567), - Trunc(d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(1234), - Trunc(d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(1), Trunc(d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(inf, Trunc(inf, unit_sign * absl::Seconds(1))); - - EXPECT_EQ(absl::Nanoseconds(-1234567890), - Trunc(-d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(-1234567), - Trunc(-d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(-1234), - Trunc(-d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(-1), Trunc(-d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(-inf, Trunc(-inf, unit_sign * absl::Seconds(1))); - } -} - -TEST(Duration, Flooring) { - const absl::Duration d = absl::Nanoseconds(1234567890); - const absl::Duration inf = absl::InfiniteDuration(); - for (int unit_sign : {1, -1}) { // sign shouldn't matter - EXPECT_EQ(absl::Nanoseconds(1234567890), - absl::Floor(d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(1234567), - absl::Floor(d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(1234), - absl::Floor(d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(1), absl::Floor(d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(inf, absl::Floor(inf, unit_sign * absl::Seconds(1))); - - EXPECT_EQ(absl::Nanoseconds(-1234567890), - absl::Floor(-d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(-1234568), - absl::Floor(-d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(-1235), - absl::Floor(-d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(-2), absl::Floor(-d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(-inf, absl::Floor(-inf, unit_sign * absl::Seconds(1))); - } -} - -TEST(Duration, Ceiling) { - const absl::Duration d = absl::Nanoseconds(1234567890); - const absl::Duration inf = absl::InfiniteDuration(); - for (int unit_sign : {1, -1}) { // // sign shouldn't matter - EXPECT_EQ(absl::Nanoseconds(1234567890), - absl::Ceil(d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(1234568), - absl::Ceil(d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(1235), - absl::Ceil(d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(2), absl::Ceil(d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(inf, absl::Ceil(inf, unit_sign * absl::Seconds(1))); - - EXPECT_EQ(absl::Nanoseconds(-1234567890), - absl::Ceil(-d, unit_sign * absl::Nanoseconds(1))); - EXPECT_EQ(absl::Microseconds(-1234567), - absl::Ceil(-d, unit_sign * absl::Microseconds(1))); - EXPECT_EQ(absl::Milliseconds(-1234), - absl::Ceil(-d, unit_sign * absl::Milliseconds(1))); - EXPECT_EQ(absl::Seconds(-1), absl::Ceil(-d, unit_sign * absl::Seconds(1))); - EXPECT_EQ(-inf, absl::Ceil(-inf, unit_sign * absl::Seconds(1))); - } -} - -TEST(Duration, RoundTripUnits) { - const int kRange = 100000; - -#define ROUND_TRIP_UNIT(U, LOW, HIGH) \ - do { \ - for (int64_t i = LOW; i < HIGH; ++i) { \ - absl::Duration d = absl::U(i); \ - if (d == absl::InfiniteDuration()) \ - EXPECT_EQ(kint64max, d / absl::U(1)); \ - else if (d == -absl::InfiniteDuration()) \ - EXPECT_EQ(kint64min, d / absl::U(1)); \ - else \ - EXPECT_EQ(i, absl::U(i) / absl::U(1)); \ - } \ - } while (0) - - ROUND_TRIP_UNIT(Nanoseconds, kint64min, kint64min + kRange); - ROUND_TRIP_UNIT(Nanoseconds, -kRange, kRange); - ROUND_TRIP_UNIT(Nanoseconds, kint64max - kRange, kint64max); - - ROUND_TRIP_UNIT(Microseconds, kint64min, kint64min + kRange); - ROUND_TRIP_UNIT(Microseconds, -kRange, kRange); - ROUND_TRIP_UNIT(Microseconds, kint64max - kRange, kint64max); - - ROUND_TRIP_UNIT(Milliseconds, kint64min, kint64min + kRange); - ROUND_TRIP_UNIT(Milliseconds, -kRange, kRange); - ROUND_TRIP_UNIT(Milliseconds, kint64max - kRange, kint64max); - - ROUND_TRIP_UNIT(Seconds, kint64min, kint64min + kRange); - ROUND_TRIP_UNIT(Seconds, -kRange, kRange); - ROUND_TRIP_UNIT(Seconds, kint64max - kRange, kint64max); - - ROUND_TRIP_UNIT(Minutes, kint64min / 60, kint64min / 60 + kRange); - ROUND_TRIP_UNIT(Minutes, -kRange, kRange); - ROUND_TRIP_UNIT(Minutes, kint64max / 60 - kRange, kint64max / 60); - - ROUND_TRIP_UNIT(Hours, kint64min / 3600, kint64min / 3600 + kRange); - ROUND_TRIP_UNIT(Hours, -kRange, kRange); - ROUND_TRIP_UNIT(Hours, kint64max / 3600 - kRange, kint64max / 3600); - -#undef ROUND_TRIP_UNIT -} - -TEST(Duration, TruncConversions) { - // Tests ToTimespec()/DurationFromTimespec() - const struct { - absl::Duration d; - timespec ts; - } to_ts[] = { - {absl::Seconds(1) + absl::Nanoseconds(1), {1, 1}}, - {absl::Seconds(1) + absl::Nanoseconds(1) / 2, {1, 0}}, - {absl::Seconds(1) + absl::Nanoseconds(0), {1, 0}}, - {absl::Seconds(0) + absl::Nanoseconds(0), {0, 0}}, - {absl::Seconds(0) - absl::Nanoseconds(1) / 2, {0, 0}}, - {absl::Seconds(0) - absl::Nanoseconds(1), {-1, 999999999}}, - {absl::Seconds(-1) + absl::Nanoseconds(1), {-1, 1}}, - {absl::Seconds(-1) + absl::Nanoseconds(1) / 2, {-1, 1}}, - {absl::Seconds(-1) + absl::Nanoseconds(0), {-1, 0}}, - {absl::Seconds(-1) - absl::Nanoseconds(1) / 2, {-1, 0}}, - }; - for (const auto& test : to_ts) { - EXPECT_THAT(absl::ToTimespec(test.d), TimespecMatcher(test.ts)); - } - const struct { - timespec ts; - absl::Duration d; - } from_ts[] = { - {{1, 1}, absl::Seconds(1) + absl::Nanoseconds(1)}, - {{1, 0}, absl::Seconds(1) + absl::Nanoseconds(0)}, - {{0, 0}, absl::Seconds(0) + absl::Nanoseconds(0)}, - {{0, -1}, absl::Seconds(0) - absl::Nanoseconds(1)}, - {{-1, 999999999}, absl::Seconds(0) - absl::Nanoseconds(1)}, - {{-1, 1}, absl::Seconds(-1) + absl::Nanoseconds(1)}, - {{-1, 0}, absl::Seconds(-1) + absl::Nanoseconds(0)}, - {{-1, -1}, absl::Seconds(-1) - absl::Nanoseconds(1)}, - {{-2, 999999999}, absl::Seconds(-1) - absl::Nanoseconds(1)}, - }; - for (const auto& test : from_ts) { - EXPECT_EQ(test.d, absl::DurationFromTimespec(test.ts)); - } - - // Tests ToTimeval()/DurationFromTimeval() (same as timespec above) - const struct { - absl::Duration d; - timeval tv; - } to_tv[] = { - {absl::Seconds(1) + absl::Microseconds(1), {1, 1}}, - {absl::Seconds(1) + absl::Microseconds(1) / 2, {1, 0}}, - {absl::Seconds(1) + absl::Microseconds(0), {1, 0}}, - {absl::Seconds(0) + absl::Microseconds(0), {0, 0}}, - {absl::Seconds(0) - absl::Microseconds(1) / 2, {0, 0}}, - {absl::Seconds(0) - absl::Microseconds(1), {-1, 999999}}, - {absl::Seconds(-1) + absl::Microseconds(1), {-1, 1}}, - {absl::Seconds(-1) + absl::Microseconds(1) / 2, {-1, 1}}, - {absl::Seconds(-1) + absl::Microseconds(0), {-1, 0}}, - {absl::Seconds(-1) - absl::Microseconds(1) / 2, {-1, 0}}, - }; - for (const auto& test : to_tv) { - EXPECT_THAT(absl::ToTimeval(test.d), TimevalMatcher(test.tv)); - } - const struct { - timeval tv; - absl::Duration d; - } from_tv[] = { - {{1, 1}, absl::Seconds(1) + absl::Microseconds(1)}, - {{1, 0}, absl::Seconds(1) + absl::Microseconds(0)}, - {{0, 0}, absl::Seconds(0) + absl::Microseconds(0)}, - {{0, -1}, absl::Seconds(0) - absl::Microseconds(1)}, - {{-1, 999999}, absl::Seconds(0) - absl::Microseconds(1)}, - {{-1, 1}, absl::Seconds(-1) + absl::Microseconds(1)}, - {{-1, 0}, absl::Seconds(-1) + absl::Microseconds(0)}, - {{-1, -1}, absl::Seconds(-1) - absl::Microseconds(1)}, - {{-2, 999999}, absl::Seconds(-1) - absl::Microseconds(1)}, - }; - for (const auto& test : from_tv) { - EXPECT_EQ(test.d, absl::DurationFromTimeval(test.tv)); - } -} - -TEST(Duration, SmallConversions) { - // Special tests for conversions of small durations. - - EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0)); - // TODO(bww): Is the next one OK? - 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)); - EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.500e-9)); - EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.625e-9)); - EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.750e-9)); - 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(-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)); - EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.500e-9)); - EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.625e-9)); - EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.750e-9)); - EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-0.875e-9)); - EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-1.000e-9)); - - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 0; - EXPECT_THAT(ToTimespec(absl::Nanoseconds(0)), TimespecMatcher(ts)); - // TODO(bww): Are the next three OK? - EXPECT_THAT(ToTimespec(absl::Nanoseconds(1) / 4), TimespecMatcher(ts)); - EXPECT_THAT(ToTimespec(absl::Nanoseconds(2) / 4), TimespecMatcher(ts)); - EXPECT_THAT(ToTimespec(absl::Nanoseconds(3) / 4), TimespecMatcher(ts)); - ts.tv_nsec = 1; - EXPECT_THAT(ToTimespec(absl::Nanoseconds(4) / 4), TimespecMatcher(ts)); - EXPECT_THAT(ToTimespec(absl::Nanoseconds(5) / 4), TimespecMatcher(ts)); - EXPECT_THAT(ToTimespec(absl::Nanoseconds(6) / 4), TimespecMatcher(ts)); - EXPECT_THAT(ToTimespec(absl::Nanoseconds(7) / 4), TimespecMatcher(ts)); - ts.tv_nsec = 2; - EXPECT_THAT(ToTimespec(absl::Nanoseconds(8) / 4), TimespecMatcher(ts)); - - timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - EXPECT_THAT(ToTimeval(absl::Nanoseconds(0)), TimevalMatcher(tv)); - // TODO(bww): Is the next one OK? - EXPECT_THAT(ToTimeval(absl::Nanoseconds(999)), TimevalMatcher(tv)); - tv.tv_usec = 1; - EXPECT_THAT(ToTimeval(absl::Nanoseconds(1000)), TimevalMatcher(tv)); - EXPECT_THAT(ToTimeval(absl::Nanoseconds(1999)), TimevalMatcher(tv)); - tv.tv_usec = 2; - EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv)); -} - -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); - 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) - << "given double time_as_seconds = " << std::setprecision(17) - << time_as_seconds; - } -} - -// For a variety of interesting durations, we find the exact point -// where one double converts to that duration, and the very next double -// converts to the next duration. For both of those points, verify that -// Seconds(point) returns the same duration as point * Seconds(1.0) -TEST(Duration, ToDoubleSecondsCheckEdgeCases) { - constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond; - constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u); - int misses = 0; - for (int64_t seconds = 0; seconds < 99; ++seconds) { - uint32_t tick_vals[] = {0, +999, +999999, +999999999, kTicksPerSecond - 1, - 0, 1000, 1000000, 1000000000, kTicksPerSecond, - 1, 1001, 1000001, 1000000001, kTicksPerSecond + 1, - 2, 1002, 1000002, 1000000002, kTicksPerSecond + 2, - 3, 1003, 1000003, 1000000003, kTicksPerSecond + 3, - 4, 1004, 1000004, 1000000004, kTicksPerSecond + 4, - 5, 6, 7, 8, 9}; - for (uint32_t ticks : tick_vals) { - absl::Duration s_plus_t = absl::Seconds(seconds) + ticks * duration_tick; - for (absl::Duration d : {s_plus_t, -s_plus_t}) { - absl::Duration after_d = d + duration_tick; - EXPECT_NE(d, after_d); - EXPECT_EQ(after_d - d, duration_tick); - - double low_edge = ToDoubleSeconds(d); - EXPECT_EQ(d, absl::Seconds(low_edge)); - - double high_edge = ToDoubleSeconds(after_d); - EXPECT_EQ(after_d, absl::Seconds(high_edge)); - - for (;;) { - double midpoint = low_edge + (high_edge - low_edge) / 2; - if (midpoint == low_edge || midpoint == high_edge) break; - absl::Duration mid_duration = absl::Seconds(midpoint); - if (mid_duration == d) { - low_edge = midpoint; - } else { - EXPECT_EQ(mid_duration, after_d); - high_edge = midpoint; - } - } - // Now low_edge is the highest double that converts to Duration d, - // and high_edge is the lowest double that converts to Duration after_d. - VerifySameAsMul(low_edge, &misses); - VerifySameAsMul(high_edge, &misses); - } - } - } -} - -TEST(Duration, ToDoubleSecondsCheckRandom) { - std::random_device rd; - std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); - std::mt19937_64 gen(seed); - // We want doubles distributed from 1/8ns up to 2^63, where - // as many values are tested from 1ns to 2ns as from 1sec to 2sec, - // so even distribute along a log-scale of those values, and - // exponentiate before using them. (9.223377e+18 is just slightly - // out of bounds for absl::Duration.) - std::uniform_real_distribution<double> uniform(std::log(0.125e-9), - std::log(9.223377e+18)); - int misses = 0; - for (int i = 0; i < 1000000; ++i) { - double d = std::exp(uniform(gen)); - VerifySameAsMul(d, &misses); - VerifySameAsMul(-d, &misses); - } -} - -TEST(Duration, ConversionSaturation) { - absl::Duration d; - - const auto max_timeval_sec = - std::numeric_limits<decltype(timeval::tv_sec)>::max(); - const auto min_timeval_sec = - std::numeric_limits<decltype(timeval::tv_sec)>::min(); - timeval tv; - tv.tv_sec = max_timeval_sec; - tv.tv_usec = 999998; - d = absl::DurationFromTimeval(tv); - tv = ToTimeval(d); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999998, tv.tv_usec); - d += absl::Microseconds(1); - tv = ToTimeval(d); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999999, tv.tv_usec); - d += absl::Microseconds(1); // no effect - tv = ToTimeval(d); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999999, tv.tv_usec); - - tv.tv_sec = min_timeval_sec; - tv.tv_usec = 1; - d = absl::DurationFromTimeval(tv); - tv = ToTimeval(d); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(1, tv.tv_usec); - d -= absl::Microseconds(1); - tv = ToTimeval(d); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(0, tv.tv_usec); - d -= absl::Microseconds(1); // no effect - tv = ToTimeval(d); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(0, tv.tv_usec); - - const auto max_timespec_sec = - std::numeric_limits<decltype(timespec::tv_sec)>::max(); - const auto min_timespec_sec = - std::numeric_limits<decltype(timespec::tv_sec)>::min(); - timespec ts; - ts.tv_sec = max_timespec_sec; - ts.tv_nsec = 999999998; - d = absl::DurationFromTimespec(ts); - ts = absl::ToTimespec(d); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999998, ts.tv_nsec); - d += absl::Nanoseconds(1); - ts = absl::ToTimespec(d); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999999, ts.tv_nsec); - d += absl::Nanoseconds(1); // no effect - ts = absl::ToTimespec(d); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999999, ts.tv_nsec); - - ts.tv_sec = min_timespec_sec; - ts.tv_nsec = 1; - d = absl::DurationFromTimespec(ts); - ts = absl::ToTimespec(d); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(1, ts.tv_nsec); - d -= absl::Nanoseconds(1); - ts = absl::ToTimespec(d); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(0, ts.tv_nsec); - d -= absl::Nanoseconds(1); // no effect - ts = absl::ToTimespec(d); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(0, ts.tv_nsec); -} - -TEST(Duration, FormatDuration) { - // Example from Go's docs. - EXPECT_EQ("72h3m0.5s", - absl::FormatDuration(absl::Hours(72) + absl::Minutes(3) + - absl::Milliseconds(500))); - // Go's largest time: 2540400h10m10.000000000s - EXPECT_EQ("2540400h10m10s", - absl::FormatDuration(absl::Hours(2540400) + absl::Minutes(10) + - absl::Seconds(10))); - - EXPECT_EQ("0", absl::FormatDuration(absl::ZeroDuration())); - EXPECT_EQ("0", absl::FormatDuration(absl::Seconds(0))); - EXPECT_EQ("0", absl::FormatDuration(absl::Nanoseconds(0))); - - EXPECT_EQ("1ns", absl::FormatDuration(absl::Nanoseconds(1))); - EXPECT_EQ("1us", absl::FormatDuration(absl::Microseconds(1))); - EXPECT_EQ("1ms", absl::FormatDuration(absl::Milliseconds(1))); - EXPECT_EQ("1s", absl::FormatDuration(absl::Seconds(1))); - EXPECT_EQ("1m", absl::FormatDuration(absl::Minutes(1))); - EXPECT_EQ("1h", absl::FormatDuration(absl::Hours(1))); - - EXPECT_EQ("1h1m", absl::FormatDuration(absl::Hours(1) + absl::Minutes(1))); - EXPECT_EQ("1h1s", absl::FormatDuration(absl::Hours(1) + absl::Seconds(1))); - EXPECT_EQ("1m1s", absl::FormatDuration(absl::Minutes(1) + absl::Seconds(1))); - - EXPECT_EQ("1h0.25s", - absl::FormatDuration(absl::Hours(1) + absl::Milliseconds(250))); - EXPECT_EQ("1m0.25s", - absl::FormatDuration(absl::Minutes(1) + absl::Milliseconds(250))); - EXPECT_EQ("1h1m0.25s", - absl::FormatDuration(absl::Hours(1) + absl::Minutes(1) + - absl::Milliseconds(250))); - EXPECT_EQ("1h0.0005s", - absl::FormatDuration(absl::Hours(1) + absl::Microseconds(500))); - EXPECT_EQ("1h0.0000005s", - absl::FormatDuration(absl::Hours(1) + absl::Nanoseconds(500))); - - // Subsecond special case. - EXPECT_EQ("1.5ns", absl::FormatDuration(absl::Nanoseconds(1) + - absl::Nanoseconds(1) / 2)); - EXPECT_EQ("1.25ns", absl::FormatDuration(absl::Nanoseconds(1) + - absl::Nanoseconds(1) / 4)); - EXPECT_EQ("1ns", absl::FormatDuration(absl::Nanoseconds(1) + - absl::Nanoseconds(1) / 9)); - EXPECT_EQ("1.2us", absl::FormatDuration(absl::Microseconds(1) + - absl::Nanoseconds(200))); - EXPECT_EQ("1.2ms", absl::FormatDuration(absl::Milliseconds(1) + - absl::Microseconds(200))); - EXPECT_EQ("1.0002ms", absl::FormatDuration(absl::Milliseconds(1) + - absl::Nanoseconds(200))); - EXPECT_EQ("1.00001ms", absl::FormatDuration(absl::Milliseconds(1) + - absl::Nanoseconds(10))); - EXPECT_EQ("1.000001ms", - absl::FormatDuration(absl::Milliseconds(1) + absl::Nanoseconds(1))); - - // Negative durations. - EXPECT_EQ("-1ns", absl::FormatDuration(absl::Nanoseconds(-1))); - EXPECT_EQ("-1us", absl::FormatDuration(absl::Microseconds(-1))); - EXPECT_EQ("-1ms", absl::FormatDuration(absl::Milliseconds(-1))); - EXPECT_EQ("-1s", absl::FormatDuration(absl::Seconds(-1))); - EXPECT_EQ("-1m", absl::FormatDuration(absl::Minutes(-1))); - EXPECT_EQ("-1h", absl::FormatDuration(absl::Hours(-1))); - - EXPECT_EQ("-1h1m", - absl::FormatDuration(-(absl::Hours(1) + absl::Minutes(1)))); - EXPECT_EQ("-1h1s", - absl::FormatDuration(-(absl::Hours(1) + absl::Seconds(1)))); - EXPECT_EQ("-1m1s", - absl::FormatDuration(-(absl::Minutes(1) + absl::Seconds(1)))); - - EXPECT_EQ("-1ns", absl::FormatDuration(absl::Nanoseconds(-1))); - EXPECT_EQ("-1.2us", absl::FormatDuration( - -(absl::Microseconds(1) + absl::Nanoseconds(200)))); - EXPECT_EQ("-1.2ms", absl::FormatDuration( - -(absl::Milliseconds(1) + absl::Microseconds(200)))); - EXPECT_EQ("-1.0002ms", absl::FormatDuration(-(absl::Milliseconds(1) + - absl::Nanoseconds(200)))); - EXPECT_EQ("-1.00001ms", absl::FormatDuration(-(absl::Milliseconds(1) + - absl::Nanoseconds(10)))); - EXPECT_EQ("-1.000001ms", absl::FormatDuration(-(absl::Milliseconds(1) + - absl::Nanoseconds(1)))); - - // - // Interesting corner cases. - // - - const absl::Duration qns = absl::Nanoseconds(1) / 4; - const absl::Duration max_dur = - absl::Seconds(kint64max) + (absl::Seconds(1) - qns); - const absl::Duration min_dur = absl::Seconds(kint64min); - - EXPECT_EQ("0.25ns", absl::FormatDuration(qns)); - EXPECT_EQ("-0.25ns", absl::FormatDuration(-qns)); - EXPECT_EQ("2562047788015215h30m7.99999999975s", - absl::FormatDuration(max_dur)); - EXPECT_EQ("-2562047788015215h30m8s", absl::FormatDuration(min_dur)); - - // Tests printing full precision from units that print using FDivDuration - EXPECT_EQ("55.00000000025s", absl::FormatDuration(absl::Seconds(55) + qns)); - EXPECT_EQ("55.00000025ms", - absl::FormatDuration(absl::Milliseconds(55) + qns)); - EXPECT_EQ("55.00025us", absl::FormatDuration(absl::Microseconds(55) + qns)); - EXPECT_EQ("55.25ns", absl::FormatDuration(absl::Nanoseconds(55) + qns)); - - // Formatting infinity - EXPECT_EQ("inf", absl::FormatDuration(absl::InfiniteDuration())); - EXPECT_EQ("-inf", absl::FormatDuration(-absl::InfiniteDuration())); - - // Formatting approximately +/- 100 billion years - const absl::Duration huge_range = ApproxYears(100000000000); - EXPECT_EQ("876000000000000h", absl::FormatDuration(huge_range)); - EXPECT_EQ("-876000000000000h", absl::FormatDuration(-huge_range)); - - EXPECT_EQ("876000000000000h0.999999999s", - absl::FormatDuration(huge_range + - (absl::Seconds(1) - absl::Nanoseconds(1)))); - EXPECT_EQ("876000000000000h0.9999999995s", - absl::FormatDuration( - huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 2))); - EXPECT_EQ("876000000000000h0.99999999975s", - absl::FormatDuration( - huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 4))); - - EXPECT_EQ("-876000000000000h0.999999999s", - absl::FormatDuration(-huge_range - - (absl::Seconds(1) - absl::Nanoseconds(1)))); - EXPECT_EQ("-876000000000000h0.9999999995s", - absl::FormatDuration( - -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 2))); - EXPECT_EQ("-876000000000000h0.99999999975s", - absl::FormatDuration( - -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 4))); -} - -TEST(Duration, ParseDuration) { - absl::Duration d; - - // No specified unit. Should only work for zero and infinity. - EXPECT_TRUE(absl::ParseDuration("0", &d)); - EXPECT_EQ(absl::ZeroDuration(), d); - EXPECT_TRUE(absl::ParseDuration("+0", &d)); - EXPECT_EQ(absl::ZeroDuration(), d); - EXPECT_TRUE(absl::ParseDuration("-0", &d)); - EXPECT_EQ(absl::ZeroDuration(), d); - - EXPECT_TRUE(absl::ParseDuration("inf", &d)); - EXPECT_EQ(absl::InfiniteDuration(), d); - EXPECT_TRUE(absl::ParseDuration("+inf", &d)); - EXPECT_EQ(absl::InfiniteDuration(), d); - EXPECT_TRUE(absl::ParseDuration("-inf", &d)); - EXPECT_EQ(-absl::InfiniteDuration(), d); - EXPECT_FALSE(absl::ParseDuration("infBlah", &d)); - - // Illegal input forms. - EXPECT_FALSE(absl::ParseDuration("", &d)); - EXPECT_FALSE(absl::ParseDuration("0.0", &d)); - EXPECT_FALSE(absl::ParseDuration(".0", &d)); - EXPECT_FALSE(absl::ParseDuration(".", &d)); - EXPECT_FALSE(absl::ParseDuration("01", &d)); - EXPECT_FALSE(absl::ParseDuration("1", &d)); - EXPECT_FALSE(absl::ParseDuration("-1", &d)); - EXPECT_FALSE(absl::ParseDuration("2", &d)); - EXPECT_FALSE(absl::ParseDuration("2 s", &d)); - EXPECT_FALSE(absl::ParseDuration(".s", &d)); - EXPECT_FALSE(absl::ParseDuration("-.s", &d)); - EXPECT_FALSE(absl::ParseDuration("s", &d)); - EXPECT_FALSE(absl::ParseDuration(" 2s", &d)); - EXPECT_FALSE(absl::ParseDuration("2s ", &d)); - EXPECT_FALSE(absl::ParseDuration(" 2s ", &d)); - EXPECT_FALSE(absl::ParseDuration("2mt", &d)); - EXPECT_FALSE(absl::ParseDuration("1e3s", &d)); - - // One unit type. - EXPECT_TRUE(absl::ParseDuration("1ns", &d)); - EXPECT_EQ(absl::Nanoseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1us", &d)); - EXPECT_EQ(absl::Microseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1ms", &d)); - EXPECT_EQ(absl::Milliseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1s", &d)); - EXPECT_EQ(absl::Seconds(1), d); - EXPECT_TRUE(absl::ParseDuration("2m", &d)); - EXPECT_EQ(absl::Minutes(2), d); - EXPECT_TRUE(absl::ParseDuration("2h", &d)); - EXPECT_EQ(absl::Hours(2), d); - - // Huge counts of a unit. - EXPECT_TRUE(absl::ParseDuration("9223372036854775807us", &d)); - EXPECT_EQ(absl::Microseconds(9223372036854775807), d); - EXPECT_TRUE(absl::ParseDuration("-9223372036854775807us", &d)); - EXPECT_EQ(absl::Microseconds(-9223372036854775807), d); - - // Multiple units. - EXPECT_TRUE(absl::ParseDuration("2h3m4s", &d)); - EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4), d); - EXPECT_TRUE(absl::ParseDuration("3m4s5us", &d)); - EXPECT_EQ(absl::Minutes(3) + absl::Seconds(4) + absl::Microseconds(5), d); - EXPECT_TRUE(absl::ParseDuration("2h3m4s5ms6us7ns", &d)); - EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4) + - absl::Milliseconds(5) + absl::Microseconds(6) + - absl::Nanoseconds(7), - d); - - // Multiple units out of order. - EXPECT_TRUE(absl::ParseDuration("2us3m4s5h", &d)); - EXPECT_EQ(absl::Hours(5) + absl::Minutes(3) + absl::Seconds(4) + - absl::Microseconds(2), - d); - - // Fractional values of units. - EXPECT_TRUE(absl::ParseDuration("1.5ns", &d)); - EXPECT_EQ(1.5 * absl::Nanoseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1.5us", &d)); - EXPECT_EQ(1.5 * absl::Microseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1.5ms", &d)); - EXPECT_EQ(1.5 * absl::Milliseconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1.5s", &d)); - EXPECT_EQ(1.5 * absl::Seconds(1), d); - EXPECT_TRUE(absl::ParseDuration("1.5m", &d)); - EXPECT_EQ(1.5 * absl::Minutes(1), d); - EXPECT_TRUE(absl::ParseDuration("1.5h", &d)); - EXPECT_EQ(1.5 * absl::Hours(1), d); - - // Huge fractional counts of a unit. - EXPECT_TRUE(absl::ParseDuration("0.4294967295s", &d)); - EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d); - EXPECT_TRUE(absl::ParseDuration("0.429496729501234567890123456789s", &d)); - EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d); - - // Negative durations. - EXPECT_TRUE(absl::ParseDuration("-1s", &d)); - EXPECT_EQ(absl::Seconds(-1), d); - EXPECT_TRUE(absl::ParseDuration("-1m", &d)); - EXPECT_EQ(absl::Minutes(-1), d); - EXPECT_TRUE(absl::ParseDuration("-1h", &d)); - EXPECT_EQ(absl::Hours(-1), d); - - EXPECT_TRUE(absl::ParseDuration("-1h2s", &d)); - EXPECT_EQ(-(absl::Hours(1) + absl::Seconds(2)), d); - EXPECT_FALSE(absl::ParseDuration("1h-2s", &d)); - EXPECT_FALSE(absl::ParseDuration("-1h-2s", &d)); - EXPECT_FALSE(absl::ParseDuration("-1h -2s", &d)); -} - -TEST(Duration, FormatParseRoundTrip) { -#define TEST_PARSE_ROUNDTRIP(d) \ - do { \ - std::string s = absl::FormatDuration(d); \ - absl::Duration dur; \ - EXPECT_TRUE(absl::ParseDuration(s, &dur)); \ - EXPECT_EQ(d, dur); \ - } while (0) - - TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1)); - TEST_PARSE_ROUNDTRIP(absl::Microseconds(1)); - TEST_PARSE_ROUNDTRIP(absl::Milliseconds(1)); - TEST_PARSE_ROUNDTRIP(absl::Seconds(1)); - TEST_PARSE_ROUNDTRIP(absl::Minutes(1)); - TEST_PARSE_ROUNDTRIP(absl::Hours(1)); - TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(2)); - - TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(-1)); - TEST_PARSE_ROUNDTRIP(absl::Microseconds(-1)); - TEST_PARSE_ROUNDTRIP(absl::Milliseconds(-1)); - TEST_PARSE_ROUNDTRIP(absl::Seconds(-1)); - TEST_PARSE_ROUNDTRIP(absl::Minutes(-1)); - TEST_PARSE_ROUNDTRIP(absl::Hours(-1)); - - TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(2)); - TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(-2)); - TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(-2)); - - TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1) + - absl::Nanoseconds(1) / 4); // 1.25ns - - const absl::Duration huge_range = ApproxYears(100000000000); - TEST_PARSE_ROUNDTRIP(huge_range); - TEST_PARSE_ROUNDTRIP(huge_range + (absl::Seconds(1) - absl::Nanoseconds(1))); - -#undef TEST_PARSE_ROUNDTRIP -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/format.cc b/third_party/abseil_cpp/absl/time/format.cc deleted file mode 100644 index 4005fb704cf6..000000000000 --- a/third_party/abseil_cpp/absl/time/format.cc +++ /dev/null @@ -1,160 +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 <string.h> - -#include <cctype> -#include <cstdint> - -#include "absl/strings/match.h" -#include "absl/strings/string_view.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" -#include "absl/time/time.h" - -namespace cctz = absl::time_internal::cctz; - -namespace absl { -ABSL_NAMESPACE_BEGIN - -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 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 { - -const char kInfiniteFutureStr[] = "infinite-future"; -const char kInfinitePastStr[] = "infinite-past"; - -struct cctz_parts { - cctz::time_point<cctz::seconds> sec; - cctz::detail::femtoseconds fem; -}; - -inline cctz::time_point<cctz::seconds> unix_epoch() { - return std::chrono::time_point_cast<cctz::seconds>( - std::chrono::system_clock::from_time_t(0)); -} - -// Splits a Time into seconds and femtoseconds, which can be used with CCTZ. -// Requires that 't' is finite. See duration.cc for details about rep_hi and -// rep_lo. -cctz_parts Split(absl::Time t) { - const auto d = time_internal::ToUnixDuration(t); - const int64_t rep_hi = time_internal::GetRepHi(d); - const int64_t rep_lo = time_internal::GetRepLo(d); - const auto sec = unix_epoch() + cctz::seconds(rep_hi); - const auto fem = cctz::detail::femtoseconds(rep_lo * (1000 * 1000 / 4)); - return {sec, fem}; -} - -// Joins the given seconds and femtoseconds into a Time. See duration.cc for -// details about rep_hi and rep_lo. -absl::Time Join(const cctz_parts& parts) { - const int64_t rep_hi = (parts.sec - unix_epoch()).count(); - const uint32_t rep_lo = parts.fem.count() / (1000 * 1000 / 4); - const auto d = time_internal::MakeDuration(rep_hi, rep_lo); - return time_internal::FromUnixDuration(d); -} - -} // namespace - -std::string FormatTime(absl::string_view format, absl::Time t, - absl::TimeZone tz) { - if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr); - if (t == absl::InfinitePast()) return std::string(kInfinitePastStr); - const auto parts = Split(t); - return cctz::detail::format(std::string(format), parts.sec, parts.fem, - cctz::time_zone(tz)); -} - -std::string FormatTime(absl::Time t, absl::TimeZone tz) { - return FormatTime(RFC3339_full, t, tz); -} - -std::string FormatTime(absl::Time t) { - return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone()); -} - -bool ParseTime(absl::string_view format, absl::string_view input, - absl::Time* time, std::string* err) { - return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err); -} - -// If the input string does not contain an explicit UTC offset, interpret -// the fields with respect to the given TimeZone. -bool ParseTime(absl::string_view format, absl::string_view input, - absl::TimeZone tz, absl::Time* time, std::string* err) { - auto strip_leading_space = [](absl::string_view* sv) { - while (!sv->empty()) { - if (!std::isspace(sv->front())) return; - sv->remove_prefix(1); - } - }; - - // Portable toolchains means we don't get nice constexpr here. - struct Literal { - const char* name; - size_t size; - absl::Time value; - }; - static Literal literals[] = { - {kInfiniteFutureStr, strlen(kInfiniteFutureStr), InfiniteFuture()}, - {kInfinitePastStr, strlen(kInfinitePastStr), InfinitePast()}, - }; - strip_leading_space(&input); - for (const auto& lit : literals) { - if (absl::StartsWith(input, absl::string_view(lit.name, lit.size))) { - absl::string_view tail = input; - tail.remove_prefix(lit.size); - strip_leading_space(&tail); - if (tail.empty()) { - *time = lit.value; - return true; - } - } - } - - std::string error; - cctz_parts parts; - const bool b = - cctz::detail::parse(std::string(format), std::string(input), - cctz::time_zone(tz), &parts.sec, &parts.fem, &error); - if (b) { - *time = Join(parts); - } else if (err != nullptr) { - *err = error; - } - return b; -} - -// Functions required to support absl::Time flags. -bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) { - return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error); -} - -std::string AbslUnparseFlag(absl::Time t) { - return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone()); -} -bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) { - return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error); -} - -std::string UnparseFlag(absl::Time t) { - return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone()); -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/format_benchmark.cc b/third_party/abseil_cpp/absl/time/format_benchmark.cc deleted file mode 100644 index 19e481dbd1a5..000000000000 --- a/third_party/abseil_cpp/absl/time/format_benchmark.cc +++ /dev/null @@ -1,64 +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 <cstddef> -#include <string> - -#include "absl/time/internal/test_util.h" -#include "absl/time/time.h" -#include "benchmark/benchmark.h" - -namespace { - -namespace { -const char* const kFormats[] = { - absl::RFC1123_full, // 0 - absl::RFC1123_no_wday, // 1 - absl::RFC3339_full, // 2 - absl::RFC3339_sec, // 3 - "%Y-%m-%d%ET%H:%M:%S", // 4 - "%Y-%m-%d", // 5 -}; -const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); -} // namespace - -void BM_Format_FormatTime(benchmark::State& state) { - const std::string fmt = kFormats[state.range(0)]; - state.SetLabel(fmt); - const absl::TimeZone lax = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - const absl::Time t = - absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) + - absl::Nanoseconds(1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::FormatTime(fmt, t, lax).length()); - } -} -BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1); - -void BM_Format_ParseTime(benchmark::State& state) { - const std::string fmt = kFormats[state.range(0)]; - state.SetLabel(fmt); - const absl::TimeZone lax = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - absl::Time t = absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) + - absl::Nanoseconds(1); - const std::string when = absl::FormatTime(fmt, t, lax); - std::string err; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ParseTime(fmt, when, lax, &t, &err)); - } -} -BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1); - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/format_test.cc b/third_party/abseil_cpp/absl/time/format_test.cc deleted file mode 100644 index a9a1eb8ee1d6..000000000000 --- a/third_party/abseil_cpp/absl/time/format_test.cc +++ /dev/null @@ -1,441 +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 <cstdint> -#include <limits> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/internal/test_util.h" -#include "absl/time/time.h" - -using testing::HasSubstr; - -namespace { - -// A helper that tests the given format specifier by itself, and with leading -// and trailing characters. For example: TestFormatSpecifier(t, "%a", "Thu"). -void TestFormatSpecifier(absl::Time t, absl::TimeZone tz, - const std::string& fmt, const std::string& ans) { - EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz)); - EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz)); - EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz)); - EXPECT_EQ("xxx " + ans + " yyy", - absl::FormatTime("xxx " + fmt + " yyy", t, tz)); -} - -// -// Testing FormatTime() -// - -TEST(FormatTime, Basics) { - absl::TimeZone tz = absl::UTCTimeZone(); - absl::Time t = absl::FromTimeT(0); - - // Starts with a couple basic edge cases. - EXPECT_EQ("", absl::FormatTime("", t, tz)); - EXPECT_EQ(" ", absl::FormatTime(" ", t, tz)); - EXPECT_EQ(" ", absl::FormatTime(" ", t, tz)); - EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz)); - std::string big(128, 'x'); - EXPECT_EQ(big, absl::FormatTime(big, t, tz)); - // Cause the 1024-byte buffer to grow. - std::string bigger(100000, 'x'); - EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz)); - - t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5); - t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8); - EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz)); - EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz)); - EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz)); - EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz)); - EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz)); -} - -TEST(FormatTime, LocaleSpecific) { - const absl::TimeZone tz = absl::UTCTimeZone(); - absl::Time t = absl::FromTimeT(0); - - TestFormatSpecifier(t, tz, "%a", "Thu"); - TestFormatSpecifier(t, tz, "%A", "Thursday"); - TestFormatSpecifier(t, tz, "%b", "Jan"); - TestFormatSpecifier(t, tz, "%B", "January"); - - // %c should at least produce the numeric year and time-of-day. - const std::string s = - absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone()); - EXPECT_THAT(s, HasSubstr("1970")); - EXPECT_THAT(s, HasSubstr("00:00:00")); - - TestFormatSpecifier(t, tz, "%p", "AM"); - TestFormatSpecifier(t, tz, "%x", "01/01/70"); - TestFormatSpecifier(t, tz, "%X", "00:00:00"); -} - -TEST(FormatTime, ExtendedSeconds) { - const absl::TimeZone tz = absl::UTCTimeZone(); - - // No subseconds. - absl::Time t = absl::FromTimeT(0) + absl::Seconds(5); - EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz)); - EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz)); - - // With subseconds. - t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8); - EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz)); - EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz)); - EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz)); - - // Times before the Unix epoch. - t = absl::FromUnixMicros(-1); - EXPECT_EQ("1969-12-31 23:59:59.999999", - absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz)); - - // Here is a "%E*S" case we got wrong for a while. While the first - // instant below is correctly rendered as "...:07.333304", the second - // one used to appear as "...:07.33330499999999999". - t = absl::FromUnixMicros(1395024427333304); - EXPECT_EQ("2014-03-17 02:47:07.333304", - absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz)); - t += absl::Microseconds(1); - EXPECT_EQ("2014-03-17 02:47:07.333305", - absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz)); -} - -TEST(FormatTime, RFC1123FormatPadsYear) { // locale specific - absl::TimeZone tz = absl::UTCTimeZone(); - - // A year of 77 should be padded to 0077. - absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz); - EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000", - absl::FormatTime(absl::RFC1123_full, t, tz)); - EXPECT_EQ("28 Jun 0077 09:08:07 +0000", - absl::FormatTime(absl::RFC1123_no_wday, t, tz)); -} - -TEST(FormatTime, InfiniteTime) { - absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles"); - - // The format and timezone are ignored. - EXPECT_EQ("infinite-future", - absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz)); - EXPECT_EQ("infinite-past", - absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz)); -} - -// -// Testing ParseTime() -// - -TEST(ParseTime, Basics) { - absl::Time t = absl::FromTimeT(1234567890); - std::string err; - - // Simple edge cases. - EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err; - EXPECT_EQ(absl::UnixEpoch(), t); // everything defaulted - EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err; - EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err; - EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err; - EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err; - - EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z", - "2013-06-28 19:08:09 -0800", &t, &err)) - << err; - const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t); - EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs); - EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); -} - -TEST(ParseTime, NullErrorString) { - absl::Time t; - EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr)); - EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr)); - EXPECT_FALSE( - absl::ParseTime("%H out of range", "42 out of range", &t, nullptr)); -} - -TEST(ParseTime, WithTimeZone) { - const absl::TimeZone tz = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - absl::Time t; - std::string e; - - // We can parse a string without a UTC offset if we supply a timezone. - EXPECT_TRUE( - absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e)) - << e; - auto ci = tz.At(t); - EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs); - EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); - - // But the timezone is ignored when a UTC offset is present. - EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z", - "2013-06-28 19:08:09 +0800", tz, &t, &e)) - << e; - ci = absl::FixedTimeZone(8 * 60 * 60).At(t); - EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs); - EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); -} - -TEST(ParseTime, ErrorCases) { - absl::Time t = absl::FromTimeT(0); - std::string err; - - EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - - // Can't parse an illegal format specifier. - err.clear(); - EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err; - // Exact contents of "err" are platform-dependent because of - // differences in the strptime implementation between macOS and Linux. - EXPECT_FALSE(err.empty()); - - // Fails because of trailing, unparsed data "blah". - EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - - // Feb 31 requires normalization. - EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Out-of-range")); - - // Check that we cannot have spaces in UTC offsets. - EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err; - EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err; - EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - - // Check that we reject other malformed UTC offsets. - EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - - // Check that we do not accept "-0" in fields that allow zero. - EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); -} - -TEST(ParseTime, ExtendedSeconds) { - std::string err; - absl::Time t; - - // Here is a "%E*S" case we got wrong for a while. The fractional - // part of the first instant is less than 2^31 and was correctly - // parsed, while the second (and any subsecond field >=2^31) failed. - t = absl::UnixEpoch(); - EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err; - EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) + - absl::Nanoseconds(1) / 2, - t); - t = absl::UnixEpoch(); - EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err; - EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) + - absl::Nanoseconds(3) / 4, - t); - - // We should also be able to specify long strings of digits far - // beyond the current resolution and have them convert the same way. - t = absl::UnixEpoch(); - EXPECT_TRUE(absl::ParseTime( - "%E*S", "0.214748364801234567890123456789012345678901234567890123456789", - &t, &err)) - << err; - EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) + - absl::Nanoseconds(3) / 4, - t); -} - -TEST(ParseTime, ExtendedOffsetErrors) { - std::string err; - absl::Time t; - - // %z against +-HHMM. - EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - - // %z against +-HH. - EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); - - // %Ez against +-HH:MM. - EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - - // %Ez against +-HHMM. - EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Illegal trailing data")); - - // %Ez against +-HH. - EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err; - EXPECT_THAT(err, HasSubstr("Failed to parse")); -} - -TEST(ParseTime, InfiniteTime) { - absl::Time t; - std::string err; - EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err)); - EXPECT_EQ(absl::InfiniteFuture(), t); - - // Surrounding whitespace. - EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future", &t, &err)); - EXPECT_EQ(absl::InfiniteFuture(), t); - EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future ", &t, &err)); - EXPECT_EQ(absl::InfiniteFuture(), t); - EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future ", &t, &err)); - EXPECT_EQ(absl::InfiniteFuture(), t); - - EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err)); - EXPECT_EQ(absl::InfinitePast(), t); - - // Surrounding whitespace. - EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past", &t, &err)); - EXPECT_EQ(absl::InfinitePast(), t); - EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past ", &t, &err)); - EXPECT_EQ(absl::InfinitePast(), t); - EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past ", &t, &err)); - EXPECT_EQ(absl::InfinitePast(), t); - - // "infinite-future" as literal string - absl::TimeZone tz = absl::UTCTimeZone(); - EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04", - &t, &err)); - EXPECT_NE(absl::InfiniteFuture(), t); - EXPECT_EQ(3, tz.At(t).cs.hour()); - EXPECT_EQ(4, tz.At(t).cs.minute()); - - // "infinite-past" as literal string - EXPECT_TRUE( - absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err)); - EXPECT_NE(absl::InfinitePast(), t); - EXPECT_EQ(3, tz.At(t).cs.hour()); - EXPECT_EQ(4, tz.At(t).cs.minute()); - - // The input doesn't match the format. - EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err)); - EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err)); -} - -TEST(ParseTime, FailsOnUnrepresentableTime) { - const absl::TimeZone utc = absl::UTCTimeZone(); - absl::Time t; - EXPECT_FALSE( - absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr)); - EXPECT_TRUE( - absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr)); - EXPECT_TRUE( - absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr)); - EXPECT_FALSE( - absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr)); -} - -// -// Roundtrip test for FormatTime()/ParseTime(). -// - -TEST(FormatParse, RoundTrip) { - const absl::TimeZone lax = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - const absl::Time in = - absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax); - const absl::Duration subseconds = absl::Nanoseconds(654321); - std::string err; - - // RFC3339, which renders subseconds. - { - absl::Time out; - const std::string s = - absl::FormatTime(absl::RFC3339_full, in + subseconds, lax); - EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err)) - << s << ": " << err; - EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez - } - - // RFC1123, which only does whole seconds. - { - absl::Time out; - const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax); - EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err)) - << s << ": " << err; - EXPECT_EQ(in, out); // RFC1123_full includes %z - } - - // `absl::FormatTime()` falls back to strftime() for "%c", which appears to - // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which - // appears to fail on "%c" (or at least on the "%c" text produced by - // `strftime()`). This makes it fail the round-trip test. - // - // Under the emscripten compiler `absl::ParseTime() falls back to - // `strptime()`, but that ends up using a different definition for "%c" - // compared to `strftime()`, also causing the round-trip test to fail - // (see https://github.com/kripken/emscripten/pull/7491). -#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__) - // Even though we don't know what %c will produce, it should roundtrip, - // but only in the 0-offset timezone. - { - absl::Time out; - const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone()); - EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err; - EXPECT_EQ(in, out); - } -#endif // !_MSC_VER && !__EMSCRIPTEN__ -} - -TEST(FormatParse, RoundTripDistantFuture) { - const absl::TimeZone tz = absl::UTCTimeZone(); - const absl::Time in = - absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()); - std::string err; - - absl::Time out; - const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz); - EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err)) - << s << ": " << err; - EXPECT_EQ(in, out); -} - -TEST(FormatParse, RoundTripDistantPast) { - const absl::TimeZone tz = absl::UTCTimeZone(); - const absl::Time in = - absl::FromUnixSeconds(std::numeric_limits<int64_t>::min()); - std::string err; - - absl::Time out; - const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz); - EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err)) - << s << ": " << err; - EXPECT_EQ(in, out); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/BUILD.bazel b/third_party/abseil_cpp/absl/time/internal/cctz/BUILD.bazel deleted file mode 100644 index 45a952924d98..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/BUILD.bazel +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright 2016 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. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") - -package(features = ["-parse_headers"]) - -licenses(["notice"]) - -filegroup( - name = "zoneinfo", - srcs = glob(["testdata/zoneinfo/**"]), -) - -config_setting( - name = "osx", - constraint_values = [ - "@bazel_tools//platforms:osx", - ], -) - -config_setting( - name = "ios", - constraint_values = [ - "@bazel_tools//platforms:ios", - ], -) - -### libraries - -cc_library( - name = "civil_time", - srcs = ["src/civil_time_detail.cc"], - hdrs = [ - "include/cctz/civil_time.h", - ], - textual_hdrs = ["include/cctz/civil_time_detail.h"], - visibility = ["//visibility:public"], - deps = ["//absl/base:config"], -) - -cc_library( - name = "time_zone", - srcs = [ - "src/time_zone_fixed.cc", - "src/time_zone_fixed.h", - "src/time_zone_format.cc", - "src/time_zone_if.cc", - "src/time_zone_if.h", - "src/time_zone_impl.cc", - "src/time_zone_impl.h", - "src/time_zone_info.cc", - "src/time_zone_info.h", - "src/time_zone_libc.cc", - "src/time_zone_libc.h", - "src/time_zone_lookup.cc", - "src/time_zone_posix.cc", - "src/time_zone_posix.h", - "src/tzfile.h", - "src/zone_info_source.cc", - ], - hdrs = [ - "include/cctz/time_zone.h", - "include/cctz/zone_info_source.h", - ], - linkopts = select({ - ":osx": [ - "-framework Foundation", - ], - ":ios": [ - "-framework Foundation", - ], - "//conditions:default": [], - }), - visibility = ["//visibility:public"], - deps = [ - ":civil_time", - "//absl/base:config", - ], -) - -### tests - -test_suite( - name = "all_tests", - visibility = ["//visibility:public"], -) - -cc_test( - name = "civil_time_test", - size = "small", - srcs = ["src/civil_time_test.cc"], - deps = [ - ":civil_time", - "//absl/base:config", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "time_zone_format_test", - size = "small", - srcs = ["src/time_zone_format_test.cc"], - data = [":zoneinfo"], - tags = [ - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - ], - deps = [ - ":civil_time", - ":time_zone", - "//absl/base:config", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "time_zone_lookup_test", - size = "small", - timeout = "moderate", - srcs = ["src/time_zone_lookup_test.cc"], - data = [":zoneinfo"], - tags = [ - "no_test_android_arm", - "no_test_android_arm64", - "no_test_android_x86", - ], - deps = [ - ":civil_time", - ":time_zone", - "//absl/base:config", - "@com_google_googletest//:gtest_main", - ], -) - -### benchmarks - -cc_test( - name = "cctz_benchmark", - srcs = [ - "src/cctz_benchmark.cc", - "src/time_zone_if.h", - "src/time_zone_impl.h", - "src/time_zone_info.h", - "src/tzfile.h", - ], - linkstatic = 1, - tags = ["benchmark"], - deps = [ - ":civil_time", - ":time_zone", - "//absl/base:config", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -### examples - -### binaries diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/civil_time.h b/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/civil_time.h deleted file mode 100644 index d47ff86fe43e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/civil_time.h +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ -#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time_detail.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// The term "civil time" refers to the legally recognized human-scale time -// that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil -// time follows the Gregorian Calendar and is a time-zone-independent concept. -// A "date" is perhaps the most common example of a civil time (represented in -// this library as cctz::civil_day). This library provides six classes and a -// handful of functions that help with rounding, iterating, and arithmetic on -// civil times while avoiding complications like daylight-saving time (DST). -// -// The following six classes form the core of this civil-time library: -// -// * civil_second -// * civil_minute -// * civil_hour -// * civil_day -// * civil_month -// * civil_year -// -// Each class is a simple value type with the same interface for construction -// and the same six accessors for each of the civil fields (year, month, day, -// hour, minute, and second, aka YMDHMS). These classes differ only in their -// alignment, which is indicated by the type name and specifies the field on -// which arithmetic operates. -// -// Each class can be constructed by passing up to six optional integer -// arguments representing the YMDHMS fields (in that order) to the -// constructor. Omitted fields are assigned their minimum valid value. Hours, -// minutes, and seconds will be set to 0, month and day will be set to 1, and -// since there is no minimum valid year, it will be set to 1970. So, a -// default-constructed civil-time object will have YMDHMS fields representing -// "1970-01-01 00:00:00". Fields that are out-of-range are normalized (e.g., -// October 32 -> November 1) so that all civil-time objects represent valid -// values. -// -// Each civil-time class is aligned to the civil-time field indicated in the -// class's name after normalization. Alignment is performed by setting all the -// inferior fields to their minimum valid value (as described above). The -// following are examples of how each of the six types would align the fields -// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the -// string format used here is not important; it's just a shorthand way of -// showing the six YMDHMS fields.) -// -// civil_second 2015-11-22 12:34:56 -// civil_minute 2015-11-22 12:34:00 -// civil_hour 2015-11-22 12:00:00 -// civil_day 2015-11-22 00:00:00 -// civil_month 2015-11-01 00:00:00 -// civil_year 2015-01-01 00:00:00 -// -// Each civil-time type performs arithmetic on the field to which it is -// aligned. This means that adding 1 to a civil_day increments the day field -// (normalizing as necessary), and subtracting 7 from a civil_month operates -// on the month field (normalizing as necessary). All arithmetic produces a -// valid civil time. Difference requires two similarly aligned civil-time -// objects and returns the scalar answer in units of the objects' alignment. -// For example, the difference between two civil_hour objects will give an -// answer in units of civil hours. -// -// In addition to the six civil-time types just described, there are -// a handful of helper functions and algorithms for performing common -// calculations. These are described below. -// -// Note: In C++14 and later, this library is usable in a constexpr context. -// -// CONSTRUCTION: -// -// Each of the civil-time types can be constructed in two ways: by directly -// passing to the constructor up to six (optional) integers representing the -// YMDHMS fields, or by copying the YMDHMS fields from a differently aligned -// civil-time type. -// -// civil_day default_value; // 1970-01-01 00:00:00 -// -// civil_day a(2015, 2, 3); // 2015-02-03 00:00:00 -// civil_day b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 -// civil_day c(2015); // 2015-01-01 00:00:00 -// -// civil_second ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 -// civil_minute mm(ss); // 2015-02-03 04:05:00 -// civil_hour hh(mm); // 2015-02-03 04:00:00 -// civil_day d(hh); // 2015-02-03 00:00:00 -// civil_month m(d); // 2015-02-01 00:00:00 -// civil_year y(m); // 2015-01-01 00:00:00 -// -// m = civil_month(y); // 2015-01-01 00:00:00 -// d = civil_day(m); // 2015-01-01 00:00:00 -// hh = civil_hour(d); // 2015-01-01 00:00:00 -// mm = civil_minute(hh); // 2015-01-01 00:00:00 -// ss = civil_second(mm); // 2015-01-01 00:00:00 -// -// ALIGNMENT CONVERSION: -// -// The alignment of a civil-time object cannot change, but the object may be -// used to construct a new object with a different alignment. This is referred -// to as "realigning". When realigning to a type with the same or more -// precision (e.g., civil_day -> civil_second), the conversion may be -// performed implicitly since no information is lost. However, if information -// could be discarded (e.g., civil_second -> civil_day), the conversion must -// be explicit at the call site. -// -// void fun(const civil_day& day); -// -// civil_second cs; -// fun(cs); // Won't compile because data may be discarded -// fun(civil_day(cs)); // OK: explicit conversion -// -// civil_day cd; -// fun(cd); // OK: no conversion needed -// -// civil_month cm; -// fun(cm); // OK: implicit conversion to civil_day -// -// NORMALIZATION: -// -// Integer arguments passed to the constructor may be out-of-range, in which -// case they are normalized to produce a valid civil-time object. This enables -// natural arithmetic on constructor arguments without worrying about the -// field's range. Normalization guarantees that there are no invalid -// civil-time objects. -// -// civil_day d(2016, 10, 32); // Out-of-range day; normalized to 2016-11-01 -// -// Note: If normalization is undesired, you can signal an error by comparing -// the constructor arguments to the normalized values returned by the YMDHMS -// properties. -// -// PROPERTIES: -// -// All civil-time types have accessors for all six of the civil-time fields: -// year, month, day, hour, minute, and second. Recall that fields inferior to -// the type's alignment will be set to their minimum valid value. -// -// civil_day d(2015, 6, 28); -// // d.year() == 2015 -// // d.month() == 6 -// // d.day() == 28 -// // d.hour() == 0 -// // d.minute() == 0 -// // d.second() == 0 -// -// COMPARISON: -// -// Comparison always considers all six YMDHMS fields, regardless of the type's -// alignment. Comparison between differently aligned civil-time types is -// allowed. -// -// civil_day feb_3(2015, 2, 3); // 2015-02-03 00:00:00 -// civil_day mar_4(2015, 3, 4); // 2015-03-04 00:00:00 -// // feb_3 < mar_4 -// // civil_year(feb_3) == civil_year(mar_4) -// -// civil_second feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 -// // feb_3 < feb_3_noon -// // feb_3 == civil_day(feb_3_noon) -// -// // Iterates all the days of February 2015. -// for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) { -// // ... -// } -// -// STREAMING: -// -// Each civil-time type may be sent to an output stream using operator<<(). -// The output format follows the pattern "YYYY-MM-DDThh:mm:ss" where fields -// inferior to the type's alignment are omitted. -// -// civil_second cs(2015, 2, 3, 4, 5, 6); -// std::cout << cs << "\n"; // Outputs: 2015-02-03T04:05:06 -// -// civil_day cd(cs); -// std::cout << cd << "\n"; // Outputs: 2015-02-03 -// -// civil_year cy(cs); -// std::cout << cy << "\n"; // Outputs: 2015 -// -// ARITHMETIC: -// -// Civil-time types support natural arithmetic operators such as addition, -// subtraction, and difference. Arithmetic operates on the civil-time field -// indicated in the type's name. Difference requires arguments with the same -// alignment and returns the answer in units of the alignment. -// -// civil_day a(2015, 2, 3); -// ++a; // 2015-02-04 00:00:00 -// --a; // 2015-02-03 00:00:00 -// civil_day b = a + 1; // 2015-02-04 00:00:00 -// civil_day c = 1 + b; // 2015-02-05 00:00:00 -// int n = c - a; // n = 2 (civil days) -// int m = c - civil_month(c); // Won't compile: different types. -// -// EXAMPLE: Adding a month to January 31. -// -// One of the classic questions that arises when considering a civil-time -// library (or a date library or a date/time library) is this: "What happens -// when you add a month to January 31?" This is an interesting question -// because there could be a number of possible answers: -// -// 1. March 3 (or 2 if a leap year). This may make sense if the operation -// wants the equivalent of February 31. -// 2. February 28 (or 29 if a leap year). This may make sense if the operation -// wants the last day of January to go to the last day of February. -// 3. Error. The caller may get some error, an exception, an invalid date -// object, or maybe false is returned. This may make sense because there is -// no single unambiguously correct answer to the question. -// -// Practically speaking, any answer that is not what the programmer intended -// is the wrong answer. -// -// This civil-time library avoids the problem by making it impossible to ask -// ambiguous questions. All civil-time objects are aligned to a particular -// civil-field boundary (such as aligned to a year, month, day, hour, minute, -// or second), and arithmetic operates on the field to which the object is -// aligned. This means that in order to "add a month" the object must first be -// aligned to a month boundary, which is equivalent to the first day of that -// month. -// -// Of course, there are ways to compute an answer the question at hand using -// this civil-time library, but they require the programmer to be explicit -// about the answer they expect. To illustrate, let's see how to compute all -// three of the above possible answers to the question of "Jan 31 plus 1 -// month": -// -// const civil_day d(2015, 1, 31); -// -// // Answer 1: -// // Add 1 to the month field in the constructor, and rely on normalization. -// const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day()); -// // ans_normalized == 2015-03-03 (aka Feb 31) -// -// // Answer 2: -// // Add 1 to month field, capping to the end of next month. -// const auto next_month = civil_month(d) + 1; -// const auto last_day_of_next_month = civil_day(next_month + 1) - 1; -// const auto ans_capped = std::min(ans_normalized, last_day_of_next_month); -// // ans_capped == 2015-02-28 -// -// // Answer 3: -// // Signal an error if the normalized answer is not in next month. -// if (civil_month(ans_normalized) != next_month) { -// // error, month overflow -// } -// -using civil_year = detail::civil_year; -using civil_month = detail::civil_month; -using civil_day = detail::civil_day; -using civil_hour = detail::civil_hour; -using civil_minute = detail::civil_minute; -using civil_second = detail::civil_second; - -// An enum class with members monday, tuesday, wednesday, thursday, friday, -// saturday, and sunday. These enum values may be sent to an output stream -// using operator<<(). The result is the full weekday name in English with a -// leading capital letter. -// -// weekday wd = weekday::thursday; -// std::cout << wd << "\n"; // Outputs: Thursday -// -using detail::weekday; - -// Returns the weekday for the given civil-time value. -// -// civil_day a(2015, 8, 13); -// weekday wd = get_weekday(a); // wd == weekday::thursday -// -using detail::get_weekday; - -// Returns the civil_day that strictly follows or precedes the given -// civil_day, and that falls on the given weekday. -// -// For example, given: -// -// August 2015 -// Su Mo Tu We Th Fr Sa -// 1 -// 2 3 4 5 6 7 8 -// 9 10 11 12 13 14 15 -// 16 17 18 19 20 21 22 -// 23 24 25 26 27 28 29 -// 30 31 -// -// civil_day a(2015, 8, 13); // get_weekday(a) == weekday::thursday -// civil_day b = next_weekday(a, weekday::thursday); // b = 2015-08-20 -// civil_day c = prev_weekday(a, weekday::thursday); // c = 2015-08-06 -// -// civil_day d = ... -// // Gets the following Thursday if d is not already Thursday -// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); -// // Gets the previous Thursday if d is not already Thursday -// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); -// -using detail::next_weekday; -using detail::prev_weekday; - -// Returns the day-of-year for the given civil-time value. -// -// civil_day a(2015, 1, 1); -// int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1 -// civil_day b(2015, 12, 31); -// int yd_dec_31 = get_yearday(b); // yd_dec_31 = 365 -// -using detail::get_yearday; - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ diff --git a/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 deleted file mode 100644 index 8aadde57ca72..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ /dev/null @@ -1,628 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ -#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ - -#include <cstdint> -#include <limits> -#include <ostream> -#include <type_traits> - -#include "absl/base/config.h" - -// Disable constexpr support unless we are in C++14 mode. -#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) -#define CONSTEXPR_D constexpr // data -#define CONSTEXPR_F constexpr // function -#define CONSTEXPR_M constexpr // member -#else -#define CONSTEXPR_D const -#define CONSTEXPR_F inline -#define CONSTEXPR_M -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Support years that at least span the range of 64-bit time_t values. -using year_t = std::int_fast64_t; - -// Type alias that indicates an argument is not normalized (e.g., the -// constructor parameters and operands/results of addition/subtraction). -using diff_t = std::int_fast64_t; - -namespace detail { - -// Type aliases that indicate normalized argument values. -using month_t = std::int_fast8_t; // [1:12] -using day_t = std::int_fast8_t; // [1:31] -using hour_t = std::int_fast8_t; // [0:23] -using minute_t = std::int_fast8_t; // [0:59] -using second_t = std::int_fast8_t; // [0:59] - -// Normalized civil-time fields: Y-M-D HH:MM:SS. -struct fields { - CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour, - minute_t minute, second_t second) - : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} - std::int_least64_t y; - std::int_least8_t m; - std::int_least8_t d; - std::int_least8_t hh; - std::int_least8_t mm; - std::int_least8_t ss; -}; - -struct second_tag {}; -struct minute_tag : second_tag {}; -struct hour_tag : minute_tag {}; -struct day_tag : hour_tag {}; -struct month_tag : day_tag {}; -struct year_tag : month_tag {}; - -//////////////////////////////////////////////////////////////////////// - -// Field normalization (without avoidable overflow). - -namespace impl { - -CONSTEXPR_F bool is_leap_year(year_t y) noexcept { - return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); -} -CONSTEXPR_F int year_index(year_t y, month_t m) noexcept { - return (static_cast<int>((y + (m > 2)) % 400) + 400) % 400; -} -CONSTEXPR_F int days_per_century(year_t y, month_t m) noexcept { - const int yi = year_index(y, m); - return 36524 + (yi == 0 || yi > 300); -} -CONSTEXPR_F int days_per_4years(year_t y, month_t m) noexcept { - const int yi = year_index(y, m); - return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96); -} -CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept { - return is_leap_year(y + (m > 2)) ? 366 : 365; -} -CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept { - CONSTEXPR_D int k_days_per_month[1 + 12] = { - -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year - }; - return k_days_per_month[m] + (m == 2 && is_leap_year(y)); -} - -CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh, - minute_t mm, second_t ss) noexcept { - year_t ey = y % 400; - const year_t oey = ey; - ey += (cd / 146097) * 400; - cd %= 146097; - if (cd < 0) { - ey -= 400; - cd += 146097; - } - ey += (d / 146097) * 400; - d = d % 146097 + cd; - if (d > 0) { - if (d > 146097) { - ey += 400; - d -= 146097; - } - } else { - if (d > -365) { - // We often hit the previous year when stepping a civil time backwards, - // so special case it to avoid counting up by 100/4/1-year chunks. - ey -= 1; - d += days_per_year(ey, m); - } else { - ey -= 400; - d += 146097; - } - } - if (d > 365) { - for (;;) { - int n = days_per_century(ey, m); - if (d <= n) break; - d -= n; - ey += 100; - } - for (;;) { - int n = days_per_4years(ey, m); - if (d <= n) break; - d -= n; - ey += 4; - } - for (;;) { - int n = days_per_year(ey, m); - if (d <= n) break; - d -= n; - ++ey; - } - } - if (d > 28) { - for (;;) { - int n = days_per_month(ey, m); - if (d <= n) break; - d -= n; - if (++m > 12) { - ++ey; - m = 1; - } - } - } - return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss); -} -CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh, - minute_t mm, second_t ss) noexcept { - if (m != 12) { - y += m / 12; - m %= 12; - if (m <= 0) { - y -= 1; - m += 12; - } - } - return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss); -} -CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh, - minute_t mm, second_t ss) noexcept { - cd += hh / 24; - hh %= 24; - if (hh < 0) { - cd -= 1; - hh += 24; - } - return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss); -} -CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch, - diff_t mm, second_t ss) noexcept { - ch += mm / 60; - mm %= 60; - if (mm < 0) { - ch -= 1; - mm += 60; - } - return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24, - static_cast<minute_t>(mm), ss); -} -CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm, - diff_t ss) noexcept { - // Optimization for when (non-constexpr) fields are already normalized. - if (0 <= ss && ss < 60) { - const second_t nss = static_cast<second_t>(ss); - if (0 <= mm && mm < 60) { - const minute_t nmm = static_cast<minute_t>(mm); - if (0 <= hh && hh < 24) { - const hour_t nhh = static_cast<hour_t>(hh); - if (1 <= d && d <= 28 && 1 <= m && m <= 12) { - const day_t nd = static_cast<day_t>(d); - const month_t nm = static_cast<month_t>(m); - return fields(y, nm, nd, nhh, nmm, nss); - } - return n_mon(y, m, d, 0, nhh, nmm, nss); - } - return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss); - } - return n_min(y, m, d, hh, mm / 60, mm % 60, nss); - } - diff_t cm = ss / 60; - ss %= 60; - if (ss < 0) { - cm -= 1; - ss += 60; - } - return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60, - static_cast<second_t>(ss)); -} - -} // namespace impl - -//////////////////////////////////////////////////////////////////////// - -// Increments the indicated (normalized) field by "n". -CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept { - return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60); -} -CONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept { - return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss); -} -CONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept { - return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss); -} -CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept { - return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept { - return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept { - return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss); -} - -//////////////////////////////////////////////////////////////////////// - -namespace impl { - -// Returns (v * f + a) but avoiding intermediate overflow when possible. -CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept { - return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f; -} - -// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. -// Probably overflows for years outside [-292277022656:292277026595]. -CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept { - const diff_t eyear = (m <= 2) ? y - 1 : y; - const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400; - const diff_t yoe = eyear - era * 400; - const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; - const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; - return era * 146097 + doe - 719468; -} - -// Returns the difference in days between two normalized Y-M-D tuples. -// ymd_ord() will encounter integer overflow given extreme year values, -// yet the difference between two such extreme values may actually be -// small, so we take a little care to avoid overflow when possible by -// exploiting the 146097-day cycle. -CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2, - month_t m2, day_t d2) noexcept { - const diff_t a_c4_off = y1 % 400; - const diff_t b_c4_off = y2 % 400; - diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); - diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2); - if (c4_diff > 0 && delta < 0) { - delta += 2 * 146097; - c4_diff -= 2 * 400; - } else if (c4_diff < 0 && delta > 0) { - delta -= 2 * 146097; - c4_diff += 2 * 400; - } - return (c4_diff / 400 * 146097) + delta; -} - -} // namespace impl - -// Returns the difference between fields structs using the indicated unit. -CONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept { - return f1.y - f2.y; -} -CONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m)); -} -CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept { - return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d); -} -CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh)); -} -CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm)); -} -CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss); -} - -//////////////////////////////////////////////////////////////////////// - -// Aligns the (normalized) fields struct to the indicated field. -CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; } -CONSTEXPR_F fields align(minute_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; -} -CONSTEXPR_F fields align(hour_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, 0, 0}; -} -CONSTEXPR_F fields align(day_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, 0, 0, 0}; -} -CONSTEXPR_F fields align(month_tag, fields f) noexcept { - return fields{f.y, f.m, 1, 0, 0, 0}; -} -CONSTEXPR_F fields align(year_tag, fields f) noexcept { - return fields{f.y, 1, 1, 0, 0, 0}; -} - -//////////////////////////////////////////////////////////////////////// - -namespace impl { - -template <typename H> -H AbslHashValueImpl(second_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss); -} -template <typename H> -H AbslHashValueImpl(minute_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm); -} -template <typename H> -H AbslHashValueImpl(hour_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh); -} -template <typename H> -H AbslHashValueImpl(day_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d); -} -template <typename H> -H AbslHashValueImpl(month_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m); -} -template <typename H> -H AbslHashValueImpl(year_tag, H h, fields f) { - return H::combine(std::move(h), f.y); -} - -} // namespace impl - -//////////////////////////////////////////////////////////////////////// - -template <typename T> -class civil_time { - public: - explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1, - diff_t hh = 0, diff_t mm = 0, - diff_t ss = 0) noexcept - : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {} - - CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {} - civil_time(const civil_time&) = default; - civil_time& operator=(const civil_time&) = default; - - // Conversion between civil times of different alignment. Conversion to - // a more precise alignment is allowed implicitly (e.g., day -> hour), - // but conversion where information is discarded must be explicit - // (e.g., second -> minute). - template <typename U, typename S> - using preserves_data = - typename std::enable_if<std::is_base_of<U, S>::value>::type; - template <typename U> - CONSTEXPR_M civil_time(const civil_time<U>& ct, - preserves_data<T, U>* = nullptr) noexcept - : civil_time(ct.f_) {} - template <typename U> - explicit CONSTEXPR_M civil_time(const civil_time<U>& ct, - preserves_data<U, T>* = nullptr) noexcept - : civil_time(ct.f_) {} - - // Factories for the maximum/minimum representable civil_time. - static CONSTEXPR_F civil_time(max)() { - const auto max_year = (std::numeric_limits<std::int_least64_t>::max)(); - return civil_time(max_year, 12, 31, 23, 59, 59); - } - static CONSTEXPR_F civil_time(min)() { - const auto min_year = (std::numeric_limits<std::int_least64_t>::min)(); - return civil_time(min_year, 1, 1, 0, 0, 0); - } - - // Field accessors. Note: All but year() return an int. - CONSTEXPR_M year_t year() const noexcept { return f_.y; } - CONSTEXPR_M int month() const noexcept { return f_.m; } - CONSTEXPR_M int day() const noexcept { return f_.d; } - CONSTEXPR_M int hour() const noexcept { return f_.hh; } - CONSTEXPR_M int minute() const noexcept { return f_.mm; } - CONSTEXPR_M int second() const noexcept { return f_.ss; } - - // Assigning arithmetic. - CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept { - return *this = *this + n; - } - CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept { - return *this = *this - n; - } - CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; } - CONSTEXPR_M civil_time operator++(int) noexcept { - const civil_time a = *this; - ++*this; - return a; - } - CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; } - CONSTEXPR_M civil_time operator--(int) noexcept { - const civil_time a = *this; - --*this; - return a; - } - - // Binary arithmetic operators. - friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept { - return civil_time(step(T{}, a.f_, n)); - } - friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept { - 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)); - } - friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept { - return difference(T{}, lhs.f_, rhs.f_); - } - - template <typename H> - friend H AbslHashValue(H h, civil_time a) { - return impl::AbslHashValueImpl(T{}, std::move(h), a.f_); - } - - private: - // All instantiations of this template are allowed to call the following - // private constructor and access the private fields member. - template <typename U> - friend class civil_time; - - // The designated constructor that all others eventually call. - explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {} - - fields f_; -}; - -// Disallows difference between differently aligned types. -// auto n = civil_day(...) - civil_hour(...); // would be confusing. -template <typename T, typename U> -CONSTEXPR_F diff_t operator-(civil_time<T>, civil_time<U>) = delete; - -using civil_year = civil_time<year_tag>; -using civil_month = civil_time<month_tag>; -using civil_day = civil_time<day_tag>; -using civil_hour = civil_time<hour_tag>; -using civil_minute = civil_time<minute_tag>; -using civil_second = civil_time<second_tag>; - -//////////////////////////////////////////////////////////////////////// - -// Relational operators that work with differently aligned objects. -// Always compares all six fields. -template <typename T1, typename T2> -CONSTEXPR_F bool operator<(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return ( - lhs.year() < rhs.year() || - (lhs.year() == rhs.year() && - (lhs.month() < rhs.month() || - (lhs.month() == rhs.month() && - (lhs.day() < rhs.day() || (lhs.day() == rhs.day() && - (lhs.hour() < rhs.hour() || - (lhs.hour() == rhs.hour() && - (lhs.minute() < rhs.minute() || - (lhs.minute() == rhs.minute() && - (lhs.second() < rhs.second()))))))))))); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(rhs < lhs); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator>=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(lhs < rhs); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator>(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return rhs < lhs; -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator==(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return lhs.year() == rhs.year() && lhs.month() == rhs.month() && - lhs.day() == rhs.day() && lhs.hour() == rhs.hour() && - lhs.minute() == rhs.minute() && lhs.second() == rhs.second(); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator!=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(lhs == rhs); -} - -//////////////////////////////////////////////////////////////////////// - -enum class weekday { - monday, - tuesday, - wednesday, - thursday, - friday, - saturday, - sunday, -}; - -CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept { - CONSTEXPR_D weekday k_weekday_by_mon_off[13] = { - weekday::monday, weekday::tuesday, weekday::wednesday, - weekday::thursday, weekday::friday, weekday::saturday, - weekday::sunday, weekday::monday, weekday::tuesday, - weekday::wednesday, weekday::thursday, weekday::friday, - weekday::saturday, - }; - CONSTEXPR_D int k_weekday_offsets[1 + 12] = { - -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, - }; - year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3); - wd += wd / 4 - wd / 100 + wd / 400; - wd += k_weekday_offsets[cs.month()] + cs.day(); - return k_weekday_by_mon_off[wd % 7 + 6]; -} - -//////////////////////////////////////////////////////////////////////// - -CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept { - CONSTEXPR_D weekday k_weekdays_forw[14] = { - weekday::monday, weekday::tuesday, weekday::wednesday, - weekday::thursday, weekday::friday, weekday::saturday, - weekday::sunday, weekday::monday, weekday::tuesday, - weekday::wednesday, weekday::thursday, weekday::friday, - weekday::saturday, weekday::sunday, - }; - weekday base = get_weekday(cd); - for (int i = 0;; ++i) { - if (base == k_weekdays_forw[i]) { - for (int j = i + 1;; ++j) { - if (wd == k_weekdays_forw[j]) { - return cd + (j - i); - } - } - } - } -} - -CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { - CONSTEXPR_D weekday k_weekdays_back[14] = { - weekday::sunday, weekday::saturday, weekday::friday, - weekday::thursday, weekday::wednesday, weekday::tuesday, - weekday::monday, weekday::sunday, weekday::saturday, - weekday::friday, weekday::thursday, weekday::wednesday, - weekday::tuesday, weekday::monday, - }; - weekday base = get_weekday(cd); - for (int i = 0;; ++i) { - if (base == k_weekdays_back[i]) { - for (int j = i + 1;; ++j) { - if (wd == k_weekdays_back[j]) { - return cd - (j - i); - } - } - } - } -} - -CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept { - CONSTEXPR_D int k_month_offsets[1 + 12] = { - -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, - }; - const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year())); - return k_month_offsets[cs.month()] + feb29 + cs.day(); -} - -//////////////////////////////////////////////////////////////////////// - -std::ostream& operator<<(std::ostream& os, const civil_year& y); -std::ostream& operator<<(std::ostream& os, const civil_month& m); -std::ostream& operator<<(std::ostream& os, const civil_day& d); -std::ostream& operator<<(std::ostream& os, const civil_hour& h); -std::ostream& operator<<(std::ostream& os, const civil_minute& m); -std::ostream& operator<<(std::ostream& os, const civil_second& s); -std::ostream& operator<<(std::ostream& os, weekday wd); - -} // namespace detail -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef CONSTEXPR_M -#undef CONSTEXPR_F -#undef CONSTEXPR_D - -#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ 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 deleted file mode 100644 index 5562a37bc807..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/time_zone.h +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2016 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. - -// A library for translating between absolute times (represented by -// std::chrono::time_points of the std::chrono::system_clock) and civil -// times (represented by cctz::civil_second) using the rules defined by -// a time zone (cctz::time_zone). - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ - -#include <chrono> -#include <cstdint> -#include <string> -#include <utility> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Convenience aliases. Not intended as public API points. -template <typename D> -using time_point = std::chrono::time_point<std::chrono::system_clock, D>; -using seconds = std::chrono::duration<std::int_fast64_t>; -using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. - -namespace detail { -template <typename D> -inline std::pair<time_point<seconds>, D> split_seconds( - const time_point<D>& tp) { - 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 -// geo-political region within which particular rules are used for mapping -// between absolute and civil times. Time zones are named using the TZ -// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" -// or "Australia/Sydney". Time zones are created from factory functions such -// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ -// identifiers. -// -// Example: -// cctz::time_zone utc = cctz::utc_time_zone(); -// cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8)); -// cctz::time_zone loc = cctz::local_time_zone(); -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// -// See also: -// - http://www.iana.org/time-zones -// - https://en.wikipedia.org/wiki/Zoneinfo -class time_zone { - public: - time_zone() : time_zone(nullptr) {} // Equivalent to UTC - time_zone(const time_zone&) = default; - time_zone& operator=(const time_zone&) = default; - - std::string name() const; - - // An absolute_lookup represents the civil time (cctz::civil_second) within - // this time_zone at the given absolute time (time_point). There are - // additionally a few other fields that may be useful when working with - // older APIs, such as std::tm. - // - // Example: - // const cctz::time_zone tz = ... - // const auto tp = std::chrono::system_clock::now(); - // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); - struct absolute_lookup { - civil_second cs; - // Note: The following fields exist for backward compatibility with older - // APIs. Accessing these fields directly is a sign of imprudent logic in - // the calling code. Modern time-related code should only access this data - // indirectly by way of cctz::format(). - int offset; // civil seconds east of UTC - bool is_dst; // is offset non-standard? - const char* abbr; // time-zone abbreviation (e.g., "PST") - }; - absolute_lookup lookup(const time_point<seconds>& tp) const; - template <typename D> - absolute_lookup lookup(const time_point<D>& tp) const { - return lookup(detail::split_seconds(tp).first); - } - - // A civil_lookup represents the absolute time(s) (time_point) that - // correspond to the given civil time (cctz::civil_second) within this - // time_zone. Usually the given civil time represents a unique instant - // in time, in which case the conversion is unambiguous. However, - // within this time zone, the given civil time may be skipped (e.g., - // during a positive UTC offset shift), or repeated (e.g., during a - // negative UTC offset shift). To account for these possibilities, - // civil_lookup is richer than just a single time_point. - // - // In all cases the civil_lookup::kind enum will indicate the nature - // of the given civil-time argument, and the pre, trans, and post - // members will give the absolute time answers using the pre-transition - // offset, the transition point itself, and the post-transition offset, - // respectively (all three times are equal if kind == UNIQUE). If any - // of these three absolute times is outside the representable range of a - // time_point<seconds> the field is set to its maximum/minimum value. - // - // Example: - // cctz::time_zone lax; - // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } - // - // // A unique civil time. - // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); - // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE - // // jan01.pre is 2011/01/01 00:00:00 -0800 - // // jan01.trans is 2011/01/01 00:00:00 -0800 - // // jan01.post is 2011/01/01 00:00:00 -0800 - // - // // A Spring DST transition, when there is a gap in civil time. - // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); - // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED - // // mar13.pre is 2011/03/13 03:15:00 -0700 - // // mar13.trans is 2011/03/13 03:00:00 -0700 - // // mar13.post is 2011/03/13 01:15:00 -0800 - // - // // A Fall DST transition, when civil times are repeated. - // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); - // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED - // // nov06.pre is 2011/11/06 01:15:00 -0700 - // // nov06.trans is 2011/11/06 01:00:00 -0800 - // // nov06.post is 2011/11/06 01:15:00 -0800 - struct civil_lookup { - enum civil_kind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist (pre >= trans > post) - REPEATED, // the civil time was ambiguous (pre < trans <= post) - } kind; - time_point<seconds> pre; // uses the pre-transition offset - time_point<seconds> trans; // instant of civil-offset change - time_point<seconds> post; // uses the post-transition offset - }; - civil_lookup lookup(const civil_second& cs) const; - - // Finds the time of the next/previous offset change in this time zone. - // - // By definition, next_transition(tp, &trans) returns false when tp has - // its maximum value, and prev_transition(tp, &trans) returns false - // when tp has its minimum value. If the zone has no transitions, the - // result will also be false no matter what the argument. - // - // Otherwise, when tp has its minimum value, next_transition(tp, &trans) - // returns true and sets trans to the first recorded transition. Chains - // of calls to next_transition()/prev_transition() will eventually return - // false, but it is unspecified exactly when next_transition(tp, &trans) - // jumps to false, or what time is set by prev_transition(tp, &trans) for - // a very distant tp. - // - // Note: Enumeration of time-zone transitions is for informational purposes - // only. Modern time-related code should not care about when offset changes - // occur. - // - // Example: - // cctz::time_zone nyc; - // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } - // const auto now = std::chrono::system_clock::now(); - // auto tp = cctz::time_point<cctz::seconds>::min(); - // cctz::time_zone::civil_transition trans; - // while (tp <= now && nyc.next_transition(tp, &trans)) { - // // transition: trans.from -> trans.to - // tp = nyc.lookup(trans.to).trans; - // } - struct civil_transition { - civil_second from; // the civil time we jump from - civil_second to; // the civil time we jump to - }; - bool next_transition(const time_point<seconds>& tp, - civil_transition* trans) const; - template <typename D> - bool next_transition(const time_point<D>& tp, civil_transition* trans) const { - return next_transition(detail::split_seconds(tp).first, trans); - } - bool prev_transition(const time_point<seconds>& tp, - civil_transition* trans) const; - template <typename D> - bool prev_transition(const time_point<D>& tp, civil_transition* trans) const { - return prev_transition(detail::split_seconds(tp).first, trans); - } - - // version() and description() provide additional information about the - // time zone. The content of each of the returned strings is unspecified, - // however, when the IANA Time Zone Database is the underlying data source - // the version() string will be in the familar form (e.g, "2018e") or - // empty when unavailable. - // - // Note: These functions are for informational or testing purposes only. - std::string version() const; // empty when unknown - std::string description() const; - - // Relational operators. - friend bool operator==(time_zone lhs, time_zone rhs) { - return &lhs.effective_impl() == &rhs.effective_impl(); - } - friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); } - - template <typename H> - friend H AbslHashValue(H h, time_zone tz) { - return H::combine(std::move(h), &tz.effective_impl()); - } - - class Impl; - - private: - explicit time_zone(const Impl* impl) : impl_(impl) {} - const Impl& effective_impl() const; // handles implicit UTC - const Impl* impl_; -}; - -// Loads the named time zone. May perform I/O on the initial load. -// If the name is invalid, or some other kind of error occurs, returns -// false and "*tz" is set to the UTC time zone. -bool load_time_zone(const std::string& name, time_zone* tz); - -// Returns a time_zone representing UTC. Cannot fail. -time_zone utc_time_zone(); - -// Returns a time zone that is a fixed offset (seconds east) from UTC. -// Note: If the absolute value of the offset is greater than 24 hours -// you'll get UTC (i.e., zero offset) instead. -time_zone fixed_time_zone(const seconds& offset); - -// Returns a time zone representing the local time zone. Falls back to UTC. -// Note: local_time_zone.name() may only be something like "localtime". -time_zone local_time_zone(); - -// Returns the civil time (cctz::civil_second) within the given time zone at -// the given absolute time (time_point). Since the additional fields provided -// by the time_zone::absolute_lookup struct should rarely be needed in modern -// code, this convert() function is simpler and should be preferred. -template <typename D> -inline civil_second convert(const time_point<D>& tp, const time_zone& tz) { - return tz.lookup(tp).cs; -} - -// Returns the absolute time (time_point) that corresponds to the given civil -// time within the given time zone. If the civil time is not unique (i.e., if -// it was either repeated or non-existent), then the returned time_point is -// the best estimate that preserves relative order. That is, this function -// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). -inline time_point<seconds> convert(const civil_second& cs, - const time_zone& tz) { - const time_zone::civil_lookup cl = tz.lookup(cs); - if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; - return cl.pre; -} - -namespace detail { -using femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>; -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); -} // namespace detail - -// Formats the given time_point in the given cctz::time_zone according to -// the provided format string. Uses strftime()-like formatting options, -// with the following extensions: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %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'. -// -// Note that %Y produces as many characters as it takes to fully render the -// year. A year outside of [-999:9999] when formatted with %E4Y will produce -// more than four characters, just like %Y. -// -// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z) -// so that the resulting string uniquely identifies an absolute time. -// -// Example: -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); -// std::string f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05" -// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" -template <typename D> -inline std::string format(const std::string& fmt, const time_point<D>& tp, - const time_zone& tz) { - const auto p = detail::split_seconds(tp); - const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second); - return detail::format(fmt, p.first, n, tz); -} - -// Parses an input string according to the provided format string and -// 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'. -// -// %Y consumes as many numeric characters as it can, so the matching data -// should always be terminated with a non-numeric. %E4Y always consumes -// exactly four characters, including any sign. -// -// Unspecified fields are taken from the default date and time of ... -// -// "1970-01-01 00:00:00.0 +0000" -// -// For example, parsing a string of "15:45" (%H:%M) will return a time_point -// that represents "1970-01-01 15:45:00.0 +0000". -// -// Note that parse() returns time instants, so it makes most sense to parse -// fully-specified date/time strings that include a UTC offset (%z, %Ez, or -// %E*z). -// -// Note also that parse() only heeds the fields year, month, day, hour, -// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a -// or %A), while parsed for syntactic validity, are ignored in the conversion. -// -// Date and time fields that are out-of-range will be treated as errors rather -// than normalizing them like cctz::civil_second() would do. For example, it -// is an error to parse the date "Oct 32, 2013" because 32 is out of range. -// -// A second of ":60" is normalized to ":00" of the following minute with -// fractional seconds discarded. The following table shows how the given -// seconds and subseconds will be parsed: -// -// "59.x" -> 59.x // exact -// "60.x" -> 00.0 // normalized -// "00.x" -> 00.x // exact -// -// Errors are indicated by returning false. -// -// Example: -// const cctz::time_zone tz = ... -// std::chrono::system_clock::time_point tp; -// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { -// ... -// } -template <typename D> -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; - 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 b; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ 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 deleted file mode 100644 index 012eb4ec30e0..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ -#define ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ - -#include <cstddef> -#include <functional> -#include <memory> -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A stdio-like interface for providing zoneinfo data for a particular zone. -class ZoneInfoSource { - public: - virtual ~ZoneInfoSource(); - - virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() - virtual int Skip(std::size_t offset) = 0; // like fseek() - - // 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. - virtual std::string Version() const; -}; - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz_extension { - -// A function-pointer type for a factory that returns a ZoneInfoSource -// given the name of a time zone and a fallback factory. Returns null -// when the data for the named zone cannot be found. -using ZoneInfoSourceFactory = - std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)( - const std::string&, - const std::function<std::unique_ptr< - absl::time_internal::cctz::ZoneInfoSource>(const std::string&)>&); - -// The user can control the mapping of zone names to zoneinfo data by -// providing a definition for cctz_extension::zone_info_source_factory. -// For example, given functions my_factory() and my_other_factory() that -// can return a ZoneInfoSource for a named zone, we could inject them into -// cctz::load_time_zone() with: -// -// namespace cctz_extension { -// namespace { -// std::unique_ptr<cctz::ZoneInfoSource> CustomFactory( -// const std::string& name, -// const std::function<std::unique_ptr<cctz::ZoneInfoSource>( -// const std::string& name)>& fallback_factory) { -// if (auto zip = my_factory(name)) return zip; -// if (auto zip = fallback_factory(name)) return zip; -// if (auto zip = my_other_factory(name)) return zip; -// return nullptr; -// } -// } // namespace -// ZoneInfoSourceFactory zone_info_source_factory = CustomFactory; -// } // namespace cctz_extension -// -// This might be used, say, to use zoneinfo data embedded in the program, -// or read from a (possibly compressed) file archive, or both. -// -// cctz_extension::zone_info_source_factory() will be called: -// (1) from the same thread as the cctz::load_time_zone() call, -// (2) only once for any zone name, and -// (3) serially (i.e., no concurrent execution). -// -// The fallback factory obtains zoneinfo data by reading files in ${TZDIR}, -// and it is used automatically when no zone_info_source_factory definition -// is linked into the program. -extern ZoneInfoSourceFactory zone_info_source_factory; - -} // namespace cctz_extension -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ diff --git a/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 deleted file mode 100644 index 4e39188ff3e6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/cctz_benchmark.cc +++ /dev/null @@ -1,1030 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <algorithm> -#include <cassert> -#include <chrono> -#include <ctime> -#include <random> -#include <string> -#include <vector> - -#include "benchmark/benchmark.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" -#include "time_zone_impl.h" - -namespace { - -namespace cctz = absl::time_internal::cctz; - -void BM_Difference_Days(benchmark::State& state) { - const cctz::civil_day c(2014, 8, 22); - const cctz::civil_day epoch(1970, 1, 1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(c - epoch); - } -} -BENCHMARK(BM_Difference_Days); - -void BM_Step_Days(benchmark::State& state) { - const cctz::civil_day kStart(2014, 8, 22); - cctz::civil_day c = kStart; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(++c); - } -} -BENCHMARK(BM_Step_Days); - -void BM_GetWeekday(benchmark::State& state) { - const cctz::civil_day c(2014, 8, 22); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::get_weekday(c)); - } -} -BENCHMARK(BM_GetWeekday); - -void BM_NextWeekday(benchmark::State& state) { - const cctz::civil_day kStart(2014, 8, 22); - const cctz::civil_day kDays[7] = { - kStart + 0, kStart + 1, kStart + 2, kStart + 3, - kStart + 4, kStart + 5, kStart + 6, - }; - const cctz::weekday kWeekdays[7] = { - cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday, - cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday, - cctz::weekday::sunday, - }; - while (state.KeepRunningBatch(7 * 7)) { - for (const auto from : kDays) { - for (const auto to : kWeekdays) { - benchmark::DoNotOptimize(cctz::next_weekday(from, to)); - } - } - } -} -BENCHMARK(BM_NextWeekday); - -void BM_PrevWeekday(benchmark::State& state) { - const cctz::civil_day kStart(2014, 8, 22); - const cctz::civil_day kDays[7] = { - kStart + 0, kStart + 1, kStart + 2, kStart + 3, - kStart + 4, kStart + 5, kStart + 6, - }; - const cctz::weekday kWeekdays[7] = { - cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday, - cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday, - cctz::weekday::sunday, - }; - while (state.KeepRunningBatch(7 * 7)) { - for (const auto from : kDays) { - for (const auto to : kWeekdays) { - benchmark::DoNotOptimize(cctz::prev_weekday(from, to)); - } - } - } -} -BENCHMARK(BM_PrevWeekday); - -const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez"; -const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; - -const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; -const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; - -// A list of known time-zone names. -// TODO: Refactor with src/time_zone_lookup_test.cc. -const char* const kTimeZoneNames[] = {"Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Nelson", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Nuuk", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Punta_Arenas", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Atyrau", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Barnaul", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Famagusta", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qostanay", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Tomsk", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yangon", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Astrakhan", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Kirov", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Saratov", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Ulyanovsk", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr}; - -std::vector<std::string> AllTimeZoneNames() { - std::vector<std::string> names; - for (const char* const* namep = kTimeZoneNames; *namep != nullptr; ++namep) { - names.push_back(std::string("file:") + *namep); - } - assert(!names.empty()); - - std::mt19937 urbg(42); // a UniformRandomBitGenerator with fixed seed - std::shuffle(names.begin(), names.end(), urbg); - return names; -} - -cctz::time_zone TestTimeZone() { - cctz::time_zone tz; - cctz::load_time_zone("America/Los_Angeles", &tz); - return tz; -} - -void BM_Zone_LoadUTCTimeZoneFirst(benchmark::State& state) { - cctz::time_zone tz; - cctz::load_time_zone("UTC", &tz); // in case we're first - cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz)); - } -} -BENCHMARK(BM_Zone_LoadUTCTimeZoneFirst); - -void BM_Zone_LoadUTCTimeZoneLast(benchmark::State& state) { - cctz::time_zone tz; - for (const auto& name : AllTimeZoneNames()) { - cctz::load_time_zone(name, &tz); // prime cache - } - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz)); - } -} -BENCHMARK(BM_Zone_LoadUTCTimeZoneLast); - -void BM_Zone_LoadTimeZoneFirst(benchmark::State& state) { - cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first - const std::string name = "file:America/Los_Angeles"; - while (state.KeepRunning()) { - state.PauseTiming(); - cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); - state.ResumeTiming(); - benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz)); - } -} -BENCHMARK(BM_Zone_LoadTimeZoneFirst); - -void BM_Zone_LoadTimeZoneCached(benchmark::State& state) { - cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first - cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); - const std::string name = "file:America/Los_Angeles"; - cctz::load_time_zone(name, &tz); // prime cache - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz)); - } -} -BENCHMARK(BM_Zone_LoadTimeZoneCached); - -void BM_Zone_LoadLocalTimeZoneCached(benchmark::State& state) { - cctz::utc_time_zone(); // in case we're first - cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); - cctz::local_time_zone(); // prime cache - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::local_time_zone()); - } -} -BENCHMARK(BM_Zone_LoadLocalTimeZoneCached); - -void BM_Zone_LoadAllTimeZonesFirst(benchmark::State& state) { - cctz::time_zone tz; - const std::vector<std::string> names = AllTimeZoneNames(); - for (auto index = names.size(); state.KeepRunning(); ++index) { - if (index == names.size()) { - index = 0; - } - if (index == 0) { - state.PauseTiming(); - cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); - state.ResumeTiming(); - } - benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz)); - } -} -BENCHMARK(BM_Zone_LoadAllTimeZonesFirst); - -void BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) { - cctz::time_zone tz; - const std::vector<std::string> names = AllTimeZoneNames(); - for (const auto& name : names) { - cctz::load_time_zone(name, &tz); // prime cache - } - for (auto index = names.size(); state.KeepRunning(); ++index) { - if (index == names.size()) { - index = 0; - } - benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz)); - } -} -BENCHMARK(BM_Zone_LoadAllTimeZonesCached); - -void BM_Zone_TimeZoneEqualityImplicit(benchmark::State& state) { - cctz::time_zone tz; // implicit UTC - while (state.KeepRunning()) { - benchmark::DoNotOptimize(tz == tz); - } -} -BENCHMARK(BM_Zone_TimeZoneEqualityImplicit); - -void BM_Zone_TimeZoneEqualityExplicit(benchmark::State& state) { - cctz::time_zone tz = cctz::utc_time_zone(); // explicit UTC - while (state.KeepRunning()) { - benchmark::DoNotOptimize(tz == tz); - } -} -BENCHMARK(BM_Zone_TimeZoneEqualityExplicit); - -void BM_Zone_UTCTimeZone(benchmark::State& state) { - cctz::time_zone tz; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::utc_time_zone()); - } -} -BENCHMARK(BM_Zone_UTCTimeZone); - -// In each "ToCivil" benchmark we switch between two instants separated -// by at least one transition in order to defeat any internal caching of -// previous results (e.g., see local_time_hint_). -// -// The "UTC" variants use UTC instead of the Google/local time zone. - -void BM_Time_ToCivil_CCTZ(benchmark::State& state) { - const cctz::time_zone tz = TestTimeZone(); - std::chrono::system_clock::time_point tp = - std::chrono::system_clock::from_time_t(1384569027); - std::chrono::system_clock::time_point tp2 = - std::chrono::system_clock::from_time_t(1418962578); - while (state.KeepRunning()) { - std::swap(tp, tp2); - tp += std::chrono::seconds(1); - benchmark::DoNotOptimize(cctz::convert(tp, tz)); - } -} -BENCHMARK(BM_Time_ToCivil_CCTZ); - -void BM_Time_ToCivil_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - time_t t = 1384569027; - time_t t2 = 1418962578; - struct tm tm; - while (state.KeepRunning()) { - std::swap(t, t2); - t += 1; -#if defined(_WIN32) || defined(_WIN64) - benchmark::DoNotOptimize(localtime_s(&tm, &t)); -#else - benchmark::DoNotOptimize(localtime_r(&t, &tm)); -#endif - } -} -BENCHMARK(BM_Time_ToCivil_Libc); - -void BM_Time_ToCivilUTC_CCTZ(benchmark::State& state) { - const cctz::time_zone tz = cctz::utc_time_zone(); - std::chrono::system_clock::time_point tp = - std::chrono::system_clock::from_time_t(1384569027); - while (state.KeepRunning()) { - tp += std::chrono::seconds(1); - benchmark::DoNotOptimize(cctz::convert(tp, tz)); - } -} -BENCHMARK(BM_Time_ToCivilUTC_CCTZ); - -void BM_Time_ToCivilUTC_Libc(benchmark::State& state) { - time_t t = 1384569027; - struct tm tm; - while (state.KeepRunning()) { - t += 1; -#if defined(_WIN32) || defined(_WIN64) - benchmark::DoNotOptimize(gmtime_s(&tm, &t)); -#else - benchmark::DoNotOptimize(gmtime_r(&t, &tm)); -#endif - } -} -BENCHMARK(BM_Time_ToCivilUTC_Libc); - -// In each "FromCivil" benchmark we switch between two YMDhms values -// separated by at least one transition in order to defeat any internal -// caching of previous results (e.g., see time_local_hint_). -// -// The "UTC" variants use UTC instead of the Google/local time zone. -// The "Day0" variants require normalization of the day of month. - -void BM_Time_FromCivil_CCTZ(benchmark::State& state) { - const cctz::time_zone tz = TestTimeZone(); - int i = 0; - while (state.KeepRunning()) { - if ((i++ & 1) == 0) { - benchmark::DoNotOptimize( - cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz)); - } else { - benchmark::DoNotOptimize( - cctz::convert(cctz::civil_second(2013, 11, 15, 18, 30, 27), tz)); - } - } -} -BENCHMARK(BM_Time_FromCivil_CCTZ); - -void BM_Time_FromCivil_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - int i = 0; - while (state.KeepRunning()) { - struct tm tm; - if ((i++ & 1) == 0) { - tm.tm_year = 2014 - 1900; - tm.tm_mon = 12 - 1; - tm.tm_mday = 18; - tm.tm_hour = 20; - tm.tm_min = 16; - tm.tm_sec = 18; - } else { - tm.tm_year = 2013 - 1900; - tm.tm_mon = 11 - 1; - tm.tm_mday = 15; - tm.tm_hour = 18; - tm.tm_min = 30; - tm.tm_sec = 27; - } - tm.tm_isdst = -1; - benchmark::DoNotOptimize(mktime(&tm)); - } -} -BENCHMARK(BM_Time_FromCivil_Libc); - -void BM_Time_FromCivilUTC_CCTZ(benchmark::State& state) { - const cctz::time_zone tz = cctz::utc_time_zone(); - while (state.KeepRunning()) { - benchmark::DoNotOptimize( - cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz)); - } -} -BENCHMARK(BM_Time_FromCivilUTC_CCTZ); - -// There is no BM_Time_FromCivilUTC_Libc. - -void BM_Time_FromCivilDay0_CCTZ(benchmark::State& state) { - const cctz::time_zone tz = TestTimeZone(); - int i = 0; - while (state.KeepRunning()) { - if ((i++ & 1) == 0) { - benchmark::DoNotOptimize( - cctz::convert(cctz::civil_second(2014, 12, 0, 20, 16, 18), tz)); - } else { - benchmark::DoNotOptimize( - cctz::convert(cctz::civil_second(2013, 11, 0, 18, 30, 27), tz)); - } - } -} -BENCHMARK(BM_Time_FromCivilDay0_CCTZ); - -void BM_Time_FromCivilDay0_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - int i = 0; - while (state.KeepRunning()) { - struct tm tm; - if ((i++ & 1) == 0) { - tm.tm_year = 2014 - 1900; - tm.tm_mon = 12 - 1; - tm.tm_mday = 0; - tm.tm_hour = 20; - tm.tm_min = 16; - tm.tm_sec = 18; - } else { - tm.tm_year = 2013 - 1900; - tm.tm_mon = 11 - 1; - tm.tm_mday = 0; - tm.tm_hour = 18; - tm.tm_min = 30; - tm.tm_sec = 27; - } - tm.tm_isdst = -1; - benchmark::DoNotOptimize(mktime(&tm)); - } -} -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 -}; -const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); - -void BM_Format_FormatTime(benchmark::State& state) { - const std::string fmt = kFormats[state.range(0)]; - state.SetLabel(fmt); - const cctz::time_zone tz = TestTimeZone(); - const std::chrono::system_clock::time_point tp = - cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) + - std::chrono::microseconds(1); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::format(fmt, tp, tz)); - } -} -BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1); - -void BM_Format_ParseTime(benchmark::State& state) { - const std::string fmt = kFormats[state.range(0)]; - state.SetLabel(fmt); - const cctz::time_zone tz = TestTimeZone(); - std::chrono::system_clock::time_point tp = - cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) + - std::chrono::microseconds(1); - const std::string when = cctz::format(fmt, tp, tz); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(cctz::parse(fmt, when, tz, &tp)); - } -} -BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1); - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/civil_time_detail.cc b/third_party/abseil_cpp/absl/time/internal/cctz/src/civil_time_detail.cc deleted file mode 100644 index 0b07e397e560..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/civil_time_detail.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/time/internal/cctz/include/cctz/civil_time_detail.h" - -#include <iomanip> -#include <ostream> -#include <sstream> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { -namespace detail { - -// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss, -// while omitting fields inferior to the type's alignment. For example, -// civil_day is formatted only as YYYY-MM-DD. -std::ostream& operator<<(std::ostream& os, const civil_year& y) { - std::stringstream ss; - ss << y.year(); // No padding. - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_month& m) { - std::stringstream ss; - ss << civil_year(m) << '-'; - ss << std::setfill('0') << std::setw(2) << m.month(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_day& d) { - std::stringstream ss; - ss << civil_month(d) << '-'; - ss << std::setfill('0') << std::setw(2) << d.day(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_hour& h) { - std::stringstream ss; - ss << civil_day(h) << 'T'; - ss << std::setfill('0') << std::setw(2) << h.hour(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_minute& m) { - std::stringstream ss; - ss << civil_hour(m) << ':'; - ss << std::setfill('0') << std::setw(2) << m.minute(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_second& s) { - std::stringstream ss; - ss << civil_minute(s) << ':'; - ss << std::setfill('0') << std::setw(2) << s.second(); - return os << ss.str(); -} - -//////////////////////////////////////////////////////////////////////// - -std::ostream& operator<<(std::ostream& os, weekday wd) { - switch (wd) { - case weekday::monday: - return os << "Monday"; - case weekday::tuesday: - return os << "Tuesday"; - case weekday::wednesday: - return os << "Wednesday"; - case weekday::thursday: - return os << "Thursday"; - case weekday::friday: - return os << "Friday"; - case weekday::saturday: - return os << "Saturday"; - case weekday::sunday: - return os << "Sunday"; - } - return os; // Should never get here, but -Wreturn-type may warn without this. -} - -} // namespace detail -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index a5a71230419f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/civil_time_test.cc +++ /dev/null @@ -1,1066 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/time/internal/cctz/include/cctz/civil_time.h" - -#include <iomanip> -#include <limits> -#include <sstream> -#include <string> -#include <type_traits> - -#include "gtest/gtest.h" -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -template <typename T> -std::string Format(const T& t) { - std::stringstream ss; - ss << t; - return ss.str(); -} - -} // namespace - -#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) -// Construction constexpr tests - -TEST(CivilTime, Normal) { - constexpr civil_second css(2016, 1, 28, 17, 14, 12); - static_assert(css.second() == 12, "Normal.second"); - constexpr civil_minute cmm(2016, 1, 28, 17, 14); - static_assert(cmm.minute() == 14, "Normal.minute"); - constexpr civil_hour chh(2016, 1, 28, 17); - static_assert(chh.hour() == 17, "Normal.hour"); - constexpr civil_day cd(2016, 1, 28); - static_assert(cd.day() == 28, "Normal.day"); - constexpr civil_month cm(2016, 1); - static_assert(cm.month() == 1, "Normal.month"); - constexpr civil_year cy(2016); - static_assert(cy.year() == 2016, "Normal.year"); -} - -TEST(CivilTime, Conversion) { - constexpr civil_year cy(2016); - static_assert(cy.year() == 2016, "Conversion.year"); - constexpr civil_month cm(cy); - static_assert(cm.month() == 1, "Conversion.month"); - constexpr civil_day cd(cm); - static_assert(cd.day() == 1, "Conversion.day"); - constexpr civil_hour chh(cd); - static_assert(chh.hour() == 0, "Conversion.hour"); - constexpr civil_minute cmm(chh); - static_assert(cmm.minute() == 0, "Conversion.minute"); - constexpr civil_second css(cmm); - static_assert(css.second() == 0, "Conversion.second"); -} - -// Normalization constexpr tests - -TEST(CivilTime, Normalized) { - constexpr civil_second cs(2016, 1, 28, 17, 14, 12); - static_assert(cs.year() == 2016, "Normalized.year"); - static_assert(cs.month() == 1, "Normalized.month"); - static_assert(cs.day() == 28, "Normalized.day"); - static_assert(cs.hour() == 17, "Normalized.hour"); - static_assert(cs.minute() == 14, "Normalized.minute"); - static_assert(cs.second() == 12, "Normalized.second"); -} - -TEST(CivilTime, SecondOverflow) { - constexpr civil_second cs(2016, 1, 28, 17, 14, 121); - static_assert(cs.year() == 2016, "SecondOverflow.year"); - static_assert(cs.month() == 1, "SecondOverflow.month"); - static_assert(cs.day() == 28, "SecondOverflow.day"); - static_assert(cs.hour() == 17, "SecondOverflow.hour"); - static_assert(cs.minute() == 16, "SecondOverflow.minute"); - static_assert(cs.second() == 1, "SecondOverflow.second"); -} - -TEST(CivilTime, SecondUnderflow) { - constexpr civil_second cs(2016, 1, 28, 17, 14, -121); - static_assert(cs.year() == 2016, "SecondUnderflow.year"); - static_assert(cs.month() == 1, "SecondUnderflow.month"); - static_assert(cs.day() == 28, "SecondUnderflow.day"); - static_assert(cs.hour() == 17, "SecondUnderflow.hour"); - static_assert(cs.minute() == 11, "SecondUnderflow.minute"); - static_assert(cs.second() == 59, "SecondUnderflow.second"); -} - -TEST(CivilTime, MinuteOverflow) { - constexpr civil_second cs(2016, 1, 28, 17, 121, 12); - static_assert(cs.year() == 2016, "MinuteOverflow.year"); - static_assert(cs.month() == 1, "MinuteOverflow.month"); - static_assert(cs.day() == 28, "MinuteOverflow.day"); - static_assert(cs.hour() == 19, "MinuteOverflow.hour"); - static_assert(cs.minute() == 1, "MinuteOverflow.minute"); - static_assert(cs.second() == 12, "MinuteOverflow.second"); -} - -TEST(CivilTime, MinuteUnderflow) { - constexpr civil_second cs(2016, 1, 28, 17, -121, 12); - static_assert(cs.year() == 2016, "MinuteUnderflow.year"); - static_assert(cs.month() == 1, "MinuteUnderflow.month"); - static_assert(cs.day() == 28, "MinuteUnderflow.day"); - static_assert(cs.hour() == 14, "MinuteUnderflow.hour"); - static_assert(cs.minute() == 59, "MinuteUnderflow.minute"); - static_assert(cs.second() == 12, "MinuteUnderflow.second"); -} - -TEST(CivilTime, HourOverflow) { - constexpr civil_second cs(2016, 1, 28, 49, 14, 12); - static_assert(cs.year() == 2016, "HourOverflow.year"); - static_assert(cs.month() == 1, "HourOverflow.month"); - static_assert(cs.day() == 30, "HourOverflow.day"); - static_assert(cs.hour() == 1, "HourOverflow.hour"); - static_assert(cs.minute() == 14, "HourOverflow.minute"); - static_assert(cs.second() == 12, "HourOverflow.second"); -} - -TEST(CivilTime, HourUnderflow) { - constexpr civil_second cs(2016, 1, 28, -49, 14, 12); - static_assert(cs.year() == 2016, "HourUnderflow.year"); - static_assert(cs.month() == 1, "HourUnderflow.month"); - static_assert(cs.day() == 25, "HourUnderflow.day"); - static_assert(cs.hour() == 23, "HourUnderflow.hour"); - static_assert(cs.minute() == 14, "HourUnderflow.minute"); - static_assert(cs.second() == 12, "HourUnderflow.second"); -} - -TEST(CivilTime, MonthOverflow) { - constexpr civil_second cs(2016, 25, 28, 17, 14, 12); - static_assert(cs.year() == 2018, "MonthOverflow.year"); - static_assert(cs.month() == 1, "MonthOverflow.month"); - static_assert(cs.day() == 28, "MonthOverflow.day"); - static_assert(cs.hour() == 17, "MonthOverflow.hour"); - static_assert(cs.minute() == 14, "MonthOverflow.minute"); - static_assert(cs.second() == 12, "MonthOverflow.second"); -} - -TEST(CivilTime, MonthUnderflow) { - constexpr civil_second cs(2016, -25, 28, 17, 14, 12); - static_assert(cs.year() == 2013, "MonthUnderflow.year"); - static_assert(cs.month() == 11, "MonthUnderflow.month"); - static_assert(cs.day() == 28, "MonthUnderflow.day"); - static_assert(cs.hour() == 17, "MonthUnderflow.hour"); - static_assert(cs.minute() == 14, "MonthUnderflow.minute"); - static_assert(cs.second() == 12, "MonthUnderflow.second"); -} - -TEST(CivilTime, C4Overflow) { - constexpr civil_second cs(2016, 1, 292195, 17, 14, 12); - static_assert(cs.year() == 2816, "C4Overflow.year"); - static_assert(cs.month() == 1, "C4Overflow.month"); - static_assert(cs.day() == 1, "C4Overflow.day"); - static_assert(cs.hour() == 17, "C4Overflow.hour"); - static_assert(cs.minute() == 14, "C4Overflow.minute"); - static_assert(cs.second() == 12, "C4Overflow.second"); -} - -TEST(CivilTime, C4Underflow) { - constexpr civil_second cs(2016, 1, -292195, 17, 14, 12); - static_assert(cs.year() == 1215, "C4Underflow.year"); - static_assert(cs.month() == 12, "C4Underflow.month"); - static_assert(cs.day() == 30, "C4Underflow.day"); - static_assert(cs.hour() == 17, "C4Underflow.hour"); - static_assert(cs.minute() == 14, "C4Underflow.minute"); - static_assert(cs.second() == 12, "C4Underflow.second"); -} - -TEST(CivilTime, MixedNormalization) { - constexpr civil_second cs(2016, -42, 122, 99, -147, 4949); - static_assert(cs.year() == 2012, "MixedNormalization.year"); - static_assert(cs.month() == 10, "MixedNormalization.month"); - static_assert(cs.day() == 4, "MixedNormalization.day"); - static_assert(cs.hour() == 1, "MixedNormalization.hour"); - static_assert(cs.minute() == 55, "MixedNormalization.minute"); - static_assert(cs.second() == 29, "MixedNormalization.second"); -} - -// Relational constexpr tests - -TEST(CivilTime, Less) { - constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); - constexpr civil_second cs2(2016, 1, 28, 17, 14, 13); - constexpr bool less = cs1 < cs2; - static_assert(less, "Less"); -} - -// Arithmetic constexpr tests - -TEST(CivilTime, Addition) { - constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); - constexpr civil_second cs2 = cs1 + 50; - static_assert(cs2.year() == 2016, "Addition.year"); - static_assert(cs2.month() == 1, "Addition.month"); - static_assert(cs2.day() == 28, "Addition.day"); - static_assert(cs2.hour() == 17, "Addition.hour"); - static_assert(cs2.minute() == 15, "Addition.minute"); - static_assert(cs2.second() == 2, "Addition.second"); -} - -TEST(CivilTime, Subtraction) { - constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); - constexpr civil_second cs2 = cs1 - 50; - static_assert(cs2.year() == 2016, "Subtraction.year"); - static_assert(cs2.month() == 1, "Subtraction.month"); - static_assert(cs2.day() == 28, "Subtraction.day"); - static_assert(cs2.hour() == 17, "Subtraction.hour"); - static_assert(cs2.minute() == 13, "Subtraction.minute"); - static_assert(cs2.second() == 22, "Subtraction.second"); -} - -TEST(CivilTime, Difference) { - constexpr civil_day cd1(2016, 1, 28); - constexpr civil_day cd2(2015, 1, 28); - constexpr int diff = cd1 - cd2; - static_assert(diff == 365, "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); - constexpr civil_day d2(9223372036854775807, 12, 31); - static_assert(d2 - d1 == 364, "DifferenceWithHugeYear"); - } - { - constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); - constexpr civil_day d2(-9223372036854775807 - 1, 12, 31); - static_assert(d2 - d1 == 365, "DifferenceWithHugeYear"); - } - { - // Check the limits of the return value at the end of the year range. - constexpr civil_day d1(9223372036854775807, 1, 1); - constexpr civil_day d2(9198119301927009252, 6, 6); - static_assert(d1 - d2 == 9223372036854775807, "DifferenceWithHugeYear"); - static_assert((d2 - 1) - d1 == -9223372036854775807 - 1, - "DifferenceWithHugeYear"); - } - { - // Check the limits of the return value at the start of the year range. - constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); - constexpr civil_day d2(-9198119301927009254, 7, 28); - static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); - static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, - "DifferenceWithHugeYear"); - } - { - // Check the limits of the return value from either side of year 0. - constexpr civil_day d1(-12626367463883278, 9, 3); - constexpr civil_day d2(12626367463883277, 3, 28); - static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); - static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, - "DifferenceWithHugeYear"); - } -} - -// NOTE: Run this with --copt=-ftrapv to detect overflow problems. -TEST(CivilTime, DifferenceNoIntermediateOverflow) { - { - // The difference up to the minute field would be below the minimum - // diff_t, but the 52 extra seconds brings us back to the minimum. - constexpr civil_second s1(-292277022657, 1, 27, 8, 29 - 1, 52); - constexpr civil_second s2(1970, 1, 1, 0, 0 - 1, 0); - static_assert(s1 - s2 == -9223372036854775807 - 1, - "DifferenceNoIntermediateOverflow"); - } - { - // The difference up to the minute field would be above the maximum - // diff_t, but the -53 extra seconds brings us back to the maximum. - constexpr civil_second s1(292277026596, 12, 4, 15, 30, 7 - 7); - constexpr civil_second s2(1970, 1, 1, 0, 0, 0 - 7); - static_assert(s1 - s2 == 9223372036854775807, - "DifferenceNoIntermediateOverflow"); - } -} - -// Helper constexpr tests - -TEST(CivilTime, WeekDay) { - constexpr civil_day cd(2016, 1, 28); - constexpr weekday wd = get_weekday(cd); - static_assert(wd == weekday::thursday, "Weekday"); -} - -TEST(CivilTime, NextWeekDay) { - constexpr civil_day cd(2016, 1, 28); - constexpr civil_day next = next_weekday(cd, weekday::thursday); - static_assert(next.year() == 2016, "NextWeekDay.year"); - static_assert(next.month() == 2, "NextWeekDay.month"); - static_assert(next.day() == 4, "NextWeekDay.day"); -} - -TEST(CivilTime, PrevWeekDay) { - constexpr civil_day cd(2016, 1, 28); - constexpr civil_day prev = prev_weekday(cd, weekday::thursday); - static_assert(prev.year() == 2016, "PrevWeekDay.year"); - static_assert(prev.month() == 1, "PrevWeekDay.month"); - static_assert(prev.day() == 21, "PrevWeekDay.day"); -} - -TEST(CivilTime, YearDay) { - constexpr civil_day cd(2016, 1, 28); - constexpr int yd = get_yearday(cd); - static_assert(yd == 28, "YearDay"); -} -#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) - -// The remaining tests do not use constexpr. - -TEST(CivilTime, DefaultConstruction) { - civil_second ss; - EXPECT_EQ("1970-01-01T00:00:00", Format(ss)); - - civil_minute mm; - EXPECT_EQ("1970-01-01T00:00", Format(mm)); - - civil_hour hh; - EXPECT_EQ("1970-01-01T00", Format(hh)); - - civil_day d; - EXPECT_EQ("1970-01-01", Format(d)); - - civil_month m; - EXPECT_EQ("1970-01", Format(m)); - - civil_year y; - EXPECT_EQ("1970", Format(y)); -} - -TEST(CivilTime, StructMember) { - struct S { - civil_day day; - }; - S s = {}; - EXPECT_EQ(civil_day{}, s.day); -} - -TEST(CivilTime, FieldsConstruction) { - EXPECT_EQ("2015-01-02T03:04:05", Format(civil_second(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03:04:00", Format(civil_second(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03:00:00", Format(civil_second(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00:00:00", Format(civil_second(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00:00:00", Format(civil_second(2015, 1))); - EXPECT_EQ("2015-01-01T00:00:00", Format(civil_second(2015))); - - EXPECT_EQ("2015-01-02T03:04", Format(civil_minute(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03:04", Format(civil_minute(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03:00", Format(civil_minute(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00:00", Format(civil_minute(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00:00", Format(civil_minute(2015, 1))); - EXPECT_EQ("2015-01-01T00:00", Format(civil_minute(2015))); - - EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02T00", Format(civil_hour(2015, 1, 2))); - EXPECT_EQ("2015-01-01T00", Format(civil_hour(2015, 1))); - EXPECT_EQ("2015-01-01T00", Format(civil_hour(2015))); - - EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3))); - EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2))); - EXPECT_EQ("2015-01-01", Format(civil_day(2015, 1))); - EXPECT_EQ("2015-01-01", Format(civil_day(2015))); - - EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3))); - EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2))); - EXPECT_EQ("2015-01", Format(civil_month(2015, 1))); - EXPECT_EQ("2015-01", Format(civil_month(2015))); - - EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3, 4, 5))); - EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3, 4))); - EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3))); - EXPECT_EQ("2015", Format(civil_year(2015, 1, 2))); - EXPECT_EQ("2015", Format(civil_year(2015, 1))); - EXPECT_EQ("2015", Format(civil_year(2015))); -} - -TEST(CivilTime, FieldsConstructionLimits) { - const int kIntMax = std::numeric_limits<int>::max(); - EXPECT_EQ("2038-01-19T03:14:07", - Format(civil_second(1970, 1, 1, 0, 0, kIntMax))); - EXPECT_EQ("6121-02-11T05:21:07", - Format(civil_second(1970, 1, 1, 0, kIntMax, kIntMax))); - EXPECT_EQ("251104-11-20T12:21:07", - Format(civil_second(1970, 1, 1, kIntMax, kIntMax, kIntMax))); - EXPECT_EQ("6130715-05-30T12:21:07", - Format(civil_second(1970, 1, kIntMax, kIntMax, kIntMax, kIntMax))); - EXPECT_EQ( - "185087685-11-26T12:21:07", - Format(civil_second(1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax))); - - const int kIntMin = std::numeric_limits<int>::min(); - EXPECT_EQ("1901-12-13T20:45:52", - Format(civil_second(1970, 1, 1, 0, 0, kIntMin))); - EXPECT_EQ("-2182-11-20T18:37:52", - Format(civil_second(1970, 1, 1, 0, kIntMin, kIntMin))); - EXPECT_EQ("-247165-02-11T10:37:52", - Format(civil_second(1970, 1, 1, kIntMin, kIntMin, kIntMin))); - EXPECT_EQ("-6126776-08-01T10:37:52", - Format(civil_second(1970, 1, kIntMin, kIntMin, kIntMin, kIntMin))); - EXPECT_EQ( - "-185083747-10-31T10:37:52", - Format(civil_second(1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin))); -} - -TEST(CivilTime, ImplicitCrossAlignment) { - civil_year year(2015); - civil_month month = year; - civil_day day = month; - civil_hour hour = day; - civil_minute minute = hour; - civil_second second = minute; - - second = year; - EXPECT_EQ(second, year); - second = month; - EXPECT_EQ(second, month); - second = day; - EXPECT_EQ(second, day); - second = hour; - EXPECT_EQ(second, hour); - second = minute; - EXPECT_EQ(second, minute); - - minute = year; - EXPECT_EQ(minute, year); - minute = month; - EXPECT_EQ(minute, month); - minute = day; - EXPECT_EQ(minute, day); - minute = hour; - EXPECT_EQ(minute, hour); - - hour = year; - EXPECT_EQ(hour, year); - hour = month; - EXPECT_EQ(hour, month); - hour = day; - EXPECT_EQ(hour, day); - - day = year; - EXPECT_EQ(day, year); - day = month; - EXPECT_EQ(day, month); - - month = year; - EXPECT_EQ(month, year); - - // Ensures unsafe conversions are not allowed. - EXPECT_FALSE((std::is_convertible<civil_second, civil_minute>::value)); - EXPECT_FALSE((std::is_convertible<civil_second, civil_hour>::value)); - EXPECT_FALSE((std::is_convertible<civil_second, civil_day>::value)); - EXPECT_FALSE((std::is_convertible<civil_second, civil_month>::value)); - EXPECT_FALSE((std::is_convertible<civil_second, civil_year>::value)); - - EXPECT_FALSE((std::is_convertible<civil_minute, civil_hour>::value)); - EXPECT_FALSE((std::is_convertible<civil_minute, civil_day>::value)); - EXPECT_FALSE((std::is_convertible<civil_minute, civil_month>::value)); - EXPECT_FALSE((std::is_convertible<civil_minute, civil_year>::value)); - - EXPECT_FALSE((std::is_convertible<civil_hour, civil_day>::value)); - EXPECT_FALSE((std::is_convertible<civil_hour, civil_month>::value)); - EXPECT_FALSE((std::is_convertible<civil_hour, civil_year>::value)); - - EXPECT_FALSE((std::is_convertible<civil_day, civil_month>::value)); - EXPECT_FALSE((std::is_convertible<civil_day, civil_year>::value)); - - EXPECT_FALSE((std::is_convertible<civil_month, civil_year>::value)); -} - -TEST(CivilTime, ExplicitCrossAlignment) { - // - // Assign from smaller units -> larger units - // - - civil_second second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ("2015-01-02T03:04:05", Format(second)); - - civil_minute minute(second); - EXPECT_EQ("2015-01-02T03:04", Format(minute)); - - civil_hour hour(minute); - EXPECT_EQ("2015-01-02T03", Format(hour)); - - civil_day day(hour); - EXPECT_EQ("2015-01-02", Format(day)); - - civil_month month(day); - EXPECT_EQ("2015-01", Format(month)); - - civil_year year(month); - EXPECT_EQ("2015", Format(year)); - - // - // Now assign from larger units -> smaller units - // - - month = civil_month(year); - EXPECT_EQ("2015-01", Format(month)); - - day = civil_day(month); - EXPECT_EQ("2015-01-01", Format(day)); - - hour = civil_hour(day); - EXPECT_EQ("2015-01-01T00", Format(hour)); - - minute = civil_minute(hour); - EXPECT_EQ("2015-01-01T00:00", Format(minute)); - - second = civil_second(minute); - EXPECT_EQ("2015-01-01T00:00:00", Format(second)); -} - -// Metafunction to test whether difference is allowed between two types. -template <typename T1, typename T2> -struct HasDifference { - template <typename U1, typename U2> - static std::false_type test(...); - template <typename U1, typename U2> - static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>())); - static constexpr bool value = decltype(test<T1, T2>(0))::value; -}; - -TEST(CivilTime, DisallowCrossAlignedDifference) { - // Difference is allowed between types with the same alignment. - static_assert(HasDifference<civil_second, civil_second>::value, ""); - static_assert(HasDifference<civil_minute, civil_minute>::value, ""); - static_assert(HasDifference<civil_hour, civil_hour>::value, ""); - static_assert(HasDifference<civil_day, civil_day>::value, ""); - static_assert(HasDifference<civil_month, civil_month>::value, ""); - static_assert(HasDifference<civil_year, civil_year>::value, ""); - - // Difference is disallowed between types with different alignments. - static_assert(!HasDifference<civil_second, civil_minute>::value, ""); - static_assert(!HasDifference<civil_second, civil_hour>::value, ""); - static_assert(!HasDifference<civil_second, civil_day>::value, ""); - static_assert(!HasDifference<civil_second, civil_month>::value, ""); - static_assert(!HasDifference<civil_second, civil_year>::value, ""); - - static_assert(!HasDifference<civil_minute, civil_hour>::value, ""); - static_assert(!HasDifference<civil_minute, civil_day>::value, ""); - static_assert(!HasDifference<civil_minute, civil_month>::value, ""); - static_assert(!HasDifference<civil_minute, civil_year>::value, ""); - - static_assert(!HasDifference<civil_hour, civil_day>::value, ""); - static_assert(!HasDifference<civil_hour, civil_month>::value, ""); - static_assert(!HasDifference<civil_hour, civil_year>::value, ""); - - static_assert(!HasDifference<civil_day, civil_month>::value, ""); - static_assert(!HasDifference<civil_day, civil_year>::value, ""); - - static_assert(!HasDifference<civil_month, civil_year>::value, ""); -} - -TEST(CivilTime, ValueSemantics) { - const civil_hour a(2015, 1, 2, 3); - const civil_hour b = a; - const civil_hour c(b); - civil_hour d; - d = c; - EXPECT_EQ("2015-01-02T03", Format(d)); -} - -TEST(CivilTime, Relational) { - // Tests that the alignment unit is ignored in comparison. - const civil_year year(2014); - const civil_month month(year); - EXPECT_EQ(year, month); - -#define TEST_RELATIONAL(OLDER, YOUNGER) \ - do { \ - EXPECT_FALSE(OLDER < OLDER); \ - EXPECT_FALSE(OLDER > OLDER); \ - EXPECT_TRUE(OLDER >= OLDER); \ - EXPECT_TRUE(OLDER <= OLDER); \ - EXPECT_FALSE(YOUNGER < YOUNGER); \ - EXPECT_FALSE(YOUNGER > YOUNGER); \ - EXPECT_TRUE(YOUNGER >= YOUNGER); \ - EXPECT_TRUE(YOUNGER <= YOUNGER); \ - EXPECT_EQ(OLDER, OLDER); \ - EXPECT_NE(OLDER, YOUNGER); \ - EXPECT_LT(OLDER, YOUNGER); \ - EXPECT_LE(OLDER, YOUNGER); \ - EXPECT_GT(YOUNGER, OLDER); \ - EXPECT_GE(YOUNGER, OLDER); \ - } while (0) - - // Alignment is ignored in comparison (verified above), so kSecond is used - // to test comparison in all field positions. - TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), - civil_second(2015, 1, 1, 0, 0, 0)); - TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), - civil_second(2014, 2, 1, 0, 0, 0)); - TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), - civil_second(2014, 1, 2, 0, 0, 0)); - TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), - civil_second(2014, 1, 1, 1, 0, 0)); - TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 0, 0), - civil_second(2014, 1, 1, 1, 1, 0)); - TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0), - civil_second(2014, 1, 1, 1, 1, 1)); - - // Tests the relational operators of two different civil-time types. - TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1)); - TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2)); - -#undef TEST_RELATIONAL -} - -TEST(CivilTime, Arithmetic) { - civil_second second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ("2015-01-02T03:04:06", Format(second += 1)); - EXPECT_EQ("2015-01-02T03:04:07", Format(second + 1)); - EXPECT_EQ("2015-01-02T03:04:08", Format(2 + second)); - EXPECT_EQ("2015-01-02T03:04:05", Format(second - 1)); - EXPECT_EQ("2015-01-02T03:04:05", Format(second -= 1)); - EXPECT_EQ("2015-01-02T03:04:05", Format(second++)); - EXPECT_EQ("2015-01-02T03:04:07", Format(++second)); - EXPECT_EQ("2015-01-02T03:04:07", Format(second--)); - EXPECT_EQ("2015-01-02T03:04:05", Format(--second)); - - civil_minute minute(2015, 1, 2, 3, 4); - EXPECT_EQ("2015-01-02T03:05", Format(minute += 1)); - EXPECT_EQ("2015-01-02T03:06", Format(minute + 1)); - EXPECT_EQ("2015-01-02T03:07", Format(2 + minute)); - EXPECT_EQ("2015-01-02T03:04", Format(minute - 1)); - EXPECT_EQ("2015-01-02T03:04", Format(minute -= 1)); - EXPECT_EQ("2015-01-02T03:04", Format(minute++)); - EXPECT_EQ("2015-01-02T03:06", Format(++minute)); - EXPECT_EQ("2015-01-02T03:06", Format(minute--)); - EXPECT_EQ("2015-01-02T03:04", Format(--minute)); - - civil_hour hour(2015, 1, 2, 3); - EXPECT_EQ("2015-01-02T04", Format(hour += 1)); - EXPECT_EQ("2015-01-02T05", Format(hour + 1)); - EXPECT_EQ("2015-01-02T06", Format(2 + hour)); - EXPECT_EQ("2015-01-02T03", Format(hour - 1)); - EXPECT_EQ("2015-01-02T03", Format(hour -= 1)); - EXPECT_EQ("2015-01-02T03", Format(hour++)); - EXPECT_EQ("2015-01-02T05", Format(++hour)); - EXPECT_EQ("2015-01-02T05", Format(hour--)); - EXPECT_EQ("2015-01-02T03", Format(--hour)); - - civil_day day(2015, 1, 2); - EXPECT_EQ("2015-01-03", Format(day += 1)); - EXPECT_EQ("2015-01-04", Format(day + 1)); - EXPECT_EQ("2015-01-05", Format(2 + day)); - EXPECT_EQ("2015-01-02", Format(day - 1)); - EXPECT_EQ("2015-01-02", Format(day -= 1)); - EXPECT_EQ("2015-01-02", Format(day++)); - EXPECT_EQ("2015-01-04", Format(++day)); - EXPECT_EQ("2015-01-04", Format(day--)); - EXPECT_EQ("2015-01-02", Format(--day)); - - civil_month month(2015, 1); - EXPECT_EQ("2015-02", Format(month += 1)); - EXPECT_EQ("2015-03", Format(month + 1)); - EXPECT_EQ("2015-04", Format(2 + month)); - EXPECT_EQ("2015-01", Format(month - 1)); - EXPECT_EQ("2015-01", Format(month -= 1)); - EXPECT_EQ("2015-01", Format(month++)); - EXPECT_EQ("2015-03", Format(++month)); - EXPECT_EQ("2015-03", Format(month--)); - EXPECT_EQ("2015-01", Format(--month)); - - civil_year year(2015); - EXPECT_EQ("2016", Format(year += 1)); - EXPECT_EQ("2017", Format(year + 1)); - EXPECT_EQ("2018", Format(2 + year)); - EXPECT_EQ("2015", Format(year - 1)); - EXPECT_EQ("2015", Format(year -= 1)); - EXPECT_EQ("2015", Format(year++)); - EXPECT_EQ("2017", Format(++year)); - EXPECT_EQ("2017", Format(year--)); - EXPECT_EQ("2015", Format(--year)); -} - -TEST(CivilTime, ArithmeticLimits) { - const int kIntMax = std::numeric_limits<int>::max(); - const int kIntMin = std::numeric_limits<int>::min(); - - civil_second second(1970, 1, 1, 0, 0, 0); - second += kIntMax; - EXPECT_EQ("2038-01-19T03:14:07", Format(second)); - second -= kIntMax; - EXPECT_EQ("1970-01-01T00:00:00", Format(second)); - second += kIntMin; - EXPECT_EQ("1901-12-13T20:45:52", Format(second)); - second -= kIntMin; - EXPECT_EQ("1970-01-01T00:00:00", Format(second)); - - civil_minute minute(1970, 1, 1, 0, 0); - minute += kIntMax; - EXPECT_EQ("6053-01-23T02:07", Format(minute)); - minute -= kIntMax; - EXPECT_EQ("1970-01-01T00:00", Format(minute)); - minute += kIntMin; - EXPECT_EQ("-2114-12-08T21:52", Format(minute)); - minute -= kIntMin; - EXPECT_EQ("1970-01-01T00:00", Format(minute)); - - civil_hour hour(1970, 1, 1, 0); - hour += kIntMax; - EXPECT_EQ("246953-10-09T07", Format(hour)); - hour -= kIntMax; - EXPECT_EQ("1970-01-01T00", Format(hour)); - hour += kIntMin; - EXPECT_EQ("-243014-03-24T16", Format(hour)); - hour -= kIntMin; - EXPECT_EQ("1970-01-01T00", Format(hour)); - - civil_day day(1970, 1, 1); - day += kIntMax; - EXPECT_EQ("5881580-07-11", Format(day)); - day -= kIntMax; - EXPECT_EQ("1970-01-01", Format(day)); - day += kIntMin; - EXPECT_EQ("-5877641-06-23", Format(day)); - day -= kIntMin; - EXPECT_EQ("1970-01-01", Format(day)); - - civil_month month(1970, 1); - month += kIntMax; - EXPECT_EQ("178958940-08", Format(month)); - month -= kIntMax; - EXPECT_EQ("1970-01", Format(month)); - month += kIntMin; - EXPECT_EQ("-178955001-05", Format(month)); - month -= kIntMin; - EXPECT_EQ("1970-01", Format(month)); - - civil_year year(0); - year += kIntMax; - EXPECT_EQ("2147483647", Format(year)); - year -= kIntMax; - EXPECT_EQ("0", Format(year)); - year += kIntMin; - EXPECT_EQ("-2147483648", Format(year)); - year -= kIntMin; - EXPECT_EQ("0", Format(year)); -} - -TEST(CivilTime, ArithmeticDifference) { - civil_second second(2015, 1, 2, 3, 4, 5); - EXPECT_EQ(0, second - second); - EXPECT_EQ(10, (second + 10) - second); - EXPECT_EQ(-10, (second - 10) - second); - - civil_minute minute(2015, 1, 2, 3, 4); - EXPECT_EQ(0, minute - minute); - EXPECT_EQ(10, (minute + 10) - minute); - EXPECT_EQ(-10, (minute - 10) - minute); - - civil_hour hour(2015, 1, 2, 3); - EXPECT_EQ(0, hour - hour); - EXPECT_EQ(10, (hour + 10) - hour); - EXPECT_EQ(-10, (hour - 10) - hour); - - civil_day day(2015, 1, 2); - EXPECT_EQ(0, day - day); - EXPECT_EQ(10, (day + 10) - day); - EXPECT_EQ(-10, (day - 10) - day); - - civil_month month(2015, 1); - EXPECT_EQ(0, month - month); - EXPECT_EQ(10, (month + 10) - month); - EXPECT_EQ(-10, (month - 10) - month); - - civil_year year(2015); - EXPECT_EQ(0, year - year); - EXPECT_EQ(10, (year + 10) - year); - EXPECT_EQ(-10, (year - 10) - year); -} - -TEST(CivilTime, DifferenceLimits) { - const int kIntMax = std::numeric_limits<int>::max(); - const int kIntMin = std::numeric_limits<int>::min(); - - // Check day arithmetic at the end of the year range. - const civil_day max_day(kIntMax, 12, 31); - EXPECT_EQ(1, max_day - (max_day - 1)); - EXPECT_EQ(-1, (max_day - 1) - max_day); - - // Check day arithmetic at the end of the year range. - const civil_day min_day(kIntMin, 1, 1); - EXPECT_EQ(1, (min_day + 1) - min_day); - EXPECT_EQ(-1, min_day - (min_day + 1)); - - // Check the limits of the return value. - const civil_day d1(1970, 1, 1); - const civil_day d2(5881580, 7, 11); - EXPECT_EQ(kIntMax, d2 - d1); - EXPECT_EQ(kIntMin, d1 - (d2 + 1)); -} - -TEST(CivilTime, Properties) { - civil_second ss(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, ss.year()); - EXPECT_EQ(2, ss.month()); - EXPECT_EQ(3, ss.day()); - EXPECT_EQ(4, ss.hour()); - EXPECT_EQ(5, ss.minute()); - EXPECT_EQ(6, ss.second()); - EXPECT_EQ(weekday::tuesday, get_weekday(ss)); - EXPECT_EQ(34, get_yearday(ss)); - - civil_minute mm(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, mm.year()); - EXPECT_EQ(2, mm.month()); - EXPECT_EQ(3, mm.day()); - EXPECT_EQ(4, mm.hour()); - EXPECT_EQ(5, mm.minute()); - EXPECT_EQ(0, mm.second()); - EXPECT_EQ(weekday::tuesday, get_weekday(mm)); - EXPECT_EQ(34, get_yearday(mm)); - - civil_hour hh(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, hh.year()); - EXPECT_EQ(2, hh.month()); - EXPECT_EQ(3, hh.day()); - EXPECT_EQ(4, hh.hour()); - EXPECT_EQ(0, hh.minute()); - EXPECT_EQ(0, hh.second()); - EXPECT_EQ(weekday::tuesday, get_weekday(hh)); - EXPECT_EQ(34, get_yearday(hh)); - - civil_day d(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, d.year()); - EXPECT_EQ(2, d.month()); - EXPECT_EQ(3, d.day()); - EXPECT_EQ(0, d.hour()); - EXPECT_EQ(0, d.minute()); - EXPECT_EQ(0, d.second()); - EXPECT_EQ(weekday::tuesday, get_weekday(d)); - EXPECT_EQ(34, get_yearday(d)); - - civil_month m(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, m.year()); - EXPECT_EQ(2, m.month()); - EXPECT_EQ(1, m.day()); - EXPECT_EQ(0, m.hour()); - EXPECT_EQ(0, m.minute()); - EXPECT_EQ(0, m.second()); - EXPECT_EQ(weekday::sunday, get_weekday(m)); - EXPECT_EQ(32, get_yearday(m)); - - civil_year y(2015, 2, 3, 4, 5, 6); - EXPECT_EQ(2015, y.year()); - EXPECT_EQ(1, y.month()); - EXPECT_EQ(1, y.day()); - EXPECT_EQ(0, y.hour()); - EXPECT_EQ(0, y.minute()); - EXPECT_EQ(0, y.second()); - EXPECT_EQ(weekday::thursday, get_weekday(y)); - EXPECT_EQ(1, get_yearday(y)); -} - -TEST(CivilTime, OutputStream) { - // Tests formatting of civil_year, which does not pad. - EXPECT_EQ("2016", Format(civil_year(2016))); - EXPECT_EQ("123", Format(civil_year(123))); - EXPECT_EQ("0", Format(civil_year(0))); - EXPECT_EQ("-1", Format(civil_year(-1))); - - // Tests formatting of sub-year types, which pad to 2 digits - EXPECT_EQ("2016-02", Format(civil_month(2016, 2))); - EXPECT_EQ("2016-02-03", Format(civil_day(2016, 2, 3))); - EXPECT_EQ("2016-02-03T04", Format(civil_hour(2016, 2, 3, 4))); - EXPECT_EQ("2016-02-03T04:05", Format(civil_minute(2016, 2, 3, 4, 5))); - EXPECT_EQ("2016-02-03T04:05:06", Format(civil_second(2016, 2, 3, 4, 5, 6))); - - // Tests formatting of weekday. - EXPECT_EQ("Monday", Format(weekday::monday)); - EXPECT_EQ("Tuesday", Format(weekday::tuesday)); - EXPECT_EQ("Wednesday", Format(weekday::wednesday)); - EXPECT_EQ("Thursday", Format(weekday::thursday)); - EXPECT_EQ("Friday", Format(weekday::friday)); - EXPECT_EQ("Saturday", Format(weekday::saturday)); - EXPECT_EQ("Sunday", Format(weekday::sunday)); -} - -TEST(CivilTime, OutputStreamLeftFillWidth) { - civil_second cs(2016, 2, 3, 4, 5, 6); - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_year(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016.................X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_month(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02..............X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_day(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03...........X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_hour(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04........X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_minute(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04:05.....X..", ss.str()); - } - { - std::stringstream ss; - ss << std::left << std::setfill('.'); - ss << std::setw(3) << 'X'; - ss << std::setw(21) << civil_second(cs); - ss << std::setw(3) << 'X'; - EXPECT_EQ("X..2016-02-03T04:05:06..X..", ss.str()); - } -} - -TEST(CivilTime, NextPrevWeekday) { - // Jan 1, 1970 was a Thursday. - const civil_day thursday(1970, 1, 1); - EXPECT_EQ(weekday::thursday, get_weekday(thursday)); - - // Thursday -> Thursday - civil_day d = next_weekday(thursday, weekday::thursday); - EXPECT_EQ(7, d - thursday) << Format(d); - EXPECT_EQ(d - 14, prev_weekday(thursday, weekday::thursday)); - - // Thursday -> Friday - d = next_weekday(thursday, weekday::friday); - EXPECT_EQ(1, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::friday)); - - // Thursday -> Saturday - d = next_weekday(thursday, weekday::saturday); - EXPECT_EQ(2, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::saturday)); - - // Thursday -> Sunday - d = next_weekday(thursday, weekday::sunday); - EXPECT_EQ(3, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::sunday)); - - // Thursday -> Monday - d = next_weekday(thursday, weekday::monday); - EXPECT_EQ(4, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::monday)); - - // Thursday -> Tuesday - d = next_weekday(thursday, weekday::tuesday); - EXPECT_EQ(5, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::tuesday)); - - // Thursday -> Wednesday - d = next_weekday(thursday, weekday::wednesday); - EXPECT_EQ(6, d - thursday) << Format(d); - EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::wednesday)); -} - -TEST(CivilTime, NormalizeWithHugeYear) { - civil_month c(9223372036854775807, 1); - EXPECT_EQ("9223372036854775807-01", Format(c)); - c = c - 1; // Causes normalization - EXPECT_EQ("9223372036854775806-12", Format(c)); - - c = civil_month(-9223372036854775807 - 1, 1); - EXPECT_EQ("-9223372036854775808-01", Format(c)); - c = c + 12; // Causes normalization - EXPECT_EQ("-9223372036854775807-01", Format(c)); -} - -TEST(CivilTime, LeapYears) { - // Test data for leap years. - const struct { - int year; - int days; - struct { - int month; - int day; - } leap_day; // The date of the day after Feb 28. - } kLeapYearTable[]{ - {1900, 365, {3, 1}}, {1999, 365, {3, 1}}, - {2000, 366, {2, 29}}, // leap year - {2001, 365, {3, 1}}, {2002, 365, {3, 1}}, - {2003, 365, {3, 1}}, {2004, 366, {2, 29}}, // leap year - {2005, 365, {3, 1}}, {2006, 365, {3, 1}}, - {2007, 365, {3, 1}}, {2008, 366, {2, 29}}, // leap year - {2009, 365, {3, 1}}, {2100, 365, {3, 1}}, - }; - - for (const auto& e : kLeapYearTable) { - // Tests incrementing through the leap day. - const civil_day feb28(e.year, 2, 28); - const civil_day next_day = feb28 + 1; - EXPECT_EQ(e.leap_day.month, next_day.month()); - EXPECT_EQ(e.leap_day.day, next_day.day()); - - // Tests difference in days of leap years. - const civil_year year(feb28); - const civil_year next_year = year + 1; - EXPECT_EQ(e.days, civil_day(next_year) - civil_day(year)); - } -} - -TEST(CivilTime, FirstThursdayInMonth) { - const civil_day nov1(2014, 11, 1); - const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday); - EXPECT_EQ("2014-11-06", Format(thursday)); - - // Bonus: Date of Thanksgiving in the United States - // Rule: Fourth Thursday of November - const civil_day thanksgiving = thursday + 7 * 3; - EXPECT_EQ("2014-11-27", Format(thanksgiving)); -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 303c0244a824..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_fixed.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_fixed.h" - -#include <algorithm> -#include <cassert> -#include <chrono> -#include <cstring> -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// The prefix used for the internal names of fixed-offset zones. -const char kFixedZonePrefix[] = "Fixed/UTC"; - -const char kDigits[] = "0123456789"; - -char* Format02d(char* p, int v) { - *p++ = kDigits[(v / 10) % 10]; - *p++ = kDigits[v % 10]; - return p; -} - -int Parse02d(const char* p) { - if (const char* ap = std::strchr(kDigits, *p)) { - int v = static_cast<int>(ap - kDigits); - if (const char* bp = std::strchr(kDigits, *++p)) { - return (v * 10) + static_cast<int>(bp - kDigits); - } - } - return -1; -} - -} // namespace - -bool FixedOffsetFromName(const std::string& name, seconds* offset) { - if (name.compare(0, std::string::npos, "UTC", 3) == 0) { - *offset = seconds::zero(); - return true; - } - - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - const char* const ep = kFixedZonePrefix + prefix_len; - if (name.size() != prefix_len + 9) // <prefix>+99:99:99 - return false; - if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false; - const char* np = name.data() + prefix_len; - if (np[0] != '+' && np[0] != '-') return false; - if (np[3] != ':' || np[6] != ':') // see note below about large offsets - return false; - - int hours = Parse02d(np + 1); - if (hours == -1) return false; - int mins = Parse02d(np + 4); - if (mins == -1) return false; - int secs = Parse02d(np + 7); - if (secs == -1) return false; - - secs += ((hours * 60) + mins) * 60; - if (secs > 24 * 60 * 60) return false; // outside supported offset range - *offset = seconds(secs * (np[0] == '-' ? -1 : 1)); // "-" means west - return true; -} - -std::string FixedOffsetToName(const seconds& offset) { - if (offset == seconds::zero()) return "UTC"; - if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) { - // We don't support fixed-offset zones more than 24 hours - // away from UTC to avoid complications in rendering such - // offsets and to (somewhat) limit the total number of zones. - return "UTC"; - } - int offset_seconds = static_cast<int>(offset.count()); - const char sign = (offset_seconds < 0 ? '-' : '+'); - int offset_minutes = offset_seconds / 60; - offset_seconds %= 60; - if (sign == '-') { - if (offset_seconds > 0) { - offset_seconds -= 60; - offset_minutes += 1; - } - offset_seconds = -offset_seconds; - offset_minutes = -offset_minutes; - } - int offset_hours = offset_minutes / 60; - offset_minutes %= 60; - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - char buf[prefix_len + sizeof("-24:00:00")]; - char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf); - *ep++ = sign; - ep = Format02d(ep, offset_hours); - *ep++ = ':'; - ep = Format02d(ep, offset_minutes); - *ep++ = ':'; - ep = Format02d(ep, offset_seconds); - *ep++ = '\0'; - assert(ep == buf + sizeof(buf)); - return buf; -} - -std::string FixedOffsetToAbbr(const seconds& offset) { - std::string abbr = FixedOffsetToName(offset); - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99 - abbr.erase(0, prefix_len); // +99:99:99 - abbr.erase(6, 1); // +99:9999 - abbr.erase(3, 1); // +999999 - if (abbr[5] == '0' && abbr[6] == '0') { // +999900 - abbr.erase(5, 2); // +9999 - if (abbr[3] == '0' && abbr[4] == '0') { // +9900 - abbr.erase(3, 2); // +99 - } - } - } - return abbr; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_fixed.h b/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_fixed.h deleted file mode 100644 index e74a0bbd9dde..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_fixed.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ - -#include <string> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Helper functions for dealing with the names and abbreviations -// of time zones that are a fixed offset (seconds east) from UTC. -// FixedOffsetFromName() extracts the offset from a valid fixed-offset -// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate -// the canonical zone name and abbreviation respectively for the given -// offset. -// -// A fixed-offset name looks like "Fixed/UTC<+-><hours>:<mins>:<secs>". -// Its abbreviation is of the form "UTC(<+->H?H(MM(SS)?)?)?" where the -// optional pieces are omitted when their values are zero. (Note that -// the sign is the opposite of that used in a POSIX TZ specification.) -// -// Note: FixedOffsetFromName() fails on syntax errors or when the parsed -// offset exceeds 24 hours. FixedOffsetToName() and FixedOffsetToAbbr() -// both produce "UTC" when the argument offset exceeds 24 hours. -bool FixedOffsetFromName(const std::string& name, seconds* offset); -std::string FixedOffsetToName(const seconds& offset); -std::string FixedOffsetToAbbr(const seconds& offset); - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ diff --git a/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 deleted file mode 100644 index d8cb047425ee..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_format.cc +++ /dev/null @@ -1,1029 +0,0 @@ -// Copyright 2016 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. - -#if !defined(HAS_STRPTIME) -#if !defined(_MSC_VER) && !defined(__MINGW32__) -#define HAS_STRPTIME 1 // assume everyone has strptime() except windows -#endif -#endif - -#if defined(HAS_STRPTIME) && HAS_STRPTIME -#if !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE // Definedness suffices for strptime. -#endif -#endif - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -// Include time.h directly since, by C++ standards, ctime doesn't have to -// declare strptime. -#include <time.h> - -#include <cctype> -#include <chrono> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <ctime> -#include <limits> -#include <string> -#include <vector> -#if !HAS_STRPTIME -#include <iomanip> -#include <sstream> -#endif - -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_if.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { -namespace detail { - -namespace { - -#if !HAS_STRPTIME -// Build a strptime() using C++11's std::get_time(). -char* strptime(const char* s, const char* fmt, std::tm* tm) { - std::istringstream input(s); - input >> std::get_time(tm, fmt); - if (input.fail()) return nullptr; - return const_cast<char*>(s) + - (input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg())); -} -#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(); - tm.tm_min = al.cs.minute(); - tm.tm_hour = al.cs.hour(); - tm.tm_mday = al.cs.day(); - tm.tm_mon = al.cs.month() - 1; - - // Saturate tm.tm_year is cases of over/underflow. - if (al.cs.year() < std::numeric_limits<int>::min() + 1900) { - tm.tm_year = std::numeric_limits<int>::min(); - } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) { - tm.tm_year = std::numeric_limits<int>::max(); - } else { - tm.tm_year = static_cast<int>(al.cs.year() - 1900); - } - - tm.tm_wday = ToTmWday(get_weekday(al.cs)); - tm.tm_yday = get_yearday(al.cs) - 1; - tm.tm_isdst = al.is_dst ? 1 : 0; - return tm; -} - -// Returns the week of the year [0:53] given a civil day and the day on -// which weeks are defined to start. -int ToWeek(const civil_day& cd, weekday week_start) { - const civil_day d(cd.year() % 400, cd.month(), cd.day()); - return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7); -} - -const char kDigits[] = "0123456789"; - -// Formats a 64-bit integer in the given field width. Note that it is up -// to the caller of Format64() [and Format02d()/FormatOffset()] to ensure -// that there is sufficient space before ep to hold the conversion. -char* Format64(char* ep, int width, std::int_fast64_t v) { - bool neg = false; - if (v < 0) { - --width; - neg = true; - if (v == std::numeric_limits<std::int_fast64_t>::min()) { - // Avoid negating minimum value. - std::int_fast64_t last_digit = -(v % 10); - v /= 10; - if (last_digit < 0) { - ++v; - last_digit += 10; - } - --width; - *--ep = kDigits[last_digit]; - } - v = -v; - } - do { - --width; - *--ep = kDigits[v % 10]; - } while (v /= 10); - while (--width >= 0) *--ep = '0'; // zero pad - if (neg) *--ep = '-'; - return ep; -} - -// Formats [0 .. 99] as %02d. -char* Format02d(char* ep, int v) { - *--ep = kDigits[v % 10]; - *--ep = kDigits[(v / 10) % 10]; - return ep; -} - -// Formats a UTC offset, like +00:00. -char* FormatOffset(char* ep, int offset, const char* mode) { - // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and - // generate a "negative zero" when we're formatting a zero offset - // as the result of a failed load_time_zone(). - char sign = '+'; - if (offset < 0) { - offset = -offset; // bounded by 24h so no overflow - sign = '-'; - } - const int seconds = offset % 60; - const int minutes = (offset /= 60) % 60; - const int hours = offset /= 60; - const char sep = mode[0]; - const bool ext = (sep != '\0' && mode[1] == '*'); - const bool ccc = (ext && mode[2] == ':'); - if (ext && (!ccc || seconds != 0)) { - ep = Format02d(ep, seconds); - *--ep = sep; - } else { - // If we're not rendering seconds, sub-minute negative offsets - // should get a positive sign (e.g., offset=-10s => "+00:00"). - if (hours == 0 && minutes == 0) sign = '+'; - } - if (!ccc || minutes != 0 || seconds != 0) { - ep = Format02d(ep, minutes); - if (sep != '\0') *--ep = sep; - } - ep = Format02d(ep, hours); - *--ep = sign; - return ep; -} - -// Formats a std::tm using strftime(3). -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 - // length up to 32x. - for (std::size_t i = 2; i != 32; i *= 2) { - std::size_t buf_size = fmt.size() * i; - std::vector<char> buf(buf_size); - if (std::size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) { - out->append(&buf[0], len); - return; - } - } -} - -// Used for %E#S/%E#f specifiers and for data values in parse(). -template <typename T> -const char* ParseInt(const char* dp, int width, T min, T max, T* vp) { - if (dp != nullptr) { - const T kmin = std::numeric_limits<T>::min(); - bool erange = false; - bool neg = false; - T value = 0; - if (*dp == '-') { - neg = true; - if (width <= 0 || --width != 0) { - ++dp; - } else { - dp = nullptr; // width was 1 - } - } - if (const char* const bp = dp) { - while (const char* cp = strchr(kDigits, *dp)) { - int d = static_cast<int>(cp - kDigits); - if (d >= 10) break; - if (value < kmin / 10) { - erange = true; - break; - } - value *= 10; - if (value < kmin + d) { - erange = true; - break; - } - value -= d; - dp += 1; - if (width > 0 && --width == 0) break; - } - if (dp != bp && !erange && (neg || value != kmin)) { - if (!neg || value != 0) { - if (!neg) value = -value; // make positive - if (min <= value && value <= max) { - *vp = value; - } else { - dp = nullptr; - } - } else { - dp = nullptr; - } - } else { - dp = nullptr; - } - } - } - return dp; -} - -// The number of base-10 digits that can be represented by a signed 64-bit -// integer. That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1). -const int kDigits10_64 = 18; - -// 10^n for everything that can be represented by a signed 64-bit integer. -const std::int_fast64_t kExp10[kDigits10_64 + 1] = { - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000, - 1000000000000000, - 10000000000000000, - 100000000000000000, - 1000000000000000000, -}; - -} // namespace - -// Uses strftime(3) to format the given Time. The following extended format -// specifiers are also supported: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %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 -// a POSIX requirement to respect changes to ${TZ}. -// -// The TZ/GNU %s extension is handled internally because strftime() has -// to use mktime() to generate it, and that assumes the local time zone. -// -// We also handle the %z and %Z specifiers to accommodate platforms that do -// not support the tm_gmtoff and tm_zone extensions to std::tm. -// -// Requires that zero() <= fs < seconds(1). -std::string format(const std::string& format, const time_point<seconds>& tp, - const detail::femtoseconds& fs, const time_zone& tz) { - std::string result; - result.reserve(format.size()); // A reasonable guess for the result size. - const time_zone::absolute_lookup al = tz.lookup(tp); - const std::tm tm = ToTM(al); - - // Scratch buffer for internal conversions. - char buf[3 + kDigits10_64]; // enough for longest conversion - char* const ep = buf + sizeof(buf); - char* bp; // works back from ep - - // Maintain three, disjoint subsequences that span format. - // [format.begin() ... pending) : already formatted into result - // [pending ... cur) : formatting pending, but no special cases - // [cur ... format.end()) : unexamined - // Initially, everything is in the unexamined part. - const char* pending = format.c_str(); // NUL terminated - const char* cur = pending; - const char* end = pending + format.length(); - - while (cur != end) { // while something is unexamined - // Moves cur to the next percent sign. - const char* start = cur; - while (cur != end && *cur != '%') ++cur; - - // If the new pending text is all ordinary, copy it out. - if (cur != start && pending == start) { - result.append(pending, static_cast<std::size_t>(cur - pending)); - pending = start = cur; - } - - // Span the sequential percent signs. - const char* percent = cur; - while (cur != end && *cur == '%') ++cur; - - // If the new pending text is all percents, copy out one - // percent for every matched pair, then skip those pairs. - if (cur != start && pending == start) { - std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2; - result.append(pending, escaped); - pending += escaped * 2; - // Also copy out a single trailing percent. - if (pending != cur && cur == end) { - result.push_back(*pending++); - } - } - - // Loop unless we have an unescaped percent. - if (cur == end || (cur - percent) % 2 == 0) continue; - - // Simple specifiers that we handle ourselves. - if (strchr("YmdeUuWwHMSzZs%", *cur)) { - if (cur - 1 != pending) { - FormatTM(&result, std::string(pending, cur - 1), tm); - } - switch (*cur) { - case 'Y': - // This avoids the tm.tm_year overflow problem for %Y, however - // tm.tm_year will still be used by other specifiers like %D. - bp = Format64(ep, 0, al.cs.year()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'm': - bp = Format02d(ep, al.cs.month()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'd': - case 'e': - bp = Format02d(ep, al.cs.day()); - 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)); - break; - case 'M': - bp = Format02d(ep, al.cs.minute()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'S': - bp = Format02d(ep, al.cs.second()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'z': - bp = FormatOffset(ep, al.offset, ""); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'Z': - result.append(al.abbr); - break; - case 's': - bp = Format64(ep, 0, ToUnixSeconds(tp)); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case '%': - result.push_back('%'); - break; - } - pending = ++cur; - continue; - } - - // More complex specifiers that we handle ourselves. - if (*cur == ':' && cur + 1 != end) { - if (*(cur + 1) == 'z') { - // Formats %:z. - if (cur - 1 != pending) { - FormatTM(&result, std::string(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - continue; - } - if (*(cur + 1) == ':' && cur + 2 != end) { - if (*(cur + 2) == 'z') { - // Formats %::z. - if (cur - 1 != pending) { - FormatTM(&result, std::string(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":*"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 3; - continue; - } - if (*(cur + 2) == ':' && cur + 3 != end) { - if (*(cur + 3) == 'z') { - // Formats %:::z. - if (cur - 1 != pending) { - FormatTM(&result, std::string(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":*:"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 4; - continue; - } - } - } - } - - // Loop if there is no E modifier. - if (*cur != 'E' || ++cur == end) continue; - - // Format our extensions. - if (*cur == 'T') { - // Formats %ET. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - result.append("T"); - pending = ++cur; - } else if (*cur == 'z') { - // Formats %Ez. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - bp = FormatOffset(ep, al.offset, ":"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = ++cur; - } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') { - // Formats %E*z. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - bp = FormatOffset(ep, al.offset, ":*"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - } else if (*cur == '*' && cur + 1 != end && - (*(cur + 1) == 'S' || *(cur + 1) == 'f')) { - // Formats %E*S or %E*F. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - char* cp = ep; - bp = Format64(cp, 15, fs.count()); - while (cp != bp && cp[-1] == '0') --cp; - switch (*(cur + 1)) { - case 'S': - if (cp != bp) *--bp = '.'; - bp = Format02d(bp, al.cs.second()); - break; - case 'f': - if (cp == bp) *--bp = '0'; - break; - } - result.append(bp, static_cast<std::size_t>(cp - bp)); - pending = cur += 2; - } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') { - // Formats %E4Y. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - bp = Format64(ep, 4, al.cs.year()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - } else if (std::isdigit(*cur)) { - // Possibly found %E#S or %E#f. - int n = 0; - if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) { - if (*np == 'S' || *np == 'f') { - // Formats %E#S or %E#f. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - bp = ep; - if (n > 0) { - if (n > kDigits10_64) n = kDigits10_64; - bp = Format64(bp, n, - (n > 15) ? fs.count() * kExp10[n - 15] - : fs.count() / kExp10[15 - n]); - if (*np == 'S') *--bp = '.'; - } - if (*np == 'S') bp = Format02d(bp, al.cs.second()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur = ++np; - } - } - } - } - - // Formats any remaining data. - if (end != pending) { - FormatTM(&result, std::string(pending, end), tm); - } - - return result; -} - -namespace { - -const char* ParseOffset(const char* dp, const char* mode, int* offset) { - if (dp != nullptr) { - const char first = *dp++; - if (first == '+' || first == '-') { - char sep = mode[0]; - int hours = 0; - int minutes = 0; - int seconds = 0; - const char* ap = ParseInt(dp, 2, 0, 23, &hours); - if (ap != nullptr && ap - dp == 2) { - dp = ap; - if (sep != '\0' && *ap == sep) ++ap; - const char* bp = ParseInt(ap, 2, 0, 59, &minutes); - if (bp != nullptr && bp - ap == 2) { - dp = bp; - if (sep != '\0' && *bp == sep) ++bp; - const char* cp = ParseInt(bp, 2, 0, 59, &seconds); - if (cp != nullptr && cp - bp == 2) dp = cp; - } - *offset = ((hours * 60 + minutes) * 60) + seconds; - if (first == '-') *offset = -*offset; - } else { - dp = nullptr; - } - } else if (first == 'Z' || first == 'z') { // Zulu - *offset = 0; - } else { - dp = nullptr; - } - } - return dp; -} - -const char* ParseZone(const char* dp, std::string* zone) { - zone->clear(); - if (dp != nullptr) { - while (*dp != '\0' && !std::isspace(*dp)) zone->push_back(*dp++); - if (zone->empty()) dp = nullptr; - } - return dp; -} - -const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) { - if (dp != nullptr) { - std::int_fast64_t v = 0; - std::int_fast64_t exp = 0; - const char* const bp = dp; - while (const char* cp = strchr(kDigits, *dp)) { - int d = static_cast<int>(cp - kDigits); - if (d >= 10) break; - if (exp < 15) { - exp += 1; - v *= 10; - v += d; - } - ++dp; - } - if (dp != bp) { - v *= kExp10[15 - exp]; - *subseconds = detail::femtoseconds(v); - } else { - dp = nullptr; - } - } - return dp; -} - -// Parses a string into a std::tm using strptime(3). -const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { - if (dp != nullptr) { - dp = strptime(dp, fmt, 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 standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are -// handled internally so that we can normally avoid strptime() altogether -// (which is particularly helpful when the native implementation is broken). -// -// The TZ/GNU %s extension is handled internally because strptime() has to -// use localtime_r() to generate it, and that assumes the local time zone. -// -// We also handle the %z specifier to accommodate platforms that do not -// support the tm_gmtoff extension to std::tm. %Z is parsed but ignored. -bool parse(const std::string& format, const std::string& input, - const time_zone& tz, time_point<seconds>* sec, - detail::femtoseconds* fs, std::string* err) { - // The unparsed input. - const char* data = input.c_str(); // NUL terminated - - // Skips leading whitespace. - while (std::isspace(*data)) ++data; - - const year_t kyearmax = std::numeric_limits<year_t>::max(); - const year_t kyearmin = std::numeric_limits<year_t>::min(); - - // Sets default values for unspecified fields. - bool saw_year = false; - year_t year = 1970; - std::tm tm{}; - tm.tm_year = 1970 - 1900; - tm.tm_mon = 1 - 1; // Jan - tm.tm_mday = 1; - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - tm.tm_wday = 4; // Thu - tm.tm_yday = 0; - tm.tm_isdst = 0; - auto subseconds = detail::femtoseconds::zero(); - bool saw_offset = false; - int offset = 0; // No offset from passed tz. - std::string zone = "UTC"; - - 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; - - // Steps through format, one specifier at a time. - while (data != nullptr && *fmt != '\0') { - if (std::isspace(*fmt)) { - while (std::isspace(*data)) ++data; - while (std::isspace(*++fmt)) continue; - continue; - } - - if (*fmt != '%') { - if (*data == *fmt) { - ++data; - ++fmt; - } else { - data = nullptr; - } - continue; - } - - const char* percent = fmt; - if (*++fmt == '\0') { - data = nullptr; - continue; - } - switch (*fmt++) { - case 'Y': - // Symmetrically with FormatTime(), directly handing %Y avoids the - // tm.tm_year overflow problem. However, tm.tm_year will still be - // used by other specifiers like %D. - data = ParseInt(data, 0, kyearmin, kyearmax, &year); - if (data != nullptr) saw_year = true; - continue; - 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); - twelve_hour = false; - continue; - case 'M': - data = ParseInt(data, 2, 0, 59, &tm.tm_min); - continue; - case 'S': - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - continue; - case 'I': - case 'l': - case 'r': // probably uses %I - twelve_hour = true; - break; - case 'R': // uses %H - case 'T': // uses %H - case 'c': // probably uses %H - case 'X': // probably uses %H - twelve_hour = false; - break; - case 'z': - data = ParseOffset(data, "", &offset); - if (data != nullptr) saw_offset = true; - continue; - case 'Z': // ignored; zone abbreviations are ambiguous - data = ParseZone(data, &zone); - continue; - case 's': - data = - ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(), - std::numeric_limits<std::int_fast64_t>::max(), &percent_s); - if (data != nullptr) saw_percent_s = true; - continue; - case ':': - if (fmt[0] == 'z' || - (fmt[0] == ':' && - (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) { - data = ParseOffset(data, ":", &offset); - if (data != nullptr) saw_offset = true; - fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3; - continue; - } - break; - case '%': - data = (*data == '%' ? data + 1 : nullptr); - continue; - case 'E': - if (fmt[0] == 'T') { - if (*data == 'T' || *data == 't') { - ++data; - ++fmt; - } else { - data = nullptr; - } - continue; - } - if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) { - data = ParseOffset(data, ":", &offset); - if (data != nullptr) saw_offset = true; - fmt += (fmt[0] == 'z') ? 1 : 2; - continue; - } - if (fmt[0] == '*' && fmt[1] == 'S') { - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - if (data != nullptr && *data == '.') { - data = ParseSubSeconds(data + 1, &subseconds); - } - fmt += 2; - continue; - } - if (fmt[0] == '*' && fmt[1] == 'f') { - if (data != nullptr && std::isdigit(*data)) { - data = ParseSubSeconds(data, &subseconds); - } - fmt += 2; - continue; - } - if (fmt[0] == '4' && fmt[1] == 'Y') { - const char* bp = data; - data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year); - if (data != nullptr) { - if (data - bp == 4) { - saw_year = true; - } else { - data = nullptr; // stopped too soon - } - } - fmt += 2; - continue; - } - if (std::isdigit(*fmt)) { - int n = 0; // value ignored - if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) { - if (*np == 'S') { - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - if (data != nullptr && *data == '.') { - data = ParseSubSeconds(data + 1, &subseconds); - } - fmt = ++np; - continue; - } - if (*np == 'f') { - if (data != nullptr && std::isdigit(*data)) { - data = ParseSubSeconds(data, &subseconds); - } - fmt = ++np; - continue; - } - } - } - if (*fmt == 'c') twelve_hour = false; // probably uses %H - if (*fmt == 'X') twelve_hour = false; // probably uses %H - if (*fmt != '\0') ++fmt; - break; - case 'O': - if (*fmt == 'H') twelve_hour = false; - if (*fmt == 'I') twelve_hour = true; - if (*fmt != '\0') ++fmt; - break; - } - - // Parses the current specifier. - const char* orig_data = data; - std::string spec(percent, static_cast<std::size_t>(fmt - percent)); - data = ParseTM(data, spec.c_str(), &tm); - - // If we successfully parsed %p we need to remember whether the result - // was AM or PM so that we can adjust tm_hour before time_zone::lookup(). - // So reparse the input with a known AM hour, and check if it is shifted - // to a PM hour. - if (spec == "%p" && data != nullptr) { - std::string test_input = "1"; - test_input.append(orig_data, static_cast<std::size_t>(data - orig_data)); - const char* test_data = test_input.c_str(); - std::tm tmp{}; - ParseTM(test_data, "%I%p", &tmp); - afternoon = (tmp.tm_hour == 13); - } - } - - // Adjust a 12-hour tm_hour value if it should be in the afternoon. - if (twelve_hour && afternoon && tm.tm_hour < 12) { - tm.tm_hour += 12; - } - - if (data == nullptr) { - if (err != nullptr) *err = "Failed to parse input"; - return false; - } - - // Skip any remaining whitespace. - while (std::isspace(*data)) ++data; - - // parse() must consume the entire input string. - if (*data != '\0') { - if (err != nullptr) *err = "Illegal trailing data in input string"; - return false; - } - - // If we saw %s then we ignore anything else and return that time. - if (saw_percent_s) { - *sec = FromUnixSeconds(percent_s); - *fs = detail::femtoseconds::zero(); - return true; - } - - // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields - // in UTC and then shift by that offset. Otherwise we want to interpret - // the fields directly in the passed time_zone. - time_zone ptz = saw_offset ? utc_time_zone() : tz; - - // Allows a leap second of 60 to normalize forward to the following ":00". - if (tm.tm_sec == 60) { - tm.tm_sec -= 1; - offset -= 1; - subseconds = detail::femtoseconds::zero(); - } - - if (!saw_year) { - year = year_t{tm.tm_year}; - if (year > kyearmax - 1900) { - // Platform-dependent, maybe unreachable. - if (err != nullptr) *err = "Out-of-range year"; - return false; - } - 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); - - // parse() should not allow normalization. Due to the restricted field - // ranges above (see ParseInt()), the only possibility is for days to roll - // into months. That is, parsing "Sep 31" should not produce "Oct 1". - if (cs.month() != month || cs.day() != tm.tm_mday) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - - // Accounts for the offset adjustment before converting to absolute time. - if ((offset < 0 && cs > civil_second::max() + offset) || - (offset > 0 && cs < civil_second::min() + offset)) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - cs -= offset; - - const auto tp = ptz.lookup(cs).pre; - // Checks for overflow/underflow and returns an error as necessary. - if (tp == time_point<seconds>::max()) { - const auto al = ptz.lookup(time_point<seconds>::max()); - if (cs > al.cs) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - } - if (tp == time_point<seconds>::min()) { - const auto al = ptz.lookup(time_point<seconds>::min()); - if (cs < al.cs) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - } - - *sec = tp; - *fs = subseconds; - return true; -} - -} // namespace detail -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index a11f93e2a597..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_format_test.cc +++ /dev/null @@ -1,1603 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <chrono> -#include <iomanip> -#include <sstream> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace chrono = std::chrono; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// This helper is a macro so that failed expectations show up with the -// correct line numbers. -#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \ - do { \ - time_zone::absolute_lookup al = tz.lookup(tp); \ - EXPECT_EQ(y, al.cs.year()); \ - EXPECT_EQ(m, al.cs.month()); \ - EXPECT_EQ(d, al.cs.day()); \ - EXPECT_EQ(hh, al.cs.hour()); \ - EXPECT_EQ(mm, al.cs.minute()); \ - EXPECT_EQ(ss, al.cs.second()); \ - EXPECT_EQ(off, al.offset); \ - EXPECT_TRUE(isdst == al.is_dst); \ - 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 RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; -const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; - -// A helper that tests the given format specifier by itself, and with leading -// and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu"). -template <typename D> -void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt, - const std::string& ans) { - EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt; - EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz)); - EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz)); - EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz)); -} - -} // namespace - -// -// Testing format() -// - -TEST(Format, TimePointResolution) { - const char kFmt[] = "%H:%M:%E*S"; - const time_zone utc = utc_time_zone(); - const time_point<chrono::nanoseconds> t0 = - chrono::system_clock::from_time_t(1420167845) + - chrono::milliseconds(123) + chrono::microseconds(456) + - chrono::nanoseconds(789); - EXPECT_EQ( - "03:04:05.123456789", - format(kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc)); - EXPECT_EQ( - "03:04:05.123456", - format(kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc)); - EXPECT_EQ( - "03:04:05.123", - format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc)); - EXPECT_EQ("03:04:05", - format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc)); - EXPECT_EQ( - "03:04:05", - format(kFmt, - chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), - utc)); - EXPECT_EQ("03:04:00", - format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc)); - EXPECT_EQ("03:00:00", - format(kFmt, chrono::time_point_cast<chrono::hours>(t0), utc)); -} - -TEST(Format, TimePointExtendedResolution) { - const char kFmt[] = "%H:%M:%E*S"; - const time_zone utc = utc_time_zone(); - const time_point<absl::time_internal::cctz::seconds> tp = - chrono::time_point_cast<absl::time_internal::cctz::seconds>( - chrono::system_clock::from_time_t(0)) + - chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56); - - EXPECT_EQ( - "12:34:56.123456789012345", - detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc)); - EXPECT_EQ( - "12:34:56.012345678901234", - detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc)); - EXPECT_EQ("12:34:56.001234567890123", - detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); - EXPECT_EQ("12:34:56.000123456789012", - detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc)); - - EXPECT_EQ("12:34:56.000000000000123", - detail::format(kFmt, tp, detail::femtoseconds(123), utc)); - EXPECT_EQ("12:34:56.000000000000012", - detail::format(kFmt, tp, detail::femtoseconds(12), utc)); - EXPECT_EQ("12:34:56.000000000000001", - detail::format(kFmt, tp, detail::femtoseconds(1), utc)); -} - -TEST(Format, Basics) { - time_zone tz = utc_time_zone(); - time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); - - // Starts with a couple basic edge cases. - EXPECT_EQ("", format("", tp, tz)); - EXPECT_EQ(" ", format(" ", tp, tz)); - EXPECT_EQ(" ", format(" ", tp, tz)); - EXPECT_EQ("xxx", format("xxx", tp, tz)); - std::string big(128, 'x'); - EXPECT_EQ(big, format(big, tp, tz)); - // Cause the 1024-byte buffer to grow. - std::string bigger(100000, 'x'); - EXPECT_EQ(bigger, format(bigger, tp, tz)); - - tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5); - tp += chrono::milliseconds(6) + chrono::microseconds(7) + - chrono::nanoseconds(8); - EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz)); - EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz)); - EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz)); - EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz)); - EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz)); -} - -TEST(Format, PosixConversions) { - const time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - - TestFormatSpecifier(tp, tz, "%d", "01"); - TestFormatSpecifier(tp, tz, "%e", " 1"); // extension but internal support - TestFormatSpecifier(tp, tz, "%H", "00"); - TestFormatSpecifier(tp, tz, "%I", "12"); - TestFormatSpecifier(tp, tz, "%j", "001"); - TestFormatSpecifier(tp, tz, "%m", "01"); - TestFormatSpecifier(tp, tz, "%M", "00"); - TestFormatSpecifier(tp, tz, "%S", "00"); - TestFormatSpecifier(tp, tz, "%U", "00"); -#if !defined(__EMSCRIPTEN__) - TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday -#endif - TestFormatSpecifier(tp, tz, "%W", "00"); - TestFormatSpecifier(tp, tz, "%y", "70"); - TestFormatSpecifier(tp, tz, "%Y", "1970"); - TestFormatSpecifier(tp, tz, "%z", "+0000"); - TestFormatSpecifier(tp, tz, "%Z", "UTC"); - TestFormatSpecifier(tp, tz, "%%", "%"); - -#if defined(__linux__) - // SU/C99/TZ extensions - TestFormatSpecifier(tp, tz, "%C", "19"); - TestFormatSpecifier(tp, tz, "%D", "01/01/70"); - TestFormatSpecifier(tp, tz, "%F", "1970-01-01"); - TestFormatSpecifier(tp, tz, "%g", "70"); - TestFormatSpecifier(tp, tz, "%G", "1970"); - TestFormatSpecifier(tp, tz, "%k", " 0"); - TestFormatSpecifier(tp, tz, "%l", "12"); - TestFormatSpecifier(tp, tz, "%n", "\n"); - TestFormatSpecifier(tp, tz, "%R", "00:00"); - TestFormatSpecifier(tp, tz, "%t", "\t"); - TestFormatSpecifier(tp, tz, "%T", "00:00:00"); - TestFormatSpecifier(tp, tz, "%u", "4"); // 4=Thursday - TestFormatSpecifier(tp, tz, "%V", "01"); - TestFormatSpecifier(tp, tz, "%s", "0"); -#endif -} - -TEST(Format, LocaleSpecific) { - const time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - - TestFormatSpecifier(tp, tz, "%a", "Thu"); - TestFormatSpecifier(tp, tz, "%A", "Thursday"); - TestFormatSpecifier(tp, tz, "%b", "Jan"); - TestFormatSpecifier(tp, tz, "%B", "January"); - - // %c should at least produce the numeric year and time-of-day. - const std::string s = format("%c", tp, utc_time_zone()); - EXPECT_THAT(s, testing::HasSubstr("1970")); - EXPECT_THAT(s, testing::HasSubstr("00:00:00")); - - TestFormatSpecifier(tp, tz, "%p", "AM"); - TestFormatSpecifier(tp, tz, "%x", "01/01/70"); - TestFormatSpecifier(tp, tz, "%X", "00:00:00"); - -#if defined(__linux__) - // SU/C99/TZ extensions - TestFormatSpecifier(tp, tz, "%h", "Jan"); // Same as %b - TestFormatSpecifier(tp, tz, "%P", "am"); - TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM"); - - // Modified conversion specifiers %E_ - TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan 1 00:00:00 1970"); - TestFormatSpecifier(tp, tz, "%EC", "19"); - TestFormatSpecifier(tp, tz, "%Ex", "01/01/70"); - TestFormatSpecifier(tp, tz, "%EX", "00:00:00"); - TestFormatSpecifier(tp, tz, "%Ey", "70"); - TestFormatSpecifier(tp, tz, "%EY", "1970"); - - // Modified conversion specifiers %O_ - TestFormatSpecifier(tp, tz, "%Od", "01"); - TestFormatSpecifier(tp, tz, "%Oe", " 1"); - TestFormatSpecifier(tp, tz, "%OH", "00"); - TestFormatSpecifier(tp, tz, "%OI", "12"); - TestFormatSpecifier(tp, tz, "%Om", "01"); - TestFormatSpecifier(tp, tz, "%OM", "00"); - TestFormatSpecifier(tp, tz, "%OS", "00"); - TestFormatSpecifier(tp, tz, "%Ou", "4"); // 4=Thursday - TestFormatSpecifier(tp, tz, "%OU", "00"); - TestFormatSpecifier(tp, tz, "%OV", "01"); - TestFormatSpecifier(tp, tz, "%Ow", "4"); // 4=Thursday - TestFormatSpecifier(tp, tz, "%OW", "00"); - TestFormatSpecifier(tp, tz, "%Oy", "70"); -#endif -} - -TEST(Format, Escaping) { - const time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - - TestFormatSpecifier(tp, tz, "%%", "%"); - TestFormatSpecifier(tp, tz, "%%a", "%a"); - TestFormatSpecifier(tp, tz, "%%b", "%b"); - TestFormatSpecifier(tp, tz, "%%Ea", "%Ea"); - TestFormatSpecifier(tp, tz, "%%Es", "%Es"); - TestFormatSpecifier(tp, tz, "%%E3S", "%E3S"); - TestFormatSpecifier(tp, tz, "%%OS", "%OS"); - TestFormatSpecifier(tp, tz, "%%O3S", "%O3S"); - - // Multiple levels of escaping. - TestFormatSpecifier(tp, tz, "%%%Y", "%1970"); - TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000"); - TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S"); -} - -TEST(Format, ExtendedSeconds) { - const time_zone tz = utc_time_zone(); - - // No subseconds. - time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); - tp += chrono::seconds(5); - EXPECT_EQ("05", format("%E*S", tp, tz)); - EXPECT_EQ("05", format("%E0S", tp, tz)); - EXPECT_EQ("05.0", format("%E1S", tp, tz)); - EXPECT_EQ("05.00", format("%E2S", tp, tz)); - EXPECT_EQ("05.000", format("%E3S", tp, tz)); - EXPECT_EQ("05.0000", format("%E4S", tp, tz)); - EXPECT_EQ("05.00000", format("%E5S", tp, tz)); - EXPECT_EQ("05.000000", format("%E6S", tp, tz)); - EXPECT_EQ("05.0000000", format("%E7S", tp, tz)); - EXPECT_EQ("05.00000000", format("%E8S", tp, tz)); - EXPECT_EQ("05.000000000", format("%E9S", tp, tz)); - EXPECT_EQ("05.0000000000", format("%E10S", tp, tz)); - EXPECT_EQ("05.00000000000", format("%E11S", tp, tz)); - EXPECT_EQ("05.000000000000", format("%E12S", tp, tz)); - EXPECT_EQ("05.0000000000000", format("%E13S", tp, tz)); - EXPECT_EQ("05.00000000000000", format("%E14S", tp, tz)); - EXPECT_EQ("05.000000000000000", format("%E15S", tp, tz)); - - // With subseconds. - tp += chrono::milliseconds(6) + chrono::microseconds(7) + - chrono::nanoseconds(8); - EXPECT_EQ("05.006007008", format("%E*S", tp, tz)); - EXPECT_EQ("05", format("%E0S", tp, tz)); - EXPECT_EQ("05.0", format("%E1S", tp, tz)); - EXPECT_EQ("05.00", format("%E2S", tp, tz)); - EXPECT_EQ("05.006", format("%E3S", tp, tz)); - EXPECT_EQ("05.0060", format("%E4S", tp, tz)); - EXPECT_EQ("05.00600", format("%E5S", tp, tz)); - EXPECT_EQ("05.006007", format("%E6S", tp, tz)); - EXPECT_EQ("05.0060070", format("%E7S", tp, tz)); - EXPECT_EQ("05.00600700", format("%E8S", tp, tz)); - EXPECT_EQ("05.006007008", format("%E9S", tp, tz)); - EXPECT_EQ("05.0060070080", format("%E10S", tp, tz)); - EXPECT_EQ("05.00600700800", format("%E11S", tp, tz)); - EXPECT_EQ("05.006007008000", format("%E12S", tp, tz)); - EXPECT_EQ("05.0060070080000", format("%E13S", tp, tz)); - EXPECT_EQ("05.00600700800000", format("%E14S", tp, tz)); - EXPECT_EQ("05.006007008000000", format("%E15S", tp, tz)); - - // Times before the Unix epoch. - tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); - EXPECT_EQ("1969-12-31 23:59:59.999999", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); - - // Here is a "%E*S" case we got wrong for a while. While the first - // instant below is correctly rendered as "...:07.333304", the second - // one used to appear as "...:07.33330499999999999". - tp = chrono::system_clock::from_time_t(0) + - chrono::microseconds(1395024427333304); - EXPECT_EQ("2014-03-17 02:47:07.333304", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); - tp += chrono::microseconds(1); - EXPECT_EQ("2014-03-17 02:47:07.333305", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); -} - -TEST(Format, ExtendedSubeconds) { - const time_zone tz = utc_time_zone(); - - // No subseconds. - time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); - tp += chrono::seconds(5); - EXPECT_EQ("0", format("%E*f", tp, tz)); - EXPECT_EQ("", format("%E0f", tp, tz)); - EXPECT_EQ("0", format("%E1f", tp, tz)); - EXPECT_EQ("00", format("%E2f", tp, tz)); - EXPECT_EQ("000", format("%E3f", tp, tz)); - EXPECT_EQ("0000", format("%E4f", tp, tz)); - EXPECT_EQ("00000", format("%E5f", tp, tz)); - EXPECT_EQ("000000", format("%E6f", tp, tz)); - EXPECT_EQ("0000000", format("%E7f", tp, tz)); - EXPECT_EQ("00000000", format("%E8f", tp, tz)); - EXPECT_EQ("000000000", format("%E9f", tp, tz)); - EXPECT_EQ("0000000000", format("%E10f", tp, tz)); - EXPECT_EQ("00000000000", format("%E11f", tp, tz)); - EXPECT_EQ("000000000000", format("%E12f", tp, tz)); - EXPECT_EQ("0000000000000", format("%E13f", tp, tz)); - EXPECT_EQ("00000000000000", format("%E14f", tp, tz)); - EXPECT_EQ("000000000000000", format("%E15f", tp, tz)); - - // With subseconds. - tp += chrono::milliseconds(6) + chrono::microseconds(7) + - chrono::nanoseconds(8); - EXPECT_EQ("006007008", format("%E*f", tp, tz)); - EXPECT_EQ("", format("%E0f", tp, tz)); - EXPECT_EQ("0", format("%E1f", tp, tz)); - EXPECT_EQ("00", format("%E2f", tp, tz)); - EXPECT_EQ("006", format("%E3f", tp, tz)); - EXPECT_EQ("0060", format("%E4f", tp, tz)); - EXPECT_EQ("00600", format("%E5f", tp, tz)); - EXPECT_EQ("006007", format("%E6f", tp, tz)); - EXPECT_EQ("0060070", format("%E7f", tp, tz)); - EXPECT_EQ("00600700", format("%E8f", tp, tz)); - EXPECT_EQ("006007008", format("%E9f", tp, tz)); - EXPECT_EQ("0060070080", format("%E10f", tp, tz)); - EXPECT_EQ("00600700800", format("%E11f", tp, tz)); - EXPECT_EQ("006007008000", format("%E12f", tp, tz)); - EXPECT_EQ("0060070080000", format("%E13f", tp, tz)); - EXPECT_EQ("00600700800000", format("%E14f", tp, tz)); - EXPECT_EQ("006007008000000", format("%E15f", tp, tz)); - - // Times before the Unix epoch. - tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); - EXPECT_EQ("1969-12-31 23:59:59.999999", - format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); - - // Here is a "%E*S" case we got wrong for a while. While the first - // instant below is correctly rendered as "...:07.333304", the second - // one used to appear as "...:07.33330499999999999". - tp = chrono::system_clock::from_time_t(0) + - chrono::microseconds(1395024427333304); - EXPECT_EQ("2014-03-17 02:47:07.333304", - format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); - tp += chrono::microseconds(1); - EXPECT_EQ("2014-03-17 02:47:07.333305", - format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); -} - -TEST(Format, CompareExtendSecondsVsSubseconds) { - const time_zone tz = utc_time_zone(); - - // This test case illustrates the differences/similarities between: - // fmt_A: %E<prec>S - // fmt_B: %S.%E<prec>f - auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; }; - auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; }; - - // No subseconds: - time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); - tp += chrono::seconds(5); - // ... %E*S and %S.%E*f are different. - EXPECT_EQ("05", format(fmt_A("*"), tp, tz)); - EXPECT_EQ("05.0", format(fmt_B("*"), tp, tz)); - // ... %E0S and %S.%E0f are different. - EXPECT_EQ("05", format(fmt_A("0"), tp, tz)); - EXPECT_EQ("05.", format(fmt_B("0"), tp, tz)); - // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15]. - for (int prec = 1; prec <= 15; ++prec) { - const std::string a = format(fmt_A(std::to_string(prec)), tp, tz); - const std::string b = format(fmt_B(std::to_string(prec)), tp, tz); - EXPECT_EQ(a, b) << "prec=" << prec; - } - - // With subseconds: - // ... %E*S and %S.%E*f are the same. - tp += chrono::milliseconds(6) + chrono::microseconds(7) + - chrono::nanoseconds(8); - EXPECT_EQ("05.006007008", format(fmt_A("*"), tp, tz)); - EXPECT_EQ("05.006007008", format(fmt_B("*"), tp, tz)); - // ... %E0S and %S.%E0f are different. - EXPECT_EQ("05", format(fmt_A("0"), tp, tz)); - EXPECT_EQ("05.", format(fmt_B("0"), tp, tz)); - // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15]. - for (int prec = 1; prec <= 15; ++prec) { - const std::string a = format(fmt_A(std::to_string(prec)), tp, tz); - const std::string b = format(fmt_B(std::to_string(prec)), tp, tz); - EXPECT_EQ(a, b) << "prec=" << prec; - } -} - -TEST(Format, ExtendedOffset) { - const auto tp = chrono::system_clock::from_time_t(0); - - auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero()); - TestFormatSpecifier(tp, tz, "%z", "+0000"); - TestFormatSpecifier(tp, tz, "%:z", "+00:00"); - TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - - tz = fixed_time_zone(chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "+0000"); - TestFormatSpecifier(tp, tz, "%:z", "+00:00"); - TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - - tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00 - TestFormatSpecifier(tp, tz, "%z", "+0000"); - TestFormatSpecifier(tp, tz, "%:z", "+00:00"); - TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - - tz = fixed_time_zone(chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%z", "+0034"); - TestFormatSpecifier(tp, tz, "%:z", "+00:34"); - TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); - - tz = fixed_time_zone(-chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%z", "-0034"); - TestFormatSpecifier(tp, tz, "%:z", "-00:34"); - TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); - - tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "+0034"); - TestFormatSpecifier(tp, tz, "%:z", "+00:34"); - TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); - - tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "-0034"); - TestFormatSpecifier(tp, tz, "%:z", "-00:34"); - TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); - - tz = fixed_time_zone(chrono::hours(12)); - TestFormatSpecifier(tp, tz, "%z", "+1200"); - TestFormatSpecifier(tp, tz, "%:z", "+12:00"); - TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); - - tz = fixed_time_zone(-chrono::hours(12)); - TestFormatSpecifier(tp, tz, "%z", "-1200"); - TestFormatSpecifier(tp, tz, "%:z", "-12:00"); - TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "+1200"); - TestFormatSpecifier(tp, tz, "%:z", "+12:00"); - TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "-1200"); - TestFormatSpecifier(tp, tz, "%:z", "-12:00"); - TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%z", "+1234"); - TestFormatSpecifier(tp, tz, "%:z", "+12:34"); - TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%z", "-1234"); - TestFormatSpecifier(tp, tz, "%:z", "-12:34"); - TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "+1234"); - TestFormatSpecifier(tp, tz, "%:z", "+12:34"); - TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%z", "-1234"); - TestFormatSpecifier(tp, tz, "%:z", "-12:34"); - TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); -} - -TEST(Format, ExtendedSecondOffset) { - const auto tp = chrono::system_clock::from_time_t(0); - - auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero()); - TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00"); - TestFormatSpecifier(tp, tz, "%::z", "+00:00:00"); - TestFormatSpecifier(tp, tz, "%:::z", "+00"); - - tz = fixed_time_zone(chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56"); - TestFormatSpecifier(tp, tz, "%::z", "+00:00:56"); - TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56"); - - tz = fixed_time_zone(-chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56"); - TestFormatSpecifier(tp, tz, "%::z", "-00:00:56"); - TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56"); - - tz = fixed_time_zone(chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00"); - TestFormatSpecifier(tp, tz, "%::z", "+00:34:00"); - TestFormatSpecifier(tp, tz, "%:::z", "+00:34"); - - tz = fixed_time_zone(-chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00"); - TestFormatSpecifier(tp, tz, "%::z", "-00:34:00"); - TestFormatSpecifier(tp, tz, "%:::z", "-00:34"); - - tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56"); - TestFormatSpecifier(tp, tz, "%::z", "+00:34:56"); - TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56"); - - tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56"); - TestFormatSpecifier(tp, tz, "%::z", "-00:34:56"); - TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56"); - - tz = fixed_time_zone(chrono::hours(12)); - TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00"); - TestFormatSpecifier(tp, tz, "%::z", "+12:00:00"); - TestFormatSpecifier(tp, tz, "%:::z", "+12"); - - tz = fixed_time_zone(-chrono::hours(12)); - TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00"); - TestFormatSpecifier(tp, tz, "%::z", "-12:00:00"); - TestFormatSpecifier(tp, tz, "%:::z", "-12"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56"); - TestFormatSpecifier(tp, tz, "%::z", "+12:00:56"); - TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56"); - TestFormatSpecifier(tp, tz, "%::z", "-12:00:56"); - TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00"); - TestFormatSpecifier(tp, tz, "%::z", "+12:34:00"); - TestFormatSpecifier(tp, tz, "%:::z", "+12:34"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); - TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00"); - TestFormatSpecifier(tp, tz, "%::z", "-12:34:00"); - TestFormatSpecifier(tp, tz, "%:::z", "-12:34"); - - tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56"); - TestFormatSpecifier(tp, tz, "%::z", "+12:34:56"); - TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56"); - - tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - - chrono::seconds(56)); - TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56"); - TestFormatSpecifier(tp, tz, "%::z", "-12:34:56"); - TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56"); -} - -TEST(Format, ExtendedYears) { - const time_zone utc = utc_time_zone(); - const char e4y_fmt[] = "%E4Y%m%d"; // no separators - - // %E4Y zero-pads the year to produce at least 4 chars, including the sign. - auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00001127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00011127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00091127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00991127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("09991127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("99991127", format(e4y_fmt, tp, utc)); - - // When the year is outside [-999:9999], more than 4 chars are produced. - tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc)); - tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("100001127", format(e4y_fmt, tp, utc)); -} - -TEST(Format, RFC3339Format) { - time_zone tz; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - - time_point<chrono::nanoseconds> tp = - convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::milliseconds(100); - EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::milliseconds(20); - EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::milliseconds(3); - EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::microseconds(400); - EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::microseconds(50); - EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::microseconds(6); - EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::nanoseconds(700); - EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::nanoseconds(80); - EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); - - tp += chrono::nanoseconds(9); - EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00", - format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); -} - -TEST(Format, RFC1123Format) { // locale specific - time_zone tz; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - - auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz)); - 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() -// - -TEST(Parse, TimePointResolution) { - const char kFmt[] = "%H:%M:%E*S"; - const time_zone utc = utc_time_zone(); - - time_point<chrono::nanoseconds> tp_ns; - EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns)); - EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc)); - - time_point<chrono::microseconds> tp_us; - EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc)); - - time_point<chrono::milliseconds> tp_ms; - EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms)); - EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc)); - - time_point<chrono::seconds> tp_s; - EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s)); - EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); - EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s)); - EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); - - time_point<chrono::minutes> tp_m; - EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m)); - EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc)); - - time_point<chrono::hours> tp_h; - EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h)); - EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc)); -} - -TEST(Parse, TimePointExtendedResolution) { - const char kFmt[] = "%H:%M:%E*S"; - const time_zone utc = utc_time_zone(); - - time_point<absl::time_internal::cctz::seconds> tp; - detail::femtoseconds fs; - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc)); - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc)); - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc)); - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc)); - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc)); - EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs)); - EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc)); -} - -TEST(Parse, Basics) { - time_zone tz = utc_time_zone(); - time_point<chrono::nanoseconds> tp = - chrono::system_clock::from_time_t(1234567890); - - // Simple edge cases. - EXPECT_TRUE(parse("", "", tz, &tp)); - EXPECT_EQ(chrono::system_clock::from_time_t(0), tp); // everything defaulted - EXPECT_TRUE(parse(" ", " ", tz, &tp)); - EXPECT_TRUE(parse(" ", " ", tz, &tp)); - EXPECT_TRUE(parse("x", "x", tz, &tp)); - EXPECT_TRUE(parse("xxx", "xxx", tz, &tp)); - - EXPECT_TRUE( - parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp)); - ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC"); -} - -TEST(Parse, WithTimeZone) { - time_zone tz; - 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. - 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"); - - // But the timezone is ignored when a UTC offset is present. - EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800", - utc_time_zone(), &tp)); - ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT"); - - // Check a skipped time (a Spring DST transition). parse() uses the - // pre-transition offset. - EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp)); - ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT"); - - // Check a repeated time (a Fall DST transition). parse() uses the - // pre-transition offset. - EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp)); - ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT"); -} - -TEST(Parse, LeapSecond) { - time_zone tz; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - time_point<chrono::nanoseconds> tp; - - // ":59" -> ":59" - EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp)); - ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT"); - - // ":59.5" -> ":59.5" - EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp)); - ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT"); - - // ":60" -> ":00" - EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp)); - ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT"); - - // ":60.5" -> ":00.0" - EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp)); - ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT"); - - // ":61" -> error - EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp)); -} - -TEST(Parse, ErrorCases) { - const time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - - // Illegal trailing data. - EXPECT_FALSE(parse("%S", "123", tz, &tp)); - - // Can't parse an illegal format specifier. - EXPECT_FALSE(parse("%Q", "x", tz, &tp)); - - // Fails because of trailing, unparsed data "blah". - EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp)); - - // Trailing whitespace is allowed. - EXPECT_TRUE(parse("%m-%d", "2-3 ", tz, &tp)); - EXPECT_EQ(2, convert(tp, utc_time_zone()).month()); - EXPECT_EQ(3, convert(tp, utc_time_zone()).day()); - - // Feb 31 requires normalization. - EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp)); - - // Check that we cannot have spaces in UTC offsets. - EXPECT_TRUE(parse("%z", "-0203", tz, &tp)); - EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp)); - EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp)); - EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp)); - - // Check that we reject other malformed UTC offsets. - EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp)); - EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp)); - - // Check that we do not accept "-0" in fields that allow zero. - EXPECT_FALSE(parse("%Y", "-0", tz, &tp)); - EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp)); - EXPECT_FALSE(parse("%H", "-0", tz, &tp)); - EXPECT_FALSE(parse("%M", "-0", tz, &tp)); - EXPECT_FALSE(parse("%S", "-0", tz, &tp)); - EXPECT_FALSE(parse("%z", "+-000", tz, &tp)); - EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp)); - EXPECT_FALSE(parse("%z", "-00-0", tz, &tp)); - EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp)); -} - -TEST(Parse, PosixConversions) { - time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - - tp = reset; - EXPECT_TRUE(parse("%d", "15", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).day()); - - // %e is an extension, but is supported internally. - tp = reset; - EXPECT_TRUE(parse("%e", "15", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d - - tp = reset; - EXPECT_TRUE(parse("%H", "17", tz, &tp)); - EXPECT_EQ(17, convert(tp, tz).hour()); - - tp = reset; - EXPECT_TRUE(parse("%I", "5", tz, &tp)); - EXPECT_EQ(5, convert(tp, tz).hour()); - - // %j is parsed but ignored. - EXPECT_TRUE(parse("%j", "32", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%m", "11", tz, &tp)); - EXPECT_EQ(11, convert(tp, tz).month()); - - tp = reset; - EXPECT_TRUE(parse("%M", "33", tz, &tp)); - EXPECT_EQ(33, convert(tp, tz).minute()); - - tp = reset; - EXPECT_TRUE(parse("%S", "55", tz, &tp)); - EXPECT_EQ(55, convert(tp, tz).second()); - - // %U is parsed but ignored. - EXPECT_TRUE(parse("%U", "15", tz, &tp)); - - // %w is parsed but ignored. - EXPECT_TRUE(parse("%w", "2", tz, &tp)); - - // %W is parsed but ignored. - EXPECT_TRUE(parse("%W", "22", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%y", "04", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); - - tp = reset; - EXPECT_TRUE(parse("%Y", "2004", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); - - EXPECT_TRUE(parse("%%", "%", tz, &tp)); - -#if defined(__linux__) - // SU/C99/TZ extensions - - // Because we handle each (non-internal) specifier in a separate call - // to strptime(), there is no way to group %C and %y together. So we - // just skip the %C/%y case. -#if 0 - tp = reset; - EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); -#endif - - tp = reset; - EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); - EXPECT_EQ(3, convert(tp, tz).day()); - EXPECT_EQ(2004, convert(tp, tz).year()); - - EXPECT_TRUE(parse("%n", "\n", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%R", "03:44", tz, &tp)); - EXPECT_EQ(3, convert(tp, tz).hour()); - EXPECT_EQ(44, convert(tp, tz).minute()); - - EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp)); - EXPECT_EQ(3, convert(tp, tz).hour()); - EXPECT_EQ(44, convert(tp, tz).minute()); - EXPECT_EQ(55, convert(tp, tz).second()); - - tp = reset; - EXPECT_TRUE(parse("%s", "1234567890", tz, &tp)); - EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); - - // %s conversion, like %z/%Ez, pays no heed to the optional zone. - time_zone lax; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); - tp = reset; - EXPECT_TRUE(parse("%s", "1234567890", lax, &tp)); - EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); - - // This is most important when the time has the same YMDhms - // breakdown in the zone as some other time. For example, ... - // 1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT) - // 1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST) - tp = reset; - EXPECT_TRUE(parse("%s", "1414917000", lax, &tp)); - EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp); - tp = reset; - EXPECT_TRUE(parse("%s", "1414920600", lax, &tp)); - EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp); -#endif -} - -TEST(Parse, LocaleSpecific) { - time_zone tz = utc_time_zone(); - auto tp = chrono::system_clock::from_time_t(0); - const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - - // %a is parsed but ignored. - EXPECT_TRUE(parse("%a", "Mon", tz, &tp)); - - // %A is parsed but ignored. - EXPECT_TRUE(parse("%A", "Monday", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%b", "Feb", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); - - tp = reset; - EXPECT_TRUE(parse("%B", "February", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); - - // %p is parsed but ignored if it's alone. But it's used with %I. - EXPECT_TRUE(parse("%p", "AM", tz, &tp)); - tp = reset; - EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp)); - EXPECT_EQ(17, convert(tp, tz).hour()); - - tp = reset; - EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp)); - if (convert(tp, tz).month() == 2) { - EXPECT_EQ(3, convert(tp, tz).day()); - } else { - EXPECT_EQ(2, convert(tp, tz).day()); - EXPECT_EQ(3, convert(tp, tz).month()); - } - EXPECT_EQ(2004, convert(tp, tz).year()); - - tp = reset; - EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).hour()); - EXPECT_EQ(44, convert(tp, tz).minute()); - EXPECT_EQ(55, convert(tp, tz).second()); - -#if defined(__linux__) - // SU/C99/TZ extensions - - tp = reset; - EXPECT_TRUE(parse("%h", "Feb", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); // Equivalent to %b - - tp = reset; - EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp)); - EXPECT_EQ(17, convert(tp, tz).hour()); - - tp = reset; - EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).hour()); - EXPECT_EQ(44, convert(tp, tz).minute()); - EXPECT_EQ(55, convert(tp, tz).second()); - - tp = reset; - EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp)); - EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp); - - // Modified conversion specifiers %E_ - - tp = reset; - EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); - EXPECT_EQ(3, convert(tp, tz).day()); - EXPECT_EQ(2004, convert(tp, tz).year()); - - tp = reset; - EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).hour()); - EXPECT_EQ(44, convert(tp, tz).minute()); - EXPECT_EQ(55, convert(tp, tz).second()); - - // %Ey, the year offset from %EC, doesn't really make sense alone as there - // is no way to represent it in tm_year (%EC is not simply the century). - // Yet, because we handle each (non-internal) specifier in a separate call - // to strptime(), there is no way to group %EC and %Ey either. So we just - // skip the %EC and %Ey cases. - - tp = reset; - EXPECT_TRUE(parse("%EY", "2004", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); - - // Modified conversion specifiers %O_ - - tp = reset; - EXPECT_TRUE(parse("%Od", "15", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).day()); - - tp = reset; - EXPECT_TRUE(parse("%Oe", "15", tz, &tp)); - EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d - - tp = reset; - EXPECT_TRUE(parse("%OH", "17", tz, &tp)); - EXPECT_EQ(17, convert(tp, tz).hour()); - - tp = reset; - EXPECT_TRUE(parse("%OI", "5", tz, &tp)); - EXPECT_EQ(5, convert(tp, tz).hour()); - - tp = reset; - EXPECT_TRUE(parse("%Om", "11", tz, &tp)); - EXPECT_EQ(11, convert(tp, tz).month()); - - tp = reset; - EXPECT_TRUE(parse("%OM", "33", tz, &tp)); - EXPECT_EQ(33, convert(tp, tz).minute()); - - tp = reset; - EXPECT_TRUE(parse("%OS", "55", tz, &tp)); - EXPECT_EQ(55, convert(tp, tz).second()); - - // %OU is parsed but ignored. - EXPECT_TRUE(parse("%OU", "15", tz, &tp)); - - // %Ow is parsed but ignored. - EXPECT_TRUE(parse("%Ow", "2", tz, &tp)); - - // %OW is parsed but ignored. - EXPECT_TRUE(parse("%OW", "22", tz, &tp)); - - tp = reset; - EXPECT_TRUE(parse("%Oy", "04", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); -#endif -} - -TEST(Parse, ExtendedSeconds) { - const time_zone tz = utc_time_zone(); - const time_point<chrono::nanoseconds> unix_epoch = - chrono::system_clock::from_time_t(0); - - // 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) { - const std::string fmt = "%E" + prec + "S"; - SCOPED_TRACE(fmt); - time_point<chrono::nanoseconds> tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "5", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.0", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.00", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.6", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.60", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.600", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.67", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.670", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "05.678", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp); - } - - // Here is a "%E*S" case we got wrong for a while. The fractional - // part of the first instant is less than 2^31 and was correctly - // parsed, while the second (and any subsecond field >=2^31) failed. - time_point<chrono::nanoseconds> tp = unix_epoch; - EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); - tp = unix_epoch; - EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); - - // We should also be able to specify long strings of digits far - // beyond the current resolution and have them convert the same way. - tp = unix_epoch; - EXPECT_TRUE(parse( - "%E*S", "0.214748364801234567890123456789012345678901234567890123456789", - tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); -} - -TEST(Parse, ExtendedSecondsScan) { - const time_zone tz = utc_time_zone(); - time_point<chrono::nanoseconds> tp; - for (int ms = 0; ms < 1000; ms += 111) { - for (int us = 0; us < 1000; us += 27) { - const int micros = ms * 1000 + us; - for (int ns = 0; ns < 1000; ns += 9) { - const auto expected = chrono::system_clock::from_time_t(0) + - chrono::nanoseconds(micros * 1000 + ns); - std::ostringstream oss; - oss << "0." << std::setfill('0') << std::setw(3); - oss << ms << std::setw(3) << us << std::setw(3) << ns; - const std::string input = oss.str(); - EXPECT_TRUE(parse("%E*S", input, tz, &tp)); - EXPECT_EQ(expected, tp) << input; - } - } - } -} - -TEST(Parse, ExtendedSubeconds) { - const time_zone tz = utc_time_zone(); - const time_point<chrono::nanoseconds> unix_epoch = - chrono::system_clock::from_time_t(0); - - // 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) { - const std::string fmt = "%E" + prec + "f"; - SCOPED_TRACE(fmt); - time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1); - EXPECT_TRUE(parse(fmt, "", tz, &tp)); - EXPECT_EQ(unix_epoch, tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "6", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "60", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "600", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "67", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "670", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "678", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp); - tp = unix_epoch; - EXPECT_TRUE(parse(fmt, "6789", tz, &tp)); - EXPECT_EQ( - unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp); - } - - // Here is a "%E*f" case we got wrong for a while. The fractional - // part of the first instant is less than 2^31 and was correctly - // parsed, while the second (and any subsecond field >=2^31) failed. - time_point<chrono::nanoseconds> tp = unix_epoch; - EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); - tp = unix_epoch; - EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); - - // We should also be able to specify long strings of digits far - // beyond the current resolution and have them convert the same way. - tp = unix_epoch; - EXPECT_TRUE(parse( - "%E*f", "214748364801234567890123456789012345678901234567890123456789", - tz, &tp)); - EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); -} - -TEST(Parse, ExtendedSubecondsScan) { - time_point<chrono::nanoseconds> tp; - const time_zone tz = utc_time_zone(); - for (int ms = 0; ms < 1000; ms += 111) { - for (int us = 0; us < 1000; us += 27) { - const int micros = ms * 1000 + us; - for (int ns = 0; ns < 1000; ns += 9) { - std::ostringstream oss; - oss << std::setfill('0') << std::setw(3) << ms; - oss << std::setw(3) << us << std::setw(3) << ns; - const std::string nanos = oss.str(); - const auto expected = chrono::system_clock::from_time_t(0) + - chrono::nanoseconds(micros * 1000 + ns); - for (int ps = 0; ps < 1000; ps += 250) { - std::ostringstream ps_oss; - oss << std::setfill('0') << std::setw(3) << ps; - const std::string input = nanos + ps_oss.str() + "999"; - EXPECT_TRUE(parse("%E*f", input, tz, &tp)); - EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input; - } - } - } - } -} - -TEST(Parse, ExtendedOffset) { - const time_zone utc = utc_time_zone(); - time_point<absl::time_internal::cctz::seconds> tp; - - EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp)); - - for (auto fmt : {"%Ez", "%z"}) { - EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); - - EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); - EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); - } -} - -TEST(Parse, ExtendedSecondOffset) { - const time_zone utc = utc_time_zone(); - time_point<absl::time_internal::cctz::seconds> tp; - - for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) { - EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); - EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); - EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp)); - - EXPECT_TRUE(parse(fmt, "+000000", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-123456", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); - EXPECT_TRUE(parse(fmt, "+123456", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); - EXPECT_FALSE(parse(fmt, "-12345", utc, &tp)); - - EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp)); - - EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); - - EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); - EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); - EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); - } -} - -TEST(Parse, ExtendedYears) { - const time_zone utc = utc_time_zone(); - const char e4y_fmt[] = "%E4Y%m%d"; // no separators - time_point<absl::time_internal::cctz::seconds> tp; - - // %E4Y consumes exactly four chars, including any sign. - EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp)); - EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp)); - EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp)); - EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp)); - EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp)); - EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp)); - EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp)); - EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp)); - EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp)); - EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp)); - EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp); - - // When the year is outside [-999:9999], the parse fails. - EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp)); - EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp)); -} - -TEST(Parse, RFC3339Format) { - const time_zone tz = utc_time_zone(); - time_point<chrono::nanoseconds> tp; - 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". - time_point<chrono::nanoseconds> tp2; - EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2)); - EXPECT_EQ(tp, tp2); - - // Check that %Ez also accepts "Z" as a synonym for "+00:00". - time_point<chrono::nanoseconds> tp3; - EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3)); - EXPECT_EQ(tp, tp3); - - // Check that %Ez also accepts "z" as a synonym for "+00:00". - time_point<chrono::nanoseconds> tp4; - EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4)); - EXPECT_EQ(tp, tp4); -} - -TEST(Parse, Week) { - const time_zone utc = utc_time_zone(); - time_point<absl::time_internal::cctz::seconds> tp; - - auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp)); - EXPECT_EQ(exp, tp); -} - -TEST(Parse, WeekYearShift) { - // %U/%W conversions with week values in {0, 52, 53} can slip - // into the previous/following calendar years. - const time_zone utc = utc_time_zone(); - time_point<absl::time_internal::cctz::seconds> tp; - - auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp)); - EXPECT_EQ(exp, tp); - - exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc); - EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp)); - EXPECT_EQ(exp, tp); - EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); - EXPECT_EQ(exp, tp); - - // Slipping into the previous/following calendar years should fail when - // we're already at the extremes. - EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp)); - EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp)); -} - -TEST(Parse, MaxRange) { - const time_zone utc = utc_time_zone(); - time_point<absl::time_internal::cctz::seconds> tp; - - // tests the upper limit using +00:00 offset - EXPECT_TRUE( - parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp)); - EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max()); - EXPECT_FALSE( - parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp)); - - // tests the upper limit using -01:00 offset - EXPECT_TRUE( - 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-04T15:30:07-01:00", utc, &tp)); - - // tests the lower limit using +00:00 offset - EXPECT_TRUE( - parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp)); - EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min()); - EXPECT_FALSE( - parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp)); - - // tests the lower limit using +01:00 offset - EXPECT_TRUE( - parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp)); - EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min()); - EXPECT_FALSE( - parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp)); - - // tests max/min civil-second overflow - EXPECT_FALSE( - parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp)); - EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01", - utc, &tp)); - - // 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. -} - -// -// Roundtrip test for format()/parse(). -// - -TEST(FormatParse, RoundTrip) { - time_zone lax; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); - const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax); - const auto subseconds = chrono::nanoseconds(654321); - - // RFC3339, which renders subseconds. - { - time_point<chrono::nanoseconds> out; - const std::string s = format(RFC3339_full, in + subseconds, lax); - EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s; - EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez - } - - // RFC1123, which only does whole seconds. - { - time_point<chrono::nanoseconds> out; - const std::string s = format(RFC1123_full, in, lax); - EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s; - EXPECT_EQ(in, out); // RFC1123_full includes %z - } - -#if defined(_WIN32) || defined(_WIN64) - // Initial investigations indicate the %c does not roundtrip on Windows. - // TODO: Figure out what is going on here (perhaps a locale problem). -#elif defined(__EMSCRIPTEN__) - // strftime() and strptime() use different defintions for "%c" under - // emscripten (see https://github.com/kripken/emscripten/pull/7491), - // causing its round-trip test to fail. -#else - // Even though we don't know what %c will produce, it should roundtrip, - // but only in the 0-offset timezone. - { - time_point<chrono::nanoseconds> out; - time_zone utc = utc_time_zone(); - const std::string s = format("%c", in, utc); - EXPECT_TRUE(parse("%c", s, utc, &out)) << s; - EXPECT_EQ(in, out); - } -#endif -} - -TEST(FormatParse, RoundTripDistantFuture) { - const time_zone utc = utc_time_zone(); - const time_point<absl::time_internal::cctz::seconds> in = - time_point<absl::time_internal::cctz::seconds>::max(); - const std::string s = format(RFC3339_full, in, utc); - time_point<absl::time_internal::cctz::seconds> out; - EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; - EXPECT_EQ(in, out); -} - -TEST(FormatParse, RoundTripDistantPast) { - const time_zone utc = utc_time_zone(); - const time_point<absl::time_internal::cctz::seconds> in = - time_point<absl::time_internal::cctz::seconds>::min(); - const std::string s = format(RFC3339_full, in, utc); - time_point<absl::time_internal::cctz::seconds> out; - EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; - EXPECT_EQ(in, out); -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_if.cc b/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_if.cc deleted file mode 100644 index 0319b2f98e67..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_if.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_if.h" - -#include "absl/base/config.h" -#include "time_zone_info.h" -#include "time_zone_libc.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -std::unique_ptr<TimeZoneIf> TimeZoneIf::Load(const std::string& name) { - // Support "libc:localtime" and "libc:*" to access the legacy - // localtime and UTC support respectively from the C library. - if (name.compare(0, 5, "libc:") == 0) { - return std::unique_ptr<TimeZoneIf>(new TimeZoneLibC(name.substr(5))); - } - - // Otherwise use the "zoneinfo" implementation by default. - std::unique_ptr<TimeZoneInfo> tz(new TimeZoneInfo); - if (!tz->Load(name)) tz.reset(); - return std::unique_ptr<TimeZoneIf>(tz.release()); -} - -// Defined out-of-line to avoid emitting a weak vtable in all TUs. -TimeZoneIf::~TimeZoneIf() {} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 32c0891c1e77..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_if.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ - -#include <chrono> -#include <cstdint> -#include <memory> -#include <string> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A simple interface used to hide time-zone complexities from time_zone::Impl. -// Subclasses implement the functions for civil-time conversions in the zone. -class TimeZoneIf { - public: - // A factory function for TimeZoneIf implementations. - static std::unique_ptr<TimeZoneIf> Load(const std::string& name); - - virtual ~TimeZoneIf(); - - virtual time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const = 0; - virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0; - - virtual bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const = 0; - virtual bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const = 0; - - virtual std::string Version() const = 0; - virtual std::string Description() const = 0; - - protected: - 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, but not that they share an epoch. -inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) { - return (tp - std::chrono::time_point_cast<seconds>( - std::chrono::system_clock::from_time_t(0))) - .count(); -} -inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) { - return std::chrono::time_point_cast<seconds>( - std::chrono::system_clock::from_time_t(0)) + - seconds(t); -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ 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 deleted file mode 100644 index f34e3aec84d6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_impl.cc +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_impl.h" - -#include <deque> -#include <memory> -#include <mutex> -#include <string> -#include <unordered_map> -#include <utility> - -#include "absl/base/config.h" -#include "time_zone_fixed.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// time_zone::Impls are linked into a map to support fast lookup by name. -using TimeZoneImplByName = - std::unordered_map<std::string, const time_zone::Impl*>; -TimeZoneImplByName* time_zone_map = nullptr; - -// Mutual exclusion for time_zone_map. -std::mutex& TimeZoneMutex() { - // This mutex is intentionally "leaked" to avoid the static deinitialization - // order fiasco (std::mutex's destructor is not trivial on many platforms). - static std::mutex* time_zone_mutex = new std::mutex; - return *time_zone_mutex; -} - -} // namespace - -time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); } - -bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { - const Impl* const utc_impl = UTCImpl(); - - // 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. - { - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map != nullptr) { - TimeZoneImplByName::const_iterator itr = time_zone_map->find(name); - if (itr != time_zone_map->end()) { - *tz = time_zone(itr->second); - return itr->second != utc_impl; - } - } - } - - // Load the new time zone (outside the lock). - std::unique_ptr<const Impl> new_impl(new Impl(name)); - - // Add the new time zone to the map. - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; - const Impl*& impl = (*time_zone_map)[name]; - if (impl == nullptr) { // this thread won any load race - impl = new_impl->zone_ ? new_impl.release() : utc_impl; - } - *tz = time_zone(impl); - return impl != utc_impl; -} - -void time_zone::Impl::ClearTimeZoneMapTestOnly() { - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map != nullptr) { - // Existing time_zone::Impl* entries are in the wild, so we can't delete - // them. Instead, we move them to a private container, where they are - // logically unreachable but not "leaked". Future requests will result - // in reloading the data. - static auto* cleared = new std::deque<const time_zone::Impl*>; - for (const auto& element : *time_zone_map) { - cleared->push_back(element.second); - } - time_zone_map->clear(); - } -} - -time_zone::Impl::Impl(const std::string& name) - : name_(name), zone_(TimeZoneIf::Load(name_)) {} - -const time_zone::Impl* time_zone::Impl::UTCImpl() { - static const Impl* utc_impl = new Impl("UTC"); // never fails - return utc_impl; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/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 deleted file mode 100644 index 7d747ba96617..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_impl.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ - -#include <memory> -#include <string> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" -#include "time_zone_if.h" -#include "time_zone_info.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// time_zone::Impl is the internal object referenced by a cctz::time_zone. -class time_zone::Impl { - public: - // The UTC time zone. Also used for other time zones that fail to load. - static time_zone UTC(); - - // Load a named time zone. Returns false if the name is invalid, or if - // some other kind of error occurs. Note that loading "UTC" never fails. - static bool LoadTimeZone(const std::string& name, time_zone* tz); - - // Clears the map of cached time zones. Primarily for use in benchmarks - // that gauge the performance of loading/parsing the time-zone data. - static void ClearTimeZoneMapTestOnly(); - - // The primary key is the time-zone ID (e.g., "America/New_York"). - const std::string& Name() const { - // TODO: It would nice if the zoneinfo data included the zone name. - return name_; - } - - // Breaks a time_point down to civil-time components in this time zone. - time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const { - return zone_->BreakTime(tp); - } - - // Converts the civil-time components in this time zone into a time_point. - // That is, the opposite of BreakTime(). The requested civil time may be - // ambiguous or illegal due to a change of UTC offset. - time_zone::civil_lookup MakeTime(const civil_second& cs) const { - return zone_->MakeTime(cs); - } - - // Finds the time of the next/previous offset change in this time zone. - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - return zone_->NextTransition(tp, trans); - } - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - return zone_->PrevTransition(tp, trans); - } - - // Returns an implementation-defined version string for this time zone. - std::string Version() const { return zone_->Version(); } - - // Returns an implementation-defined description of this time zone. - std::string Description() const { return zone_->Description(); } - - private: - explicit Impl(const std::string& name); - static const Impl* UTCImpl(); - - const std::string name_; - std::unique_ptr<TimeZoneIf> zone_; -}; - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ 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 deleted file mode 100644 index 8039353e585e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_info.cc +++ /dev/null @@ -1,965 +0,0 @@ -// Copyright 2016 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. - -// This file implements the TimeZoneIf interface using the "zoneinfo" -// data provided by the IANA Time Zone Database (i.e., the only real game -// in town). -// -// TimeZoneInfo represents the history of UTC-offset changes within a time -// zone. Most changes are due to daylight-saving rules, but occasionally -// shifts are made to the time-zone's base offset. The database only attempts -// to be definitive for times since 1970, so be wary of local-time conversions -// before that. Also, rule and zone-boundary changes are made at the whim -// of governments, so the conversion of future times needs to be taken with -// a grain of salt. -// -// For more information see tzfile(5), http://www.iana.org/time-zones, or -// https://en.wikipedia.org/wiki/Zoneinfo. -// -// Note that we assume the proleptic Gregorian calendar and 60-second -// minutes throughout. - -#include "time_zone_info.h" - -#include <algorithm> -#include <cassert> -#include <chrono> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <functional> -#include <memory> -#include <sstream> -#include <string> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_fixed.h" -#include "time_zone_posix.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -inline bool IsLeap(year_t year) { - return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); -} - -// The number of days in non-leap and leap years respectively. -const std::int_least32_t kDaysPerYear[2] = {365, 366}; - -// The day offsets of the beginning of each (1-based) month in non-leap and -// leap years respectively (e.g., 335 days before December in a leap year). -const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { - {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, - {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, -}; - -// We reject leap-second encoded zoneinfo and so assume 60-second minutes. -const std::int_least32_t kSecsPerDay = 24 * 60 * 60; - -// 400-year chunks always have 146097 days (20871 weeks). -const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay; - -// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay. -const std::int_least32_t kSecsPerYear[2] = { - 365 * kSecsPerDay, - 366 * kSecsPerDay, -}; - -// 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; -} - -// Multi-byte, numeric values are encoded using a MSB first, -// twos-complement representation. These helpers decode, from -// the given address, 4-byte and 8-byte values respectively. -// Note: If int_fastXX_t == intXX_t and this machine is not -// twos complement, then there will be at least one input value -// we cannot represent. -std::int_fast32_t Decode32(const char* cp) { - std::uint_fast32_t v = 0; - for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++); - const std::int_fast32_t s32max = 0x7fffffff; - const auto s32maxU = static_cast<std::uint_fast32_t>(s32max); - if (v <= s32maxU) return static_cast<std::int_fast32_t>(v); - return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1; -} - -std::int_fast64_t Decode64(const char* cp) { - std::uint_fast64_t v = 0; - for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++); - const std::int_fast64_t s64max = 0x7fffffffffffffff; - const auto s64maxU = static_cast<std::uint_fast64_t>(s64max); - if (v <= s64maxU) return static_cast<std::int_fast64_t>(v); - return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1; -} - -// Generate a year-relative offset for a PosixTransition. -std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday, - const PosixTransition& pt) { - std::int_fast64_t days = 0; - switch (pt.date.fmt) { - case PosixTransition::J: { - days = pt.date.j.day; - if (!leap_year || days < kMonthOffsets[1][3]) days -= 1; - break; - } - case PosixTransition::N: { - days = pt.date.n.day; - break; - } - case PosixTransition::M: { - const bool last_week = (pt.date.m.week == 5); - days = kMonthOffsets[leap_year][pt.date.m.month + last_week]; - const std::int_fast64_t weekday = (jan1_weekday + days) % 7; - if (last_week) { - days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1; - } else { - days += (pt.date.m.weekday + 7 - weekday) % 7; - days += (pt.date.m.week - 1) * 7; - } - break; - } - } - return (days * kSecsPerDay) + pt.time.offset; -} - -inline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::UNIQUE; - cl.pre = cl.trans = cl.post = tp; - return cl; -} - -inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) { - return MakeUnique(FromUnixSeconds(unix_time)); -} - -inline time_zone::civil_lookup MakeSkipped(const Transition& tr, - const civil_second& cs) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::SKIPPED; - cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec)); - cl.trans = FromUnixSeconds(tr.unix_time); - cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs)); - return cl; -} - -inline time_zone::civil_lookup MakeRepeated(const Transition& tr, - const civil_second& cs) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::REPEATED; - cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs)); - cl.trans = FromUnixSeconds(tr.unix_time); - cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec)); - return cl; -} - -inline civil_second YearShift(const civil_second& cs, year_t shift) { - return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(), - cs.minute(), cs.second()); -} - -} // namespace - -// What (no leap-seconds) UTC+seconds zoneinfo would look like. -bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { - transition_types_.resize(1); - TransitionType& tt(transition_types_.back()); - tt.utc_offset = static_cast<std::int_least32_t>(offset.count()); - tt.is_dst = false; - tt.abbr_index = 0; - - // We temporarily add some redundant, contemporary (2015 through 2025) - // transitions for performance reasons. See TimeZoneInfo::LocalTime(). - // TODO: Fix the performance issue and remove the extra transitions. - transitions_.clear(); - transitions_.reserve(12); - for (const std::int_fast64_t unix_time : { - -(1LL << 59), // a "first half" transition - 1420070400LL, // 2015-01-01T00:00:00+00:00 - 1451606400LL, // 2016-01-01T00:00:00+00:00 - 1483228800LL, // 2017-01-01T00:00:00+00:00 - 1514764800LL, // 2018-01-01T00:00:00+00:00 - 1546300800LL, // 2019-01-01T00:00:00+00:00 - 1577836800LL, // 2020-01-01T00:00:00+00:00 - 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 - }) { - Transition& tr(*transitions_.emplace(transitions_.end())); - tr.unix_time = unix_time; - tr.type_index = 0; - tr.civil_sec = LocalTime(tr.unix_time, tt).cs; - tr.prev_civil_sec = tr.civil_sec - 1; - } - - default_transition_type_ = 0; - abbreviations_ = FixedOffsetToAbbr(offset); - abbreviations_.append(1, '\0'); - future_spec_.clear(); // never needed for a fixed-offset zone - extended_ = false; - - tt.civil_max = LocalTime(seconds::max().count(), tt).cs; - tt.civil_min = LocalTime(seconds::min().count(), tt).cs; - - transitions_.shrink_to_fit(); - return true; -} - -// Builds the in-memory header using the raw bytes from the file. -bool TimeZoneInfo::Header::Build(const tzhead& tzh) { - std::int_fast32_t v; - if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false; - timecnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false; - typecnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false; - charcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false; - leapcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false; - ttisstdcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false; - ttisutcnt = static_cast<std::size_t>(v); - return true; -} - -// How many bytes of data are associated with this header. The result -// depends upon whether this is a section with 4-byte or 8-byte times. -std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const { - std::size_t len = 0; - len += (time_len + 1) * timecnt; // unix_time + type_index - len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index - len += 1 * charcnt; // abbreviations - len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC - len += 1 * ttisstdcnt; // UTC/local indicators - len += 1 * ttisutcnt; // standard/wall indicators - return len; -} - -// 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). -bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, - std::uint_fast8_t tt2_index) const { - 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.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() { - extended_ = false; - if (future_spec_.empty()) return true; // last transition prevails - - 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); - } - - // 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); - 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(); - 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; - jan1_time += kSecsPerYear[leap_year]; - jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; - leap_year = !leap_year && IsLeap(last_year_ + 1); - } - - return true; -} - -bool TimeZoneInfo::Load(ZoneInfoSource* zip) { - // Read and validate the header. - tzhead tzh; - if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; - if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) - return false; - Header hdr; - if (!hdr.Build(tzh)) return false; - std::size_t time_len = 4; - if (tzh.tzh_version[0] != '\0') { - // Skip the 4-byte data. - if (zip->Skip(hdr.DataLength(time_len)) != 0) return false; - // Read and validate the header for the 8-byte data. - if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; - if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) - return false; - if (tzh.tzh_version[0] == '\0') return false; - if (!hdr.Build(tzh)) return false; - time_len = 8; - } - if (hdr.typecnt == 0) return false; - if (hdr.leapcnt != 0) { - // This code assumes 60-second minutes so we do not want - // the leap-second encoded zoneinfo. We could reverse the - // compensation, but the "right" encoding is rarely used - // so currently we simply reject such data. - return false; - } - if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false; - if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false; - - // Read the data into a local buffer. - std::size_t len = hdr.DataLength(time_len); - std::vector<char> tbuf(len); - if (zip->Read(tbuf.data(), len) != len) return false; - const char* bp = tbuf.data(); - - // Decode and validate the transitions. - transitions_.reserve(hdr.timecnt + 2); - transitions_.resize(hdr.timecnt); - for (std::size_t i = 0; i != hdr.timecnt; ++i) { - transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); - bp += time_len; - if (i != 0) { - // Check that the transitions are ordered by time (as zic guarantees). - if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i])) - return false; // out of order - } - } - bool seen_type_0 = false; - for (std::size_t i = 0; i != hdr.timecnt; ++i) { - transitions_[i].type_index = Decode8(bp++); - if (transitions_[i].type_index >= hdr.typecnt) return false; - if (transitions_[i].type_index == 0) seen_type_0 = true; - } - - // 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 = - static_cast<std::int_least32_t>(Decode32(bp)); - if (transition_types_[i].utc_offset >= kSecsPerDay || - transition_types_[i].utc_offset <= -kSecsPerDay) - return false; - bp += 4; - transition_types_[i].is_dst = (Decode8(bp++) != 0); - transition_types_[i].abbr_index = Decode8(bp++); - if (transition_types_[i].abbr_index >= hdr.charcnt) return false; - } - - // Determine the before-first-transition type. - default_transition_type_ = 0; - if (seen_type_0 && hdr.timecnt != 0) { - std::uint_fast8_t index = 0; - if (transition_types_[0].is_dst) { - index = transitions_[0].type_index; - while (index != 0 && transition_types_[index].is_dst) --index; - } - while (index != hdr.typecnt && transition_types_[index].is_dst) ++index; - if (index != hdr.typecnt) default_transition_type_ = index; - } - - // Copy all the abbreviations. - abbreviations_.reserve(hdr.charcnt + 10); - abbreviations_.assign(bp, hdr.charcnt); - bp += hdr.charcnt; - - // Skip the unused portions. We've already dispensed with leap-second - // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when - // interpreting a POSIX spec that does not include start/end rules, and - // that isn't the case here (see "zic -p"). - bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC - bp += 1 * hdr.ttisstdcnt; // UTC/local indicators - bp += 1 * hdr.ttisutcnt; // standard/wall indicators - assert(bp == tbuf.data() + tbuf.size()); - - future_spec_.clear(); - if (tzh.tzh_version[0] != '\0') { - // Snarf up the NL-enclosed future POSIX spec. Note - // that version '3' files utilize an extended format. - auto get_char = [](ZoneInfoSource* azip) -> int { - unsigned char ch; // all non-EOF results are positive - return (azip->Read(&ch, 1) == 1) ? ch : EOF; - }; - if (get_char(zip) != '\n') return false; - for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { - if (c == EOF) return false; - future_spec_.push_back(static_cast<char>(c)); - } - } - - // We don't check for EOF so that we're forwards compatible. - - // 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. - if (version_.empty()) { - version_ = zip->Version(); - } - - // Trim redundant transitions. zic may have added these to work around - // differences between the glibc and reference implementations (see - // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071). - // For us, they just get in the way when we do future_spec_ extension. - while (hdr.timecnt > 1) { - if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index, - transitions_[hdr.timecnt - 2].type_index)) { - break; - } - hdr.timecnt -= 1; - } - 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. - 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.type_index = default_transition_type_; - } - - // 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; - } - - // Compute the local civil time for each transition and the preceding - // second. These will be used for reverse conversions in MakeTime(). - const TransitionType* ttp = &transition_types_[default_transition_type_]; - for (std::size_t i = 0; i != transitions_.size(); ++i) { - Transition& tr(transitions_[i]); - tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1; - ttp = &transition_types_[tr.type_index]; - tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs; - if (i != 0) { - // Check that the transitions are ordered by civil time. Essentially - // this means that an offset change cannot cross another such change. - // No one does this in practice, and we depend on it in MakeTime(). - if (!Transition::ByCivilTime()(transitions_[i - 1], tr)) - return false; // out of order - } - } - - // Compute the maximum/minimum civil times that can be converted to a - // time_point<seconds> for each of the zone's transition types. - for (auto& tt : transition_types_) { - tt.civil_max = LocalTime(seconds::max().count(), tt).cs; - tt.civil_min = LocalTime(seconds::min().count(), tt).cs; - } - - transitions_.shrink_to_fit(); - return true; -} - -namespace { - -// fopen(3) adaptor. -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 fp; -#else - return fopen(path, mode); // TODO: Enable the close-on-exec flag. -#endif -} - -// A stdio(3)-backed implementation of ZoneInfoSource. -class FileZoneInfoSource : public ZoneInfoSource { - public: - static std::unique_ptr<ZoneInfoSource> Open(const std::string& name); - - std::size_t Read(void* ptr, std::size_t size) override { - size = std::min(size, len_); - std::size_t nread = fread(ptr, 1, size, fp_.get()); - len_ -= nread; - return nread; - } - int Skip(std::size_t offset) override { - offset = std::min(offset, len_); - int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR); - if (rc == 0) len_ -= offset; - return rc; - } - std::string Version() const override { - // TODO: It would nice if the zoneinfo data included the tzdb version. - return std::string(); - } - - protected: - explicit FileZoneInfoSource( - FILE* fp, std::size_t len = std::numeric_limits<std::size_t>::max()) - : fp_(fp, fclose), len_(len) {} - - private: - std::unique_ptr<FILE, int (*)(FILE*)> fp_; - std::size_t len_; -}; - -std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open( - const std::string& name) { - // Use of the "file:" prefix is intended for testing purposes only. - const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; - - // Map the time-zone name to a path name. - std::string path; - if (pos == name.size() || name[pos] != '/') { - const char* tzdir = "/usr/share/zoneinfo"; - char* tzdir_env = nullptr; -#if defined(_MSC_VER) - _dupenv_s(&tzdir_env, nullptr, "TZDIR"); -#else - tzdir_env = std::getenv("TZDIR"); -#endif - if (tzdir_env && *tzdir_env) tzdir = tzdir_env; - path += tzdir; - path += '/'; -#if defined(_MSC_VER) - free(tzdir_env); -#endif - } - path.append(name, pos, std::string::npos); - - // Open the zoneinfo file. - FILE* fp = FOpen(path.c_str(), "rb"); - if (fp == nullptr) return nullptr; - std::size_t length = 0; - if (fseek(fp, 0, SEEK_END) == 0) { - long 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 { - public: - static std::unique_ptr<ZoneInfoSource> Open(const std::string& name); - std::string Version() const override { return version_; } - - private: - explicit AndroidZoneInfoSource(FILE* fp, std::size_t len, const char* vers) - : FileZoneInfoSource(fp, len), version_(vers) {} - std::string version_; -}; - -std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::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; - - // See Android's libc/tzcode/bionic.cpp for additional information. - for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", - "/system/usr/share/zoneinfo/tzdata"}) { - 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; - if (strncmp(hbuf, "tzdata", 6) != 0) continue; - const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : ""; - const std::int_fast32_t index_offset = Decode32(hbuf + 12); - const std::int_fast32_t data_offset = Decode32(hbuf + 16); - if (index_offset < 0 || data_offset < index_offset) continue; - if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0) - continue; - - char ebuf[52]; // covers entry.unused too - const std::size_t index_size = - static_cast<std::size_t>(data_offset - index_offset); - const std::size_t zonecnt = index_size / sizeof(ebuf); - if (zonecnt * sizeof(ebuf) != index_size) continue; - for (std::size_t i = 0; i != zonecnt; ++i) { - if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break; - const std::int_fast32_t start = data_offset + Decode32(ebuf + 40); - const std::int_fast32_t length = Decode32(ebuf + 44); - if (start < 0 || length < 0) break; - ebuf[40] = '\0'; // ensure zone name is NUL terminated - if (strcmp(name.c_str() + pos, ebuf) == 0) { - if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break; - return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource( - fp.release(), static_cast<std::size_t>(length), vers)); - } - } - } - - return nullptr; -} - -} // namespace - -bool TimeZoneInfo::Load(const std::string& name) { - // We can ensure that the loading of UTC or any other fixed-offset - // zone never fails because the simple, fixed-offset state can be - // internally generated. Note that this depends on our choice to not - // accept leap-second encoded ("right") zoneinfo. - auto offset = seconds::zero(); - if (FixedOffsetFromName(name, &offset)) { - return ResetToBuiltinUTC(offset); - } - - // 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; - return nullptr; - }); - return zip != nullptr && Load(zip.get()); -} - -// BreakTime() translation for a particular transition type. -time_zone::absolute_lookup TimeZoneInfo::LocalTime( - std::int_fast64_t unix_time, const TransitionType& tt) const { - // A civil time in "+offset" looks like (time+offset) in UTC. - // Note: We perform two additions in the civil_second domain to - // sidestep the chance of overflow in (unix_time + tt.utc_offset). - return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset, - tt.is_dst, &abbreviations_[tt.abbr_index]}; -} - -// BreakTime() translation for a particular transition. -time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time, - const Transition& tr) const { - const TransitionType& tt = transition_types_[tr.type_index]; - // Note: (unix_time - tr.unix_time) will never overflow as we - // have ensured that there is always a "nearby" transition. - return {tr.civil_sec + (unix_time - tr.unix_time), // TODO: Optimize. - tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; -} - -// MakeTime() translation with a conversion-preserving +N * 400-year shift. -time_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs, - year_t c4_shift) const { - assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_); - time_zone::civil_lookup cl = MakeTime(cs); - if (c4_shift > seconds::max().count() / kSecsPer400Years) { - cl.pre = cl.trans = cl.post = time_point<seconds>::max(); - } else { - const auto offset = seconds(c4_shift * kSecsPer400Years); - const auto limit = time_point<seconds>::max() - offset; - for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) { - if (*tp > limit) { - *tp = time_point<seconds>::max(); - } else { - *tp += offset; - } - } - } - return cl; -} - -time_zone::absolute_lookup TimeZoneInfo::BreakTime( - const time_point<seconds>& tp) const { - std::int_fast64_t unix_time = ToUnixSeconds(tp); - const std::size_t timecnt = transitions_.size(); - assert(timecnt != 0); // We always add a transition. - - if (unix_time < transitions_[0].unix_time) { - return LocalTime(unix_time, transition_types_[default_transition_type_]); - } - if (unix_time >= transitions_[timecnt - 1].unix_time) { - // After the last transition. If we extended the transitions using - // future_spec_, shift back to a supported year using the 400-year - // cycle of calendaric equivalence and then compensate accordingly. - if (extended_) { - const std::int_fast64_t diff = - unix_time - transitions_[timecnt - 1].unix_time; - const year_t shift = diff / kSecsPer400Years + 1; - const auto d = seconds(shift * kSecsPer400Years); - time_zone::absolute_lookup al = BreakTime(tp - d); - al.cs = YearShift(al.cs, shift * 400); - return al; - } - return LocalTime(unix_time, transitions_[timecnt - 1]); - } - - const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed); - if (0 < hint && hint < timecnt) { - if (transitions_[hint - 1].unix_time <= unix_time) { - if (unix_time < transitions_[hint].unix_time) { - return LocalTime(unix_time, transitions_[hint - 1]); - } - } - } - - const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* begin = &transitions_[0]; - const Transition* tr = std::upper_bound(begin, begin + timecnt, target, - Transition::ByUnixTime()); - local_time_hint_.store(static_cast<std::size_t>(tr - begin), - std::memory_order_relaxed); - return LocalTime(unix_time, *--tr); -} - -time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { - const std::size_t timecnt = transitions_.size(); - assert(timecnt != 0); // We always add a transition. - - // Find the first transition after our target civil time. - const Transition* tr = nullptr; - const Transition* begin = &transitions_[0]; - const Transition* end = begin + timecnt; - if (cs < begin->civil_sec) { - tr = begin; - } else if (cs >= transitions_[timecnt - 1].civil_sec) { - tr = end; - } else { - const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed); - if (0 < hint && hint < timecnt) { - if (transitions_[hint - 1].civil_sec <= cs) { - if (cs < transitions_[hint].civil_sec) { - tr = begin + hint; - } - } - } - if (tr == nullptr) { - const Transition target = {0, 0, cs, civil_second()}; - tr = std::upper_bound(begin, end, target, Transition::ByCivilTime()); - time_local_hint_.store(static_cast<std::size_t>(tr - begin), - std::memory_order_relaxed); - } - } - - if (tr == begin) { - if (tr->prev_civil_sec >= cs) { - // Before first transition, so use the default offset. - const TransitionType& tt(transition_types_[default_transition_type_]); - if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min()); - return MakeUnique(cs - (civil_second() + tt.utc_offset)); - } - // tr->prev_civil_sec < cs < tr->civil_sec - return MakeSkipped(*tr, cs); - } - - if (tr == end) { - if (cs > (--tr)->prev_civil_sec) { - // After the last transition. If we extended the transitions using - // future_spec_, shift back to a supported year using the 400-year - // cycle of calendaric equivalence and then compensate accordingly. - if (extended_ && cs.year() > last_year_) { - const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1; - return TimeLocal(YearShift(cs, shift * -400), shift); - } - const TransitionType& tt(transition_types_[tr->type_index]); - if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max()); - return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); - } - // tr->civil_sec <= cs <= tr->prev_civil_sec - return MakeRepeated(*tr, cs); - } - - if (tr->prev_civil_sec < cs) { - // tr->prev_civil_sec < cs < tr->civil_sec - return MakeSkipped(*tr, cs); - } - - if (cs <= (--tr)->prev_civil_sec) { - // tr->civil_sec <= cs <= tr->prev_civil_sec - return MakeRepeated(*tr, cs); - } - - // In between transitions. - return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); -} - -std::string TimeZoneInfo::Version() const { return version_; } - -std::string TimeZoneInfo::Description() const { - std::ostringstream oss; - oss << "#trans=" << transitions_.size(); - oss << " #types=" << transition_types_.size(); - oss << " spec='" << future_spec_ << "'"; - return oss.str(); -} - -bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - if (transitions_.empty()) return false; - 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. - ++begin; - } - std::int_fast64_t unix_time = ToUnixSeconds(tp); - const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* tr = - std::upper_bound(begin, end, target, Transition::ByUnixTime()); - for (; tr != end; ++tr) { // skip no-op transitions - std::uint_fast8_t prev_type_index = - (tr == begin) ? default_transition_type_ : tr[-1].type_index; - if (!EquivTransitions(prev_type_index, tr[0].type_index)) break; - } - // When tr == end we return false, ignoring future_spec_. - if (tr == end) return false; - trans->from = tr->prev_civil_sec + 1; - trans->to = tr->civil_sec; - return true; -} - -bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - if (transitions_.empty()) return false; - 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. - ++begin; - } - std::int_fast64_t unix_time = ToUnixSeconds(tp); - if (FromUnixSeconds(unix_time) != tp) { - if (unix_time == std::numeric_limits<std::int_fast64_t>::max()) { - if (end == begin) return false; // Ignore future_spec_. - trans->from = (--end)->prev_civil_sec + 1; - trans->to = end->civil_sec; - return true; - } - unix_time += 1; // ceils - } - const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* tr = - std::lower_bound(begin, end, target, Transition::ByUnixTime()); - for (; tr != begin; --tr) { // skip no-op transitions - std::uint_fast8_t prev_type_index = - (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; - if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break; - } - // When tr == end we return the "last" transition, ignoring future_spec_. - if (tr == begin) return false; - trans->from = (--tr)->prev_civil_sec + 1; - trans->to = tr->civil_sec; - return true; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 2467ff559d35..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_info.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ - -#include <atomic> -#include <cstddef> -#include <cstdint> -#include <string> -#include <vector> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" -#include "absl/time/internal/cctz/include/cctz/zone_info_source.h" -#include "time_zone_if.h" -#include "tzfile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A transition to a new UTC offset. -struct Transition { - std::int_least64_t unix_time; // the instant of this transition - std::uint_least8_t type_index; // index of the transition type - civil_second civil_sec; // local civil time of transition - civil_second prev_civil_sec; // local civil time one second earlier - - struct ByUnixTime { - inline bool operator()(const Transition& lhs, const Transition& rhs) const { - return lhs.unix_time < rhs.unix_time; - } - }; - struct ByCivilTime { - inline bool operator()(const Transition& lhs, const Transition& rhs) const { - return lhs.civil_sec < rhs.civil_sec; - } - }; -}; - -// The characteristics of a particular transition. -struct TransitionType { - std::int_least32_t utc_offset; // the new prevailing UTC offset - civil_second civil_max; // max convertible civil time for offset - civil_second civil_min; // min convertible civil time for offset - bool is_dst; // did we move into daylight-saving time - std::uint_least8_t abbr_index; // index of the new abbreviation -}; - -// A time zone backed by the IANA Time Zone Database (zoneinfo). -class TimeZoneInfo : public TimeZoneIf { - public: - TimeZoneInfo() = default; - TimeZoneInfo(const TimeZoneInfo&) = delete; - TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; - - // Loads the zoneinfo for the given name, returning true if successful. - bool Load(const std::string& name); - - // TimeZoneIf implementations. - time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const override; - time_zone::civil_lookup MakeTime(const civil_second& cs) const override; - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - std::string Version() const override; - std::string Description() const override; - - private: - struct Header { // counts of: - std::size_t timecnt; // transition times - std::size_t typecnt; // transition types - std::size_t charcnt; // zone abbreviation characters - std::size_t leapcnt; // leap seconds (we expect none) - std::size_t ttisstdcnt; // UTC/local indicators (unused) - std::size_t ttisutcnt; // standard/wall indicators (unused) - - bool Build(const tzhead& tzh); - 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); - bool EquivTransitions(std::uint_fast8_t tt1_index, - std::uint_fast8_t tt2_index) const; - bool ExtendTransitions(); - - bool ResetToBuiltinUTC(const seconds& offset); - bool Load(ZoneInfoSource* zip); - - // Helpers for BreakTime() and MakeTime(). - time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, - const TransitionType& tt) const; - time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, - const Transition& tr) const; - time_zone::civil_lookup TimeLocal(const civil_second& cs, - year_t c4_shift) const; - - std::vector<Transition> transitions_; // ordered by unix_time and civil_sec - std::vector<TransitionType> transition_types_; // distinct transition types - std::uint_fast8_t default_transition_type_; // for before first transition - std::string abbreviations_; // all the NUL-terminated abbreviations - - std::string version_; // the tzdata version if available - std::string future_spec_; // for after the last zic transition - bool extended_; // future_spec_ was used to generate transitions - year_t last_year_; // the final year of the generated transitions - - // We remember the transitions found during the last BreakTime() and - // MakeTime() calls. If the next request is for the same transition we - // will avoid re-searching. - mutable std::atomic<std::size_t> local_time_hint_ = {}; // BreakTime() hint - mutable std::atomic<std::size_t> time_local_hint_ = {}; // MakeTime() hint -}; - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ 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 deleted file mode 100644 index 887dd097c650..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_libc.cc +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2016 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. - -#if defined(_WIN32) || defined(_WIN64) -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#include "time_zone_libc.h" - -#include <chrono> -#include <ctime> -#include <limits> -#include <utility> - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -#if defined(_AIX) -extern "C" { -extern long altzone; -} -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -#if defined(_WIN32) || defined(_WIN64) -// Uses the globals: '_timezone', '_dstbias' and '_tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { - const bool is_dst = tm.tm_isdst > 0; - return _timezone + (is_dst ? _dstbias : 0); -} -auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return _tzname[is_dst]; -} -#elif defined(__sun) || defined(_AIX) -// Uses the globals: 'timezone', 'altzone' and 'tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { - const bool is_dst = tm.tm_isdst > 0; - return is_dst ? altzone : timezone; -} -auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return tzname[is_dst]; -} -#elif defined(__native_client__) || defined(__myriad2__) || \ - defined(__EMSCRIPTEN__) -// Uses the globals: 'timezone' and 'tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { - const bool is_dst = tm.tm_isdst > 0; - return _timezone + (is_dst ? 60 * 60 : 0); -} -auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return tzname[is_dst]; -} -#else -// Adapt to different spellings of the struct std::tm extension fields. -#if defined(tm_gmtoff) -auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { - return tm.tm_gmtoff; -} -#elif defined(__tm_gmtoff) -auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { - return tm.__tm_gmtoff; -} -#else -template <typename T> -auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { - return tm.tm_gmtoff; -} -template <typename T> -auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { - return tm.__tm_gmtoff; -} -#endif // tm_gmtoff -#if defined(tm_zone) -auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; } -#elif defined(__tm_zone) -auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { - return tm.__tm_zone; -} -#else -template <typename T> -auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { - return tm.tm_zone; -} -template <typename T> -auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { - return tm.__tm_zone; -} -#endif // tm_zone -#endif - -inline std::tm* gm_time(const std::time_t* timep, std::tm* result) { -#if defined(_WIN32) || defined(_WIN64) - return gmtime_s(result, timep) ? nullptr : result; -#else - return gmtime_r(timep, result); -#endif -} - -inline std::tm* local_time(const std::time_t* timep, std::tm* result) { -#if defined(_WIN32) || defined(_WIN64) - return localtime_s(result, timep) ? nullptr : result; -#else - return localtime_r(timep, result); -#endif -} - -// Converts a civil second and "dst" flag into a time_t and UTC offset. -// Returns false if time_t cannot represent the requested civil second. -// Caller must have already checked that cs.year() will fit into a tm_year. -bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { - std::tm tm; - tm.tm_year = static_cast<int>(cs.year() - year_t{1900}); - tm.tm_mon = cs.month() - 1; - tm.tm_mday = cs.day(); - tm.tm_hour = cs.hour(); - tm.tm_min = cs.minute(); - tm.tm_sec = cs.second(); - tm.tm_isdst = is_dst; - *t = std::mktime(&tm); - if (*t == std::time_t{-1}) { - std::tm tm2; - const std::tm* tmp = local_time(t, &tm2); - if (tmp == nullptr || tmp->tm_year != tm.tm_year || - tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday || - tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min || - tmp->tm_sec != tm.tm_sec) { - // A true error (not just one second before the epoch). - return false; - } - } - *off = static_cast<int>(tm_gmtoff(tm)); - return true; -} - -// Find the least time_t in [lo:hi] where local time matches offset, given: -// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. -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 (tm_gmtoff(*tmp) == offset) { - hi = mid; - } else { - lo = mid; - } - } else { - // 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 (tm_gmtoff(*tmp) == offset) break; - } - } - return lo; - } - } - return hi; -} - -} // namespace - -TimeZoneLibC::TimeZoneLibC(const std::string& name) - : local_(name == "localtime") {} - -time_zone::absolute_lookup TimeZoneLibC::BreakTime( - const time_point<seconds>& tp) const { - time_zone::absolute_lookup al; - al.offset = 0; - al.is_dst = false; - al.abbr = "-00"; - - const std::int_fast64_t s = ToUnixSeconds(tp); - - // If std::time_t cannot hold the input we saturate the output. - if (s < std::numeric_limits<std::time_t>::min()) { - al.cs = civil_second::min(); - return al; - } - if (s > std::numeric_limits<std::time_t>::max()) { - al.cs = civil_second::max(); - return al; - } - - const std::time_t t = static_cast<std::time_t>(s); - std::tm tm; - std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); - - // If std::tm cannot hold the result we saturate the output. - if (tmp == nullptr) { - al.cs = (s < 0) ? civil_second::min() : civil_second::max(); - return al; - } - - const year_t year = tmp->tm_year + year_t{1900}; - al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, - tmp->tm_min, tmp->tm_sec); - al.offset = static_cast<int>(tm_gmtoff(*tmp)); - al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz - al.is_dst = tmp->tm_isdst > 0; - return al; -} - -time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { - if (!local_) { - // If time_point<seconds> cannot hold the result we saturate. - static const civil_second min_tp_cs = - 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()); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - - // If tm_year cannot hold the requested year we saturate the result. - if (cs.year() < 0) { - if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) { - const time_point<seconds> tp = time_point<seconds>::min(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - } else { - if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) { - const time_point<seconds> tp = time_point<seconds>::max(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - } - - // We probe with "is_dst" values of 0 and 1 to try to distinguish unique - // civil seconds from skipped or repeated ones. This is not always possible - // however, as the "dst" flag does not change over some offset transitions. - // We are also subject to the vagaries of mktime() implementations. - std::time_t t0, t1; - int offset0, offset1; - if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) { - if (t0 == t1) { - // The civil time was singular (pre == trans == post). - const time_point<seconds> tp = FromUnixSeconds(t0); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - - if (t0 > t1) { - std::swap(t0, t1); - std::swap(offset0, offset1); - } - const std::time_t tt = find_trans(t0, t1, offset1); - const time_point<seconds> trans = FromUnixSeconds(tt); - - if (offset0 < offset1) { - // The civil time did not exist (pre >= trans > post). - const time_point<seconds> pre = FromUnixSeconds(t1); - const time_point<seconds> post = FromUnixSeconds(t0); - return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; - } - - // The civil time was ambiguous (pre < trans <= post). - const time_point<seconds> pre = FromUnixSeconds(t0); - const time_point<seconds> post = FromUnixSeconds(t1); - return {time_zone::civil_lookup::REPEATED, pre, trans, post}; - } - - // make_time() failed somehow so we saturate the result. - const time_point<seconds> tp = (cs < civil_second()) - ? time_point<seconds>::min() - : time_point<seconds>::max(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; -} - -bool TimeZoneLibC::NextTransition(const time_point<seconds>&, - time_zone::civil_transition*) const { - return false; -} - -bool TimeZoneLibC::PrevTransition(const time_point<seconds>&, - time_zone::civil_transition*) const { - return false; -} - -std::string TimeZoneLibC::Version() const { - return std::string(); // unknown -} - -std::string TimeZoneLibC::Description() const { - return local_ ? "localtime" : "UTC"; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_libc.h b/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_libc.h deleted file mode 100644 index 1da9039a15ee..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_libc.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ - -#include <string> - -#include "absl/base/config.h" -#include "time_zone_if.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3), -// and which therefore only supports UTC and the local time zone. -// TODO: Add support for fixed offsets from UTC. -class TimeZoneLibC : public TimeZoneIf { - public: - explicit TimeZoneLibC(const std::string& name); - - // TimeZoneIf implementations. - time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const override; - time_zone::civil_lookup MakeTime(const civil_second& cs) const override; - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - std::string Version() const override; - std::string Description() const override; - - private: - const bool local_; // localtime or UTC -}; - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ 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 deleted file mode 100644 index efdea64b4eb1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_lookup.cc +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -#if defined(__ANDROID__) -#include <sys/system_properties.h> -#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 -#include <dlfcn.h> -#endif -#endif - -#if defined(__APPLE__) -#include <CoreFoundation/CFTimeZone.h> - -#include <vector> -#endif - -#include <cstdlib> -#include <cstring> -#include <string> - -#include "time_zone_fixed.h" -#include "time_zone_impl.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21 -namespace { -// Android 'L' removes __system_property_get() from the NDK, however -// it is still a hidden symbol in libc so we use dlsym() to access it. -// See Chromium's base/sys_info_android.cc for a similar example. - -using property_get_func = int (*)(const char*, char*); - -property_get_func LoadSystemPropertyGet() { - int flag = RTLD_LAZY | RTLD_GLOBAL; -#if defined(RTLD_NOLOAD) - flag |= RTLD_NOLOAD; // libc.so should already be resident -#endif - if (void* handle = dlopen("libc.so", flag)) { - void* sym = dlsym(handle, "__system_property_get"); - dlclose(handle); - return reinterpret_cast<property_get_func>(sym); - } - return nullptr; -} - -int __system_property_get(const char* name, char* value) { - static property_get_func system_property_get = LoadSystemPropertyGet(); - return system_property_get ? system_property_get(name, value) : -1; -} - -} // namespace -#endif - -std::string time_zone::name() const { return effective_impl().Name(); } - -time_zone::absolute_lookup time_zone::lookup( - const time_point<seconds>& tp) const { - return effective_impl().BreakTime(tp); -} - -time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { - return effective_impl().MakeTime(cs); -} - -bool time_zone::next_transition(const time_point<seconds>& tp, - civil_transition* trans) const { - return effective_impl().NextTransition(tp, trans); -} - -bool time_zone::prev_transition(const time_point<seconds>& tp, - civil_transition* trans) const { - return effective_impl().PrevTransition(tp, trans); -} - -std::string time_zone::version() const { return effective_impl().Version(); } - -std::string time_zone::description() const { - return effective_impl().Description(); -} - -const time_zone::Impl& time_zone::effective_impl() const { - if (impl_ == nullptr) { - // Dereferencing an implicit-UTC time_zone is expected to be - // rare, so we don't mind paying a small synchronization cost. - return *time_zone::Impl::UTC().impl_; - } - return *impl_; -} - -bool load_time_zone(const std::string& name, time_zone* tz) { - return time_zone::Impl::LoadTimeZone(name, tz); -} - -time_zone utc_time_zone() { - return time_zone::Impl::UTC(); // avoid name lookup -} - -time_zone fixed_time_zone(const seconds& offset) { - time_zone tz; - load_time_zone(FixedOffsetToName(offset), &tz); - return tz; -} - -time_zone local_time_zone() { - const char* zone = ":localtime"; -#if defined(__ANDROID__) - char sysprop[PROP_VALUE_MAX]; - if (__system_property_get("persist.sys.timezone", sysprop) > 0) { - zone = sysprop; - } -#endif -#if defined(__APPLE__) - std::vector<char> buffer; - CFTimeZoneRef tz_default = CFTimeZoneCopyDefault(); - if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) { - CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex length = CFStringGetLength(tz_name); - buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1); - if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) { - zone = &buffer[0]; - } - } - CFRelease(tz_default); -#endif - - // Allow ${TZ} to override to default zone. - char* tz_env = nullptr; -#if defined(_MSC_VER) - _dupenv_s(&tz_env, nullptr, "TZ"); -#else - tz_env = std::getenv("TZ"); -#endif - if (tz_env) zone = tz_env; - - // We only support the "[:]<zone-name>" form. - if (*zone == ':') ++zone; - - // Map "localtime" to a system-specific name, but - // allow ${LOCALTIME} to override the default name. - char* localtime_env = nullptr; - if (strcmp(zone, "localtime") == 0) { -#if defined(_MSC_VER) - // System-specific default is just "localtime". - _dupenv_s(&localtime_env, nullptr, "LOCALTIME"); -#else - zone = "/etc/localtime"; // System-specific default. - localtime_env = std::getenv("LOCALTIME"); -#endif - if (localtime_env) zone = localtime_env; - } - - const std::string name = zone; -#if defined(_MSC_VER) - free(localtime_env); - free(tz_env); -#endif - - time_zone tz; - load_time_zone(name, &tz); // Falls back to UTC. - // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and - // arrange for %z to generate "-0000" when we don't know the local - // offset because the load_time_zone() failed and we're using UTC. - return tz; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl 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 deleted file mode 100644 index 9a1a8d6e400c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ /dev/null @@ -1,1442 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <chrono> -#include <cstddef> -#include <cstdlib> -#include <future> -#include <limits> -#include <string> -#include <thread> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace chrono = std::chrono; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// A list of known time-zone names. -const char* const kTimeZoneNames[] = {"Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Nelson", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Nuuk", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Punta_Arenas", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Atyrau", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Barnaul", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Famagusta", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qostanay", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Tomsk", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yangon", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Astrakhan", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Kirov", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Saratov", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Ulyanovsk", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr}; - -// Helper to return a loaded time zone by value (UTC on error). -time_zone LoadZone(const std::string& name) { - time_zone tz; - load_time_zone(name, &tz); - return tz; -} - -// This helper is a macro so that failed expectations show up with the -// correct line numbers. -#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \ - do { \ - time_zone::absolute_lookup al = tz.lookup(tp); \ - EXPECT_EQ(y, al.cs.year()); \ - EXPECT_EQ(m, al.cs.month()); \ - EXPECT_EQ(d, al.cs.day()); \ - EXPECT_EQ(hh, al.cs.hour()); \ - EXPECT_EQ(mm, al.cs.minute()); \ - EXPECT_EQ(ss, al.cs.second()); \ - EXPECT_EQ(off, al.offset); \ - EXPECT_TRUE(isdst == al.is_dst); \ - /* EXPECT_STREQ(zone, al.abbr); */ \ - } while (0) - -// These tests sometimes run on platforms that have zoneinfo data so old -// that the transition we are attempting to check does not exist, most -// notably Android emulators. Fortunately, AndroidZoneInfoSource supports -// time_zone::version() so, in cases where we've learned that it matters, -// we can make the check conditionally. -int VersionCmp(time_zone tz, const std::string& target) { - std::string version = tz.version(); - if (version.empty() && !target.empty()) return 1; // unknown > known - return version.compare(target); -} - -} // namespace - -#if !defined(__EMSCRIPTEN__) -TEST(TimeZones, LoadZonesConcurrently) { - std::promise<void> ready_promise; - std::shared_future<void> ready_future(ready_promise.get_future()); - auto load_zones = [ready_future](std::promise<void>* started, - std::set<std::string>* failures) { - started->set_value(); - ready_future.wait(); - for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { - std::string zone = *np; - time_zone tz; - if (load_time_zone(zone, &tz)) { - EXPECT_EQ(zone, tz.name()); - } else { - failures->insert(zone); - } - } - }; - - const std::size_t n_threads = 128; - std::vector<std::thread> threads; - std::vector<std::set<std::string>> thread_failures(n_threads); - for (std::size_t i = 0; i != n_threads; ++i) { - std::promise<void> started; - threads.emplace_back(load_zones, &started, &thread_failures[i]); - started.get_future().wait(); - } - ready_promise.set_value(); - for (auto& thread : threads) { - thread.join(); - } - - // Allow a small number of failures to account for skew between - // the contents of kTimeZoneNames and the zoneinfo data source. -#if defined(__ANDROID__) - // Cater to the possibility of using an even older zoneinfo data - // source when running on Android, where it is difficult to override - // the bionic tzdata provided by the test environment. - const std::size_t max_failures = 20; -#else - const std::size_t max_failures = 3; -#endif - std::set<std::string> failures; - for (const auto& thread_failure : thread_failures) { - failures.insert(thread_failure.begin(), thread_failure.end()); - } - EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures); -} -#endif - -TEST(TimeZone, NamedTimeZones) { - const time_zone utc = utc_time_zone(); - EXPECT_EQ("UTC", utc.name()); - const time_zone nyc = LoadZone("America/New_York"); - EXPECT_EQ("America/New_York", nyc.name()); - const time_zone syd = LoadZone("Australia/Sydney"); - EXPECT_EQ("Australia/Sydney", syd.name()); - const time_zone fixed0 = - fixed_time_zone(absl::time_internal::cctz::seconds::zero()); - EXPECT_EQ("UTC", fixed0.name()); - const time_zone fixed_pos = fixed_time_zone( - chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); - EXPECT_EQ("Fixed/UTC+03:25:45", fixed_pos.name()); - const time_zone fixed_neg = fixed_time_zone( - -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); - EXPECT_EQ("Fixed/UTC-12:34:56", fixed_neg.name()); -} - -TEST(TimeZone, Failures) { - time_zone tz; - EXPECT_FALSE(load_time_zone(":America/Los_Angeles", &tz)); - - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); - EXPECT_EQ(chrono::system_clock::from_time_t(0), - convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC - - // Ensures that the load still fails on a subsequent attempt. - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); - 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. - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(load_time_zone("", &tz)); - EXPECT_EQ(chrono::system_clock::from_time_t(0), - convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC -} - -TEST(TimeZone, Equality) { - const time_zone a; - const time_zone b; - EXPECT_EQ(a, b); - EXPECT_EQ(a.name(), b.name()); - - const time_zone implicit_utc; - const time_zone explicit_utc = utc_time_zone(); - EXPECT_EQ(implicit_utc, explicit_utc); - EXPECT_EQ(implicit_utc.name(), explicit_utc.name()); - - const time_zone fixed_zero = - fixed_time_zone(absl::time_internal::cctz::seconds::zero()); - EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name())); - EXPECT_EQ(fixed_zero, explicit_utc); - - const time_zone fixed_utc = LoadZone("Fixed/UTC+00:00:00"); - EXPECT_EQ(fixed_utc, LoadZone(fixed_utc.name())); - EXPECT_EQ(fixed_utc, explicit_utc); - - const time_zone fixed_pos = fixed_time_zone( - chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); - EXPECT_EQ(fixed_pos, LoadZone(fixed_pos.name())); - EXPECT_NE(fixed_pos, explicit_utc); - const time_zone fixed_neg = fixed_time_zone( - -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); - EXPECT_EQ(fixed_neg, LoadZone(fixed_neg.name())); - EXPECT_NE(fixed_neg, explicit_utc); - - const time_zone fixed_lim = fixed_time_zone(chrono::hours(24)); - EXPECT_EQ(fixed_lim, LoadZone(fixed_lim.name())); - EXPECT_NE(fixed_lim, explicit_utc); - const time_zone fixed_ovfl = - fixed_time_zone(chrono::hours(24) + chrono::seconds(1)); - EXPECT_EQ(fixed_ovfl, LoadZone(fixed_ovfl.name())); - EXPECT_EQ(fixed_ovfl, explicit_utc); - - EXPECT_EQ(fixed_time_zone(chrono::seconds(1)), - fixed_time_zone(chrono::seconds(1))); - - const time_zone local = local_time_zone(); - EXPECT_EQ(local, LoadZone(local.name())); - - time_zone la = LoadZone("America/Los_Angeles"); - time_zone nyc = LoadZone("America/New_York"); - EXPECT_NE(la, nyc); -} - -TEST(StdChronoTimePoint, TimeTAlignment) { - // Ensures that the Unix epoch and the system clock epoch are an integral - // number of seconds apart. This simplifies conversions to/from time_t. - auto diff = - chrono::system_clock::time_point() - chrono::system_clock::from_time_t(0); - EXPECT_EQ(chrono::system_clock::time_point::duration::zero(), - diff % chrono::seconds(1)); -} - -TEST(BreakTime, TimePointResolution) { - const time_zone utc = utc_time_zone(); - const auto t0 = chrono::system_clock::from_time_t(0); - - ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc, 1970, 1, 1, - 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc, 1970, 1, 1, - 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc, 1970, 1, 1, - 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc, 1970, 1, 1, 0, - 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), - utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc, 1970, 1, 1, 0, - 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc, 1970, 1, 1, 0, 0, - 0, 0, false, "UTC"); -} - -TEST(BreakTime, LocalTimeInUTC) { - const time_zone tz = utc_time_zone(); - const auto tp = chrono::system_clock::from_time_t(0); - ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); -} - -TEST(BreakTime, LocalTimeInUTCUnaligned) { - const time_zone tz = utc_time_zone(); - const auto tp = - chrono::system_clock::from_time_t(0) - chrono::milliseconds(500); - ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC"); - EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); -} - -TEST(BreakTime, LocalTimePosix) { - // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch. - const time_zone tz = utc_time_zone(); - const auto tp = chrono::system_clock::from_time_t(536457599); - ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC"); - EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); -} - -TEST(TimeZoneImpl, LocalTimeInFixed) { - const absl::time_internal::cctz::seconds offset = - -(chrono::hours(8) + chrono::minutes(33) + chrono::seconds(47)); - const time_zone tz = fixed_time_zone(offset); - const auto tp = chrono::system_clock::from_time_t(0); - ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false, - "-083347"); - EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); -} - -TEST(BreakTime, LocalTimeInNewYork) { - const time_zone tz = LoadZone("America/New_York"); - const auto tp = chrono::system_clock::from_time_t(45); - ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST"); - EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); -} - -TEST(BreakTime, LocalTimeInMTV) { - const time_zone tz = LoadZone("America/Los_Angeles"); - const auto tp = chrono::system_clock::from_time_t(1380855729); - ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT"); - EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); -} - -TEST(BreakTime, LocalTimeInSydney) { - const time_zone tz = LoadZone("Australia/Sydney"); - const auto tp = chrono::system_clock::from_time_t(90); - ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST"); - EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); -} - -TEST(MakeTime, TimePointResolution) { - const time_zone utc = utc_time_zone(); - const time_point<chrono::nanoseconds> tp_ns = - convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ns, utc)); - const time_point<chrono::microseconds> tp_us = - convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_us, utc)); - const time_point<chrono::milliseconds> tp_ms = - convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ms, utc)); - const time_point<chrono::seconds> tp_s = - convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s, utc)); - const time_point<absl::time_internal::cctz::seconds> tp_s64 = - convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s64, utc)); - - // These next two require chrono::time_point_cast because the conversion - // from a resolution of seconds (the return value of convert()) to a - // coarser resolution requires an explicit cast. - const time_point<chrono::minutes> tp_m = - chrono::time_point_cast<chrono::minutes>( - convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc)); - const time_point<chrono::hours> tp_h = chrono::time_point_cast<chrono::hours>( - convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc)); -} - -TEST(MakeTime, Normalization) { - const time_zone tz = LoadZone("America/New_York"); - const auto tp = convert(civil_second(2009, 2, 13, 18, 31, 30), tz); - EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); - - // Now requests for the same time_point but with out-of-range fields. - EXPECT_EQ(tp, convert(civil_second(2008, 14, 13, 18, 31, 30), tz)); // month - EXPECT_EQ(tp, convert(civil_second(2009, 1, 44, 18, 31, 30), tz)); // day - EXPECT_EQ(tp, convert(civil_second(2009, 2, 12, 42, 31, 30), tz)); // hour - EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 17, 91, 30), tz)); // minute - EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz)); // second -} - -// NOTE: Run this with -ftrapv to detect overflow problems. -TEST(MakeTime, SysSecondsLimits) { - const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; - const time_zone utc = utc_time_zone(); - const time_zone east = fixed_time_zone(chrono::hours(14)); - const time_zone west = fixed_time_zone(-chrono::hours(14)); - time_point<absl::time_internal::cctz::seconds> tp; - - // Approach the maximal time_point<cctz::seconds> value from below. - tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc); - EXPECT_EQ("292277026596-12-04T15:30:06+00:00", format(RFC3339, tp, utc)); - tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc); - EXPECT_EQ("292277026596-12-04T15:30:07+00:00", format(RFC3339, tp, utc)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second::max(), utc); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - - // Checks that we can also get the maximal value for a far-east zone. - tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east); - EXPECT_EQ("292277026596-12-05T05:30:07+14:00", format(RFC3339, tp, east)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second::max(), east); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - - // Checks that we can also get the maximal value for a far-west zone. - tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west); - EXPECT_EQ("292277026596-12-04T01:30:07-14:00", format(RFC3339, tp, west)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - tp = convert(civil_second::max(), west); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); - - // Approach the minimal time_point<cctz::seconds> value from above. - tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc); - EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", format(RFC3339, tp, utc)); - tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc); - EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", format(RFC3339, tp, utc)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second::min(), utc); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - - // Checks that we can also get the minimal value for a far-east zone. - tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east); - EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", format(RFC3339, tp, east)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second::min(), east); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - - // Checks that we can also get the minimal value for a far-west zone. - tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west); - EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", format(RFC3339, tp, west)); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - tp = convert(civil_second::min(), west); - EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); - - // Some similar checks for the "libc" time-zone implementation. - if (sizeof(std::time_t) >= 8) { - // Checks that "tm_year + 1900", as used by the "libc" implementation, - // can produce year values beyond the range on an int without overflow. -#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 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 - 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); - EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut)); -#endif - } -} - -TEST(MakeTime, LocalTimeLibC) { - // Checks that cctz and libc agree on transition points in [1970:2037]. - // - // We limit this test case to environments where: - // 1) we know how to change the time zone used by localtime()/mktime(), - // 2) cctz and localtime()/mktime() will use similar-enough tzdata, and - // 3) we have some idea about how mktime() behaves during transitions. -#if defined(__linux__) && !defined(__ANDROID__) - const char* const ep = getenv("TZ"); - std::string tz_name = (ep != nullptr) ? ep : ""; - for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { - ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means - const auto zi = local_time_zone(); - const auto lc = LoadZone("libc:localtime"); - time_zone::civil_transition transition; - for (auto tp = zi.lookup(civil_second()).trans; - zi.next_transition(tp, &transition); - tp = zi.lookup(transition.to).trans) { - const auto fcl = zi.lookup(transition.from); - const auto tcl = zi.lookup(transition.to); - civil_second cs; // compare cs in zi and lc - if (fcl.kind == time_zone::civil_lookup::UNIQUE) { - if (tcl.kind == time_zone::civil_lookup::UNIQUE) { - // Both unique; must be an is_dst or abbr change. - ASSERT_EQ(transition.from, transition.to); - const auto trans = fcl.trans; - const auto tal = zi.lookup(trans); - const auto tprev = trans - absl::time_internal::cctz::seconds(1); - const auto pal = zi.lookup(tprev); - if (pal.is_dst == tal.is_dst) { - ASSERT_STRNE(pal.abbr, tal.abbr); - } - continue; - } - ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind); - cs = transition.to; - } else { - ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind); - ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind); - cs = transition.from; - } - if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t) - const auto cl_zi = zi.lookup(cs); - if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) { - // The "libc" implementation cannot correctly classify transitions - // that don't change the "tm_isdst" flag. In Europe/Volgograd, for - // example, there is a SKIPPED transition from +03 to +04 with dst=F - // on both sides ... - // 1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800] - // 1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400] - // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike, - // say, the similar Europe/Chisinau transition from +02 to +03 ... - // 1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200] - // 1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800] - // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and - // returns 1521936000. - continue; - } - if (cs == civil_second(2037, 10, 4, 2, 0, 0)) { - const std::string tzname = *np; - if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") { - // The "libc" implementation gets this transition wrong (at least - // until 2018g when it was removed), returning an offset of 3600 - // instead of 0. TODO: Revert this when 2018g is ubiquitous. - continue; - } - } - const auto cl_lc = lc.lookup(cs); - SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np); - EXPECT_EQ(cl_zi.kind, cl_lc.kind); - EXPECT_EQ(cl_zi.pre, cl_lc.pre); - EXPECT_EQ(cl_zi.trans, cl_lc.trans); - EXPECT_EQ(cl_zi.post, cl_lc.post); - } - } - if (ep == nullptr) { - ASSERT_EQ(0, unsetenv("TZ")); - } else { - ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1)); - } -#endif -} - -TEST(NextTransition, UTC) { - const auto tz = utc_time_zone(); - time_zone::civil_transition trans; - - auto tp = time_point<absl::time_internal::cctz::seconds>::min(); - EXPECT_FALSE(tz.next_transition(tp, &trans)); - - tp = time_point<absl::time_internal::cctz::seconds>::max(); - EXPECT_FALSE(tz.next_transition(tp, &trans)); -} - -TEST(PrevTransition, UTC) { - const auto tz = utc_time_zone(); - time_zone::civil_transition trans; - - auto tp = time_point<absl::time_internal::cctz::seconds>::max(); - EXPECT_FALSE(tz.prev_transition(tp, &trans)); - - tp = time_point<absl::time_internal::cctz::seconds>::min(); - EXPECT_FALSE(tz.prev_transition(tp, &trans)); -} - -TEST(NextTransition, AmericaNewYork) { - const auto tz = LoadZone("America/New_York"); - time_zone::civil_transition trans; - - auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); - EXPECT_TRUE(tz.next_transition(tp, &trans)); - EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from); - EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to); - - tp = time_point<absl::time_internal::cctz::seconds>::max(); - EXPECT_FALSE(tz.next_transition(tp, &trans)); - - tp = time_point<absl::time_internal::cctz::seconds>::min(); - EXPECT_TRUE(tz.next_transition(tp, &trans)); - if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) { - // It looks like the tzdata is only 32 bit (probably macOS), - // which bottoms out at 1901-12-13T20:45:52+00:00. - EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to); - } else { - EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from); - EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to); - } -} - -TEST(PrevTransition, AmericaNewYork) { - const auto tz = LoadZone("America/New_York"); - time_zone::civil_transition trans; - - auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); - EXPECT_TRUE(tz.prev_transition(tp, &trans)); - EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from); - EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to); - - tp = time_point<absl::time_internal::cctz::seconds>::min(); - EXPECT_FALSE(tz.prev_transition(tp, &trans)); - - tp = time_point<absl::time_internal::cctz::seconds>::max(); - EXPECT_TRUE(tz.prev_transition(tp, &trans)); - // We have a transition but we don't know which one. -} - -TEST(TimeZoneEdgeCase, AmericaNewYork) { - const time_zone tz = LoadZone("America/New_York"); - - // Spring 1:59:59 -> 3:00:00 - auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, "EST"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, "EDT"); - - // Fall 1:59:59 -> 1:00:00 - tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, "EST"); -} - -TEST(TimeZoneEdgeCase, AmericaLosAngeles) { - const time_zone tz = LoadZone("America/Los_Angeles"); - - // Spring 1:59:59 -> 3:00:00 - auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, "PST"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, "PDT"); - - // Fall 1:59:59 -> 1:00:00 - tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, "PDT"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, "PST"); -} - -TEST(TimeZoneEdgeCase, ArizonaNoTransition) { - const time_zone tz = LoadZone("America/Phoenix"); - - // No transition in Spring. - auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, "MST"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, "MST"); - - // No transition in Fall. - tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, "MST"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, "MST"); -} - -TEST(TimeZoneEdgeCase, AsiaKathmandu) { - const time_zone tz = LoadZone("Asia/Kathmandu"); - - // A non-DST offset change from +0530 to +0545 - // - // 504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (+0530) - // 504901800 == Wed, 1 Jan 1986 00:15:00 +0545 (+0545) - auto tp = convert(civil_second(1985, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "+0530"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "+0545"); -} - -TEST(TimeZoneEdgeCase, PacificChatham) { - const time_zone tz = LoadZone("Pacific/Chatham"); - - // One-hour DST offset changes, but at atypical values - // - // 1365256799 == Sun, 7 Apr 2013 03:44:59 +1345 (+1345) - // 1365256800 == Sun, 7 Apr 2013 02:45:00 +1245 (+1245) - auto tp = convert(civil_second(2013, 4, 7, 3, 44, 59), tz); - ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "+1345"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "+1245"); - - // 1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (+1245) - // 1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (+1345) - tp = convert(civil_second(2013, 9, 29, 2, 44, 59), tz); - ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, "+1245"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "+1345"); -} - -TEST(TimeZoneEdgeCase, AustraliaLordHowe) { - const time_zone tz = LoadZone("Australia/Lord_Howe"); - - // Half-hour DST offset changes - // - // 1365260399 == Sun, 7 Apr 2013 01:59:59 +1100 (+11) - // 1365260400 == Sun, 7 Apr 2013 01:30:00 +1030 (+1030) - auto tp = convert(civil_second(2013, 4, 7, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "+11"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "+1030"); - - // 1380986999 == Sun, 6 Oct 2013 01:59:59 +1030 (+1030) - // 1380987000 == Sun, 6 Oct 2013 02:30:00 +1100 (+11) - tp = convert(civil_second(2013, 10, 6, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "+1030"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "+11"); -} - -TEST(TimeZoneEdgeCase, PacificApia) { - const time_zone tz = LoadZone("Pacific/Apia"); - - // At the end of December 2011, Samoa jumped forward by one day, - // skipping 30 December from the local calendar, when the nation - // moved to the west of the International Date Line. - // - // A one-day, non-DST offset change - // - // 1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (-10) - // 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14) - auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz); - ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10"); - EXPECT_EQ(363, get_yearday(convert(tp, tz))); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14"); - EXPECT_EQ(365, get_yearday(convert(tp, tz))); -} - -TEST(TimeZoneEdgeCase, AfricaCairo) { - const time_zone tz = LoadZone("Africa/Cairo"); - - if (VersionCmp(tz, "2014c") >= 0) { - // An interesting case of midnight not existing. - // - // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) - // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) - auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); - ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); - } -} - -TEST(TimeZoneEdgeCase, AfricaMonrovia) { - const time_zone tz = LoadZone("Africa/Monrovia"); - - if (VersionCmp(tz, "2017b") >= 0) { - // Strange offset change -00:44:30 -> +00:00:00 (non-DST) - // - // 63593069 == Thu, 6 Jan 1972 23:59:59 -0044 (MMT) - // 63593070 == Fri, 7 Jan 1972 00:44:30 +0000 (GMT) - auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz); - ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT"); - } -} - -TEST(TimeZoneEdgeCase, AmericaJamaica) { - // Jamaica discontinued DST transitions in 1983, and is now at a - // constant -0500. This makes it an interesting edge-case target. - // Note that the 32-bit times used in a (tzh_version == 0) zoneinfo - // file cannot represent the abbreviation-only transition of 1890, - // so we ignore the abbreviation by expecting what we received. - const time_zone tz = LoadZone("America/Jamaica"); - - // Before the first transition. - if (!tz.version().empty() && VersionCmp(tz, "2018d") >= 0) { - // We avoid the expectations on the -18430 offset below unless we are - // certain we have commit 907241e (Fix off-by-1 error for Jamaica and - // T&C before 1913) from 2018d. TODO: Remove the "version() not empty" - // part when 2018d is generally available from /usr/share/zoneinfo. - auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); - ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false, - tz.lookup(tp).abbr); - - // Over the first (abbreviation-change only) transition. - // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) - // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) - tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false, - tz.lookup(tp).abbr); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT"); - } - - // Over the last (DST) transition. - // 436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT) - // 436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST) - auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); - ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST"); - - // After the last transition. - tp = convert(civil_second(1983, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST"); -} - -TEST(TimeZoneEdgeCase, WET) { - // Cover some non-existent times within forward transitions. - const time_zone tz = LoadZone("WET"); - - // Before the first transition. - auto tp = convert(civil_second(1977, 1, 1, 0, 0, 0), tz); - ExpectTime(tp, tz, 1977, 1, 1, 0, 0, 0, 0, false, "WET"); - - // Over the first transition. - // 228877199 == Sun, 3 Apr 1977 00:59:59 +0000 (WET) - // 228877200 == Sun, 3 Apr 1977 02:00:00 +0100 (WEST) - tp = convert(civil_second(1977, 4, 3, 0, 59, 59), tz); - ExpectTime(tp, tz, 1977, 4, 3, 0, 59, 59, 0, false, "WET"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - - // A non-existent time within the first transition. - time_zone::civil_lookup cl1 = tz.lookup(civil_second(1977, 4, 3, 1, 15, 0)); - EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind); - ExpectTime(cl1.pre, tz, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl1.trans, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl1.post, tz, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET"); - - // A non-existent time within the second forward transition. - time_zone::civil_lookup cl2 = tz.lookup(civil_second(1978, 4, 2, 1, 15, 0)); - EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl2.kind); - ExpectTime(cl2.pre, tz, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl2.trans, tz, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl2.post, tz, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET"); -} - -TEST(TimeZoneEdgeCase, FixedOffsets) { - const time_zone gmtm5 = LoadZone("Etc/GMT+5"); // -0500 - auto tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtm5); - ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "-05"); - EXPECT_EQ(chrono::system_clock::from_time_t(5 * 3600), tp); - - const time_zone gmtp5 = LoadZone("Etc/GMT-5"); // +0500 - tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtp5); - ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "+05"); - EXPECT_EQ(chrono::system_clock::from_time_t(-5 * 3600), tp); -} - -TEST(TimeZoneEdgeCase, NegativeYear) { - // Tests transition from year 0 (aka 1BCE) to year -1. - const time_zone tz = utc_time_zone(); - auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz); - ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); - EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz))); - tp -= absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz))); -} - -TEST(TimeZoneEdgeCase, UTC32bitLimit) { - const time_zone tz = utc_time_zone(); - - // Limits of signed 32-bit time_t - // - // 2147483647 == Tue, 19 Jan 2038 03:14:07 +0000 (UTC) - // 2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC) - auto tp = convert(civil_second(2038, 1, 19, 3, 14, 7), tz); - ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, "UTC"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, "UTC"); -} - -TEST(TimeZoneEdgeCase, UTC5DigitYear) { - const time_zone tz = utc_time_zone(); - - // Rollover to 5-digit year - // - // 253402300799 == Fri, 31 Dec 9999 23:59:59 +0000 (UTC) - // 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC) - auto tp = convert(civil_second(9999, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.cc b/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.cc deleted file mode 100644 index 5cdd09e89d0e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.cc +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_posix.h" - -#include <cstddef> -#include <cstring> -#include <limits> -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -const char kDigits[] = "0123456789"; - -const char* ParseInt(const char* p, int min, int max, int* vp) { - int value = 0; - const char* op = p; - const int kMaxInt = std::numeric_limits<int>::max(); - for (; const char* dp = strchr(kDigits, *p); ++p) { - int d = static_cast<int>(dp - kDigits); - if (d >= 10) break; // '\0' - if (value > kMaxInt / 10) return nullptr; - value *= 10; - if (value > kMaxInt - d) return nullptr; - value += d; - } - if (p == op || value < min || value > max) return nullptr; - *vp = value; - return p; -} - -// abbr = <.*?> | [^-+,\d]{3,} -const char* ParseAbbr(const char* p, std::string* abbr) { - const char* op = p; - if (*p == '<') { // special zoneinfo <...> form - while (*++p != '>') { - if (*p == '\0') return nullptr; - } - abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1); - return ++p; - } - while (*p != '\0') { - if (strchr("-+,", *p)) break; - if (strchr(kDigits, *p)) break; - ++p; - } - if (p - op < 3) return nullptr; - abbr->assign(op, static_cast<std::size_t>(p - op)); - return p; -} - -// offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value) -const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign, - std::int_fast32_t* offset) { - if (p == nullptr) return nullptr; - if (*p == '+' || *p == '-') { - if (*p++ == '-') sign = -sign; - } - int hours = 0; - int minutes = 0; - int seconds = 0; - - p = ParseInt(p, min_hour, max_hour, &hours); - if (p == nullptr) return nullptr; - if (*p == ':') { - p = ParseInt(p + 1, 0, 59, &minutes); - if (p == nullptr) return nullptr; - if (*p == ':') { - p = ParseInt(p + 1, 0, 59, &seconds); - if (p == nullptr) return nullptr; - } - } - *offset = sign * ((((hours * 60) + minutes) * 60) + seconds); - return p; -} - -// datetime = ( Jn | n | Mm.w.d ) [ / offset ] -const char* ParseDateTime(const char* p, PosixTransition* res) { - if (p != nullptr && *p == ',') { - if (*++p == 'M') { - int month = 0; - if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr && *p == '.') { - int week = 0; - if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr && *p == '.') { - int weekday = 0; - if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) { - res->date.fmt = PosixTransition::M; - res->date.m.month = static_cast<std::int_fast8_t>(month); - res->date.m.week = static_cast<std::int_fast8_t>(week); - res->date.m.weekday = static_cast<std::int_fast8_t>(weekday); - } - } - } - } else if (*p == 'J') { - int day = 0; - if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) { - res->date.fmt = PosixTransition::J; - res->date.j.day = static_cast<std::int_fast16_t>(day); - } - } else { - int day = 0; - if ((p = ParseInt(p, 0, 365, &day)) != nullptr) { - res->date.fmt = PosixTransition::N; - res->date.n.day = static_cast<std::int_fast16_t>(day); - } - } - } - if (p != nullptr) { - res->time.offset = 2 * 60 * 60; // default offset is 02:00:00 - if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset); - } - return p; -} - -} // namespace - -// spec = std offset [ dst [ offset ] , datetime , datetime ] -bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) { - const char* p = spec.c_str(); - if (*p == ':') return false; - - p = ParseAbbr(p, &res->std_abbr); - p = ParseOffset(p, 0, 24, -1, &res->std_offset); - if (p == nullptr) return false; - if (*p == '\0') return true; - - p = ParseAbbr(p, &res->dst_abbr); - if (p == nullptr) return false; - res->dst_offset = res->std_offset + (60 * 60); // default - if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset); - - p = ParseDateTime(p, &res->dst_start); - p = ParseDateTime(p, &res->dst_end); - - return p != nullptr && *p == '\0'; -} - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.h b/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.h deleted file mode 100644 index 0cf29055f56a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/time_zone_posix.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2016 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. - -// Parsing of a POSIX zone spec as described in the TZ part of section 8.3 in -// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html. -// -// The current POSIX spec for America/Los_Angeles is "PST8PDT,M3.2.0,M11.1.0", -// which would be broken down as ... -// -// PosixTimeZone { -// std_abbr = "PST" -// std_offset = -28800 -// dst_abbr = "PDT" -// dst_offset = -25200 -// dst_start = PosixTransition { -// date { -// m { -// month = 3 -// week = 2 -// weekday = 0 -// } -// } -// time { -// offset = 7200 -// } -// } -// dst_end = PosixTransition { -// date { -// m { -// month = 11 -// week = 1 -// weekday = 0 -// } -// } -// time { -// offset = 7200 -// } -// } -// } - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ - -#include <cstdint> -#include <string> - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// The date/time of the transition. The date is specified as either: -// (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or -// (N) the Nth day of the year (0 <= N <= 365), including leap days, or -// (M) the Nth weekday of a month (e.g., the 2nd Sunday in March). -// The time, specified as a day offset, identifies the particular moment -// of the transition, and may be negative or >= 24h, and in which case -// it would take us to another day, and perhaps week, or even month. -struct PosixTransition { - enum DateFormat { J, N, M }; - - struct Date { - struct NonLeapDay { - std::int_fast16_t day; // day of non-leap year [1:365] - }; - struct Day { - std::int_fast16_t day; // day of year [0:365] - }; - struct MonthWeekWeekday { - std::int_fast8_t month; // month of year [1:12] - std::int_fast8_t week; // week of month [1:5] (5==last) - std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat - }; - - DateFormat fmt; - - union { - NonLeapDay j; - Day n; - MonthWeekWeekday m; - }; - }; - - struct Time { - std::int_fast32_t offset; // seconds before/after 00:00:00 - }; - - Date date; - Time time; -}; - -// The entirety of a POSIX-string specified time-zone rule. The standard -// abbreviation and offset are always given. If the time zone includes -// daylight saving, then the daylight abbrevation is non-empty and the -// remaining fields are also valid. Note that the start/end transitions -// are not ordered---in the southern hemisphere the transition to end -// daylight time occurs first in any particular year. -struct PosixTimeZone { - std::string std_abbr; - std::int_fast32_t std_offset; - - std::string dst_abbr; - std::int_fast32_t dst_offset; - PosixTransition dst_start; - PosixTransition dst_end; -}; - -// Breaks down a POSIX time-zone specification into its constituent pieces, -// filling in any missing values (DST offset, or start/end transition times) -// with the standard-defined defaults. Returns false if the specification -// could not be parsed (although some fields of *res may have been altered). -bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res); - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/src/tzfile.h b/third_party/abseil_cpp/absl/time/internal/cctz/src/tzfile.h deleted file mode 100644 index 269fa36c537a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/tzfile.h +++ /dev/null @@ -1,122 +0,0 @@ -/* Layout and location of TZif files. */ - -#ifndef TZFILE_H - -#define TZFILE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** Information about time zone files. -*/ - -#ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "/etc/localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES -#define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ - -/* See Internet RFC 8536 for more details about the following format. */ - -/* -** Each file begins with. . . -*/ - -#define TZ_MAGIC "TZif" - -struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ - char tzh_reserved[15]; /* reserved; must be zero */ - char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded UT offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if 1, transition -** time is standard time, if 0, -** transition time is local (wall clock) -** time; if absent, transition times are -** assumed to be local time -** tzh_ttisutcnt (char)s indexed by type; if 1, transition -** time is UT, if 0, transition time is -** local time; if absent, transition -** times are assumed to be local time. -** When this is 1, the corresponding -** std/wall indicator must also be 1. -*/ - -/* -** If tzh_version is '2' or greater, the above is followed by a second instance -** of tzhead and a second instance of the data in which each coded transition -** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style 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 -** 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 -** standard time, indicating DST all year. -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -#ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 2000 -#endif /* !defined TZ_MAX_TIMES */ - -#ifndef TZ_MAX_TYPES -/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ - -#ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ - -#ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ - -#endif /* !defined TZFILE_H */ diff --git a/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 deleted file mode 100644 index 72095339c3c1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/src/zone_info_source.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/time/internal/cctz/include/cctz/zone_info_source.h" - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Defined out-of-line to avoid emitting a weak vtable in all TUs. -ZoneInfoSource::~ZoneInfoSource() {} -std::string ZoneInfoSource::Version() const { return std::string(); } - -} // namespace cctz -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz_extension { - -namespace { - -// A default for cctz_extension::zone_info_source_factory, which simply -// defers to the fallback factory. -std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory( - const std::string& name, - const std::function< - std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>( - const std::string& name)>& fallback_factory) { - return fallback_factory(name); -} - -} // namespace - -// A "weak" definition for cctz_extension::zone_info_source_factory. -// The user may override this with their own "strong" definition (see -// zone_info_source.h). -#if !defined(__has_attribute) -#define __has_attribute(x) 0 -#endif -// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the -// Windows linker cannot handle that. Nor does the MinGW compiler know how to -// pass "#pragma comment(linker, ...)" to the Windows linker. -#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) -ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) = - DefaultFactory; -#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) -extern ZoneInfoSourceFactory zone_info_source_factory; -extern ZoneInfoSourceFactory default_factory; -ZoneInfoSourceFactory default_factory = DefaultFactory; -#if defined(_M_IX86) -#pragma comment( \ - linker, \ - "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@@ZA") -#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM) || \ - defined(_M_ARM64) -#pragma comment( \ - linker, \ - "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ - "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ - "@@ZEA") -#else -#error Unsupported MSVC platform -#endif // _M_<PLATFORM> -#else -// Make it a "strong" definition if we have no other choice. -ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; -#endif - -} // namespace cctz_extension -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/README.zoneinfo b/third_party/abseil_cpp/absl/time/internal/cctz/testdata/README.zoneinfo deleted file mode 100644 index 95fb4a91d17e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/README.zoneinfo +++ /dev/null @@ -1,37 +0,0 @@ -testdata/zoneinfo contains time-zone data files that may be used with CCTZ. -Install them in a location referenced by the ${TZDIR} environment variable. -Symbolic and hard links have been eliminated for portability. - -On Linux systems the distribution's versions of these files can probably -already be found in the default ${TZDIR} location, /usr/share/zoneinfo. - -New versions can be generated using the following shell script. - - #!/bin/sh - - set -e - DESTDIR=$(mktemp -d) - trap "rm -fr ${DESTDIR}" 0 2 15 - ( - cd ${DESTDIR} - git clone https://github.com/eggert/tz.git - make --directory=tz \ - install DESTDIR=${DESTDIR} \ - DATAFORM=vanguard \ - TZDIR=/zoneinfo \ - REDO=posix_only \ - LOCALTIME=Factory \ - TZDATA_TEXT= \ - ZONETABLES=zone1970.tab - tar --create --dereference --hard-dereference --file tzfile.tar \ - --directory=tz tzfile.h - tar --create --dereference --hard-dereference --file zoneinfo.tar \ - --exclude=zoneinfo/posixrules zoneinfo \ - --directory=tz version - ) - tar --extract --directory src --file ${DESTDIR}/tzfile.tar - tar --extract --directory testdata --file ${DESTDIR}/zoneinfo.tar - exit 0 - -To run the CCTZ tests using the testdata/zoneinfo files, execute: - - bazel test --test_env=TZDIR=${PWD}/testdata/zoneinfo ... diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/version b/third_party/abseil_cpp/absl/time/internal/cctz/testdata/version deleted file mode 100644 index b4410dce16a3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/version +++ /dev/null @@ -1 +0,0 @@ -2020d 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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9ca907bf9bb1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 56a4dd2a19fa..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0da1d1e211bc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea38c970086c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0263c90bd0d8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a461dceaa2ad..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 772e23c4cd8b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bada0638f8a2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 36b05220ac00..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3f8e44b8a6e1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 651e5cf67a54..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bada0638f8a2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bada0638f8a2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 837780922f23..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ecbc0966dc2d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f2ce2f7728e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 425ad3fda7c5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e0c89971aabe..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ca324cb4cd26..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0edc52b9b783..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b1497bda631e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adak +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cdf0572be31d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f66c9f79d6cd..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6f999b8605c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1dcc8d85434c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1dcc8d85434c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 35a52e53d123..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b275f27c0287..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 23fca1220522..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 691c56978a03..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 991d1fae69ee..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 58863e0436d1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7eba33c1c5b1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0a81cbddfa28..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 10556d5d856a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e03175027692..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6ddf7d8f6bf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 622503674225..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c82871528308..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b1497bda631e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atka +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7969e3076687..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cbe22a7622d8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9d3afa6a53bd..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e0d7653c64c1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belem +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index de99b845019f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belize +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7096b69a564b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fca97207b283..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6cb53d4e6125..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 72fec9e8c52a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boise +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6f999b8605c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0a2225244a67..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6855e4e9fe02..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 640b259fd0f8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8dbe6ff74127..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1dcc8d85434c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cd49f0534438..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9154643f4c91..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b01688065392..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e1780a5750e3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c82871528308..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 35a52e53d123..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 08f0128ee681..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9d69a0ab819e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Creston +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c09a87558d53..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6ddf7d8f6bf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8718efcce25c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 07e4c5f4ac38..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 761d1d9af536..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 09e54e5c7c5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denver +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6eb3ac46ec56..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 645ee9453073..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7da4b98fe3c7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 43484117e285..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 19ccd3576d46..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2a49c6c50f4c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6b08d15bdaba..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 092e40d70122..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f85eb3415758..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4ddc99d8b74c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 820e0dd2cd7e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 062fcaed8e07..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8aa8e588e3cb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 381ae6c46326..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ebd85d0f3e02..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9fa850a7d4c3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e06629d36841..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havana +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8283239ecab2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6b08d15bdaba..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b187d5f8c756..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a730fe666b65..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 341a0235ef48..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 76e1f6285b55..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f2acf6cbbd65..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c255f89b6da9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8700ed9f065e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6b08d15bdaba..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index af3107db51e3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index eb2c99cca53a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index be6b1b6f1e77..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b275f27c0287..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e347b369f780..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f2136d6ed41b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d9f54a18bbe6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b187d5f8c756..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6ddf7d8f6bf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 68ddaae768e6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b643c5517f92..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lima +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index aaf07787ad92..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f2136d6ed41b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6ddf7d8f6bf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dbb8d57d91d6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 86ef76bf2241..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managua +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 59c952ebc651..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 25c0232d9549..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 722751b20e52..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4c819fab0247..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 691c56978a03..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 28d2c56e1a99..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3b0ca12c95f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Merida +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9fefee388e6f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ffcf8bee10e5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3b62585d0a13..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ecb69ef2c96a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dea9e3f5864f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4b2fb3e560f6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fe6be8ea8c97..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cf1e92dc0f53..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2b6c2eea14df..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_York +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b9f67a9f9495..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 23ead1c004ff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nome +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9e74745ca791..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index becf4383301e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d03bda045d31..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ecefc15d8cdf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem +++ /dev/null Binary files differdiff --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 4ddc99d8b74c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index da0909cb212f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9154643f4c91..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panama +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5be6f9b0160d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 24f925a2dd33..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c2bd2f949b24..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3e75731baa7c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fb5185ca6028..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7f8047d9396f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 47b4dc34160d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5c9a20b947f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6ddda4822d3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 92e2ed2dbe0f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 305abcb8a221..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recife +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a3f8217a544e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Regina +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a84d1dfdb3a8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fb5185ca6028..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 35a52e53d123..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 19ccd3576d46..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f81d144206ac..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8d6032264b65..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3e0785086639..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a16da2c4d5a9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6db49124e2bb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 09e54e5c7c5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 36681ed78eaf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e5f2aec2bb2b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bdbb494487de..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 38036a32831d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f38dc56bf20d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thule +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fcb032804311..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 19ccd3576d46..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fe6be8ea8c97..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c998491112ea..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4fe59034242..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 878b6a92f740..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7e646d18e188..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 773feba89d36..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c779cef92c8a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 30315cc07893..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3ec32224f298..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c0cfc85a29e8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 232717b613f1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 05e4c6c58673..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index afb392931847..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 32c1941634ae..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea49c00b2240..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index afb392931847..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 97d80d752c8e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4e31affb50e3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6e3290717e5a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dfc509570a5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 01c47ccb86cc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3ec4fc89fe99..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1bd09fef27c9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 551884d322bc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3a40d1175a7d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 62c5840a83e2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 848216726908..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 848216726908..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cb2c82f657c7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a3ce97599100..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7409d74983c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 96203d7a4266..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ed687d2985c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ff976dd3b27a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 55dce5722cc9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fe7832cdf99e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e67b411b9f5a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00bc80a65e9a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9d49cd35cd5e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0a948c2eaca3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6b66984a2f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6b66984a2f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3eeb1b72b689..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 28136808b6d1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 168ef9baa47e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 28136808b6d1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bb7be9f3a471..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 58d75bc26eec..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d83fb076a256..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cc44179564af..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4278ffa512b3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6b66984a2f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e55318aaca8c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7ca997250288..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c80e364801be..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6e08a261274e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 550e2a08773b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c89186687300..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c9752d2f23eb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7c22f539d948..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e6e6cc6ca584..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 660ce4cf6957..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c65155402db6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e56d5afdafb2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 69ff7f6fb497..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3a0d330ffd2f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3a0d330ffd2f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index aeb733202acd..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00bc80a65e9a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e0d4fcb5c3d7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e93dd5141bca..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 59bc6e40b7bb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 01c47ccb86cc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c22f75e42db6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c22f75e42db6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 16bac8444656..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5990010b6497..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3c3584e09ae4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 58d75bc26eec..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c210d0a5989c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9378d50539df..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 65a9fa2cd2e8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dc0ed422f619..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 25a63ec8b995..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ed687d2985c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 285bed2c63a5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 57240cf89fb3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7409d74983c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ff6fe61d5075..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fe4d6c6d6d44..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 14b2ad09ead5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 01c47ccb86cc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7ca997250288..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 69f0faad1e72..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c43e27c5d4bd..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1755147fab44..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6b66984a2f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 350d77e28ee7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7fdee5cbee2b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 35d89d036d07..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 65ee428ce1c5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 166e4341d6ce..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f1555f0032f5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e6e6cc6ca584..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0edc72cfe46b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0edc72cfe46b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1aa066ce38fc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c3c307d7b99f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5990010b6497..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6f5d3a15abbe..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6f5d3a15abbe..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 69ff7f6fb497..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c39331e3aa7d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ed687d2985c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 72a3d4e87a0d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 336f932e8d45..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 14b2ad09ead5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a3bf7f29b6f1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6dd927cb9410..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b7f75a9cf650..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index aa3301478f72..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5ab3243a5f01..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8f7de1c0a19a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9558bf7180ac..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9558bf7180ac..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dfc509570a5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7c3a49c0e8cd..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2451aca76d7c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7fa5f4683538..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8906e88c819d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1a4c8ea86361..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f235d0dc742a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f397b3b9eda6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c7915db30bae..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ed0d17a610e0..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f235d0dc742a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 55ceaefc6075..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7114153b65c3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9fbc01fe6779..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 21ef2d396f6b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4d4ec8ceea9a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e271d5b3e50e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4d4ec8ceea9a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c7160da33f3e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f235d0dc742a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7114153b65c3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/North +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e449b03fcf25..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c7915db30bae..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f397b3b9eda6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/South +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f235d0dc742a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 21ef2d396f6b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c7160da33f3e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e449b03fcf25..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/West +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ed0d17a610e0..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fb5185ca6028..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9e74745ca791..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a16da2c4d5a9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 59c952ebc651..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 546748d6eace..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/CET +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d9315580584f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9fa850a7d4c3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7e646d18e188..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fe6be8ea8c97..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 645ee9453073..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e5f2aec2bb2b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c998491112ea..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a3f8217a544e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 878b6a92f740..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8d6032264b65..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d29bcd68b020..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e06629d36841..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Cuba +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 378919ea1131..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/EET +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 3ae969114563..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/EST +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 50c95e0cb076..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea38c970086c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Egypt +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4a45ea8f73f8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Eire +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 98d5dcf917c6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ecb287e66786..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e941412971a4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9c95bd0736da..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6d5ce3db7323..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5ef7be71fd96..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 75f16216f0d3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 589990ae8966..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fcb60ca2465a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c0427a40eef9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9bdc2283c07d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ca7a81f656f2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cb45601c958d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 11d988e10a3e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f4c5d5cc29b5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cd397b02cdde..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8fad7c6b0bef..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a595e60eeae1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 97b44a9baecf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4eb17ff0057b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 13aef80cbbcf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 83a28169552f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 79a983e5454a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e136690e165a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bc70fe416fdb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d18cedd524f4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4a6fa1d4945d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 38685d4219d2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index aff8d82d2a2d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 231bf9c3b713..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 465546bd396a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fb7c145ac4c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 31973271d2f8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index efa689ba9e0a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 940be4670a64..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 388df2969f2d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6970b14c506c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 45984a7599d2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4a45ea8f73f8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 017bb2e34746..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ff5e56530570..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c89186687300..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 0ec475647055..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8f83cefbcc11..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d1c93c540c26..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 64841661a01a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/London +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 682bcbf61ac7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 60bdf4d07e6e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 27539c2243ff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ff5e56530570..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 30d3a672bf64..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f30dfc7014f4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5e6b6de6451b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c210d0a5989c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dfc509570a5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00a27264c2cb..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fb7c145ac4c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 26af4c90b3b7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 639ca3be4062..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8d0c26e5c852..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 639ca3be4062..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2684d8f8b89f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 88a6f3bdb469..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index eabc972a22df..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index dd3eb3227852..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5321bbd46e7a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 743a7337ffd8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6970b14c506c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bb842cb1f508..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a5755685e390..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 388df2969f2d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 639ca3be4062..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 75339e98d0a7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 75b2eebb57c5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a486ad42eac2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index efe1a40f2a8f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a1bf9281ed1b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4ea8dae45a6f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 388df2969f2d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b4dd7735ed5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Factory +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GB +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 323cd3818ac6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0 +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 157573b1d340..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwich +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 160a53e045c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/HST +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c80e364801be..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkong +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2451aca76d7c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Iceland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8b8ce226b6b7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 766024b36c50..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 117503410ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8ce93e01247e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 75362bbf033d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 58a82e4eb701..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7c1113488200..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d3c0bb328ce9..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 248a7c93a52b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f1555f0032f5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e6e6cc6ca584..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Israel +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index be6b1b6f1e77..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaica +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1aa066ce38fc..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Japan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9416d522d0a3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e0c89971aabe..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Libya +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6f0558c3b6f4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/MET +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a0953d1e791e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/MST +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 137867c8bf5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 19ccd3576d46..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4c819fab0247..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ffcf8bee10e5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index afb392931847..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f06065ebd183..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 09e54e5c7c5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d6b66984a2f3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/PRC +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index fde4833f6be3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 244af26f8a2f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index afb392931847..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7c667093c50d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f06065ebd183..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea3fb5cd3c9e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index d29bcd68b020..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 906971e2cecf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b22ab147c3b6..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b7b30213e154..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index e3934e423c9c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 78ab35b6b02f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index a9403eca467d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ddfc34ffc097..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 720c67901740..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bf9a2d955fc2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 40e3d492e6c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 40e3d492e6c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2f676d3bf5c8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index f5d58242c819..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9416d522d0a3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 9228ee02ede2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6ea24b72cd95..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 001289ceecff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ae13aac7792a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 7b3579351395..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 79e2a9419adf..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 824f814160ee..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 001289ceecff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bc8eb7a55b8a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 8a4ba4d30a6b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b92b254a9af1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b92b254a9af1..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5d8fc3a1b253..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 143a1883b0f8..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index bf9a2d955fc2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 001289ceecff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 50a064fa0166..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6bc216823e00..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 54aeb0ffa227..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea3fb5cd3c9e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 71cca8877d33..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 4bce89300306..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index ea3fb5cd3c9e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index efe1a40f2a8f..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Poland +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 64841661a01a..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugal +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 35d89d036d07..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/ROC +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 1755147fab44..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/ROK +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 350d77e28ee7..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Singapore +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c89186687300..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkey +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/UCT +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index cdf0572be31d..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b1497bda631e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index c2bd2f949b24..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b01688065392..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Central +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6b08d15bdaba..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 2b6c2eea14df..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 40e3d492e6c2..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index b187d5f8c756..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 6eb3ac46ec56..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 09e54e5c7c5b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index aaf07787ad92..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 001289ceecff..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/UTC +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Universal +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 5e6b6de6451b..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SU +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 423c6c203a50..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/WET +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 00841a62213e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulu +++ /dev/null Binary files differdiff --git a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab b/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab deleted file mode 100644 index a4ff61a4d321..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab +++ /dev/null @@ -1,274 +0,0 @@ -# ISO 3166 alpha-2 country codes -# -# This file is in the public domain, so clarified as of -# 2009-05-17 by Arthur David Olson. -# -# From Paul Eggert (2015-05-02): -# This file contains a table of two-letter country codes. Columns are -# separated by a single tab. Lines beginning with '#' are comments. -# All text uses UTF-8 encoding. The columns of the table are as follows: -# -# 1. ISO 3166-1 alpha-2 country code, current as of -# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1 -# https://isotc.iso.org/livelink/livelink/Open/16944257 -# 2. The usual English name for the coded region, -# chosen so that alphabetic sorting of subsets produces helpful lists. -# This is not the same as the English name in the ISO 3166 tables. -# -# The table is sorted by country code. -# -# This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. -# -#country- -#code name of country, territory, area, or subdivision -AD Andorra -AE United Arab Emirates -AF Afghanistan -AG Antigua & Barbuda -AI Anguilla -AL Albania -AM Armenia -AO Angola -AQ Antarctica -AR Argentina -AS Samoa (American) -AT Austria -AU Australia -AW Aruba -AX Åland Islands -AZ Azerbaijan -BA Bosnia & Herzegovina -BB Barbados -BD Bangladesh -BE Belgium -BF Burkina Faso -BG Bulgaria -BH Bahrain -BI Burundi -BJ Benin -BL St Barthelemy -BM Bermuda -BN Brunei -BO Bolivia -BQ Caribbean NL -BR Brazil -BS Bahamas -BT Bhutan -BV Bouvet Island -BW Botswana -BY Belarus -BZ Belize -CA Canada -CC Cocos (Keeling) Islands -CD Congo (Dem. Rep.) -CF Central African Rep. -CG Congo (Rep.) -CH Switzerland -CI Côte d'Ivoire -CK Cook Islands -CL Chile -CM Cameroon -CN China -CO Colombia -CR Costa Rica -CU Cuba -CV Cape Verde -CW Curaçao -CX Christmas Island -CY Cyprus -CZ Czech Republic -DE Germany -DJ Djibouti -DK Denmark -DM Dominica -DO Dominican Republic -DZ Algeria -EC Ecuador -EE Estonia -EG Egypt -EH Western Sahara -ER Eritrea -ES Spain -ET Ethiopia -FI Finland -FJ Fiji -FK Falkland Islands -FM Micronesia -FO Faroe Islands -FR France -GA Gabon -GB Britain (UK) -GD Grenada -GE Georgia -GF French Guiana -GG Guernsey -GH Ghana -GI Gibraltar -GL Greenland -GM Gambia -GN Guinea -GP Guadeloupe -GQ Equatorial Guinea -GR Greece -GS South Georgia & the South Sandwich Islands -GT Guatemala -GU Guam -GW Guinea-Bissau -GY Guyana -HK Hong Kong -HM Heard Island & McDonald Islands -HN Honduras -HR Croatia -HT Haiti -HU Hungary -ID Indonesia -IE Ireland -IL Israel -IM Isle of Man -IN India -IO British Indian Ocean Territory -IQ Iraq -IR Iran -IS Iceland -IT Italy -JE Jersey -JM Jamaica -JO Jordan -JP Japan -KE Kenya -KG Kyrgyzstan -KH Cambodia -KI Kiribati -KM Comoros -KN St Kitts & Nevis -KP Korea (North) -KR Korea (South) -KW Kuwait -KY Cayman Islands -KZ Kazakhstan -LA Laos -LB Lebanon -LC St Lucia -LI Liechtenstein -LK Sri Lanka -LR Liberia -LS Lesotho -LT Lithuania -LU Luxembourg -LV Latvia -LY Libya -MA Morocco -MC Monaco -MD Moldova -ME Montenegro -MF St Martin (French) -MG Madagascar -MH Marshall Islands -MK North Macedonia -ML Mali -MM Myanmar (Burma) -MN Mongolia -MO Macau -MP Northern Mariana Islands -MQ Martinique -MR Mauritania -MS Montserrat -MT Malta -MU Mauritius -MV Maldives -MW Malawi -MX Mexico -MY Malaysia -MZ Mozambique -NA Namibia -NC New Caledonia -NE Niger -NF Norfolk Island -NG Nigeria -NI Nicaragua -NL Netherlands -NO Norway -NP Nepal -NR Nauru -NU Niue -NZ New Zealand -OM Oman -PA Panama -PE Peru -PF French Polynesia -PG Papua New Guinea -PH Philippines -PK Pakistan -PL Poland -PM St Pierre & Miquelon -PN Pitcairn -PR Puerto Rico -PS Palestine -PT Portugal -PW Palau -PY Paraguay -QA Qatar -RE Réunion -RO Romania -RS Serbia -RU Russia -RW Rwanda -SA Saudi Arabia -SB Solomon Islands -SC Seychelles -SD Sudan -SE Sweden -SG Singapore -SH St Helena -SI Slovenia -SJ Svalbard & Jan Mayen -SK Slovakia -SL Sierra Leone -SM San Marino -SN Senegal -SO Somalia -SR Suriname -SS South Sudan -ST Sao Tome & Principe -SV El Salvador -SX St Maarten (Dutch) -SY Syria -SZ Eswatini (Swaziland) -TC Turks & Caicos Is -TD Chad -TF French Southern & Antarctic Lands -TG Togo -TH Thailand -TJ Tajikistan -TK Tokelau -TL East Timor -TM Turkmenistan -TN Tunisia -TO Tonga -TR Turkey -TT Trinidad & Tobago -TV Tuvalu -TW Taiwan -TZ Tanzania -UA Ukraine -UG Uganda -UM US minor outlying islands -US United States -UY Uruguay -UZ Uzbekistan -VA Vatican City -VC St Vincent -VE Venezuela -VG Virgin Islands (UK) -VI Virgin Islands (US) -VN Vietnam -VU Vanuatu -WF Wallis & Futuna -WS Samoa (western) -YE Yemen -YT Mayotte -ZA South Africa -ZM Zambia -ZW Zimbabwe diff --git a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/localtime b/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/localtime deleted file mode 100644 index afeeb88d0628..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/localtime +++ /dev/null Binary files differdiff --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 deleted file mode 100644 index 53ee77e88e5e..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab +++ /dev/null @@ -1,384 +0,0 @@ -# tzdb timezone descriptions -# -# This file is in the public domain. -# -# From Paul Eggert (2018-06-27): -# This file contains a table where each row stands for a timezone where -# civil timestamps have agreed since 1970. Columns are separated by -# a single tab. Lines beginning with '#' are comments. All text uses -# UTF-8 encoding. The columns of the table are as follows: -# -# 1. The countries that overlap the timezone, as a comma-separated list -# of ISO 3166 2-character country codes. See the file 'iso3166.tab'. -# 2. Latitude and longitude of the timezone's principal location -# in ISO 6709 sign-degrees-minutes-seconds format, -# either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS, -# first latitude (+ is north), then longitude (+ is east). -# 3. Timezone name used in value of TZ environment variable. -# Please see the theory.html file for how these names are chosen. -# If multiple timezones overlap a country, each has a row in the -# table, with each column 1 containing the country code. -# 4. Comments; present if and only if a country has multiple timezones. -# -# If a timezone covers multiple countries, the most-populous city is used, -# and that country is listed first in column 1; any other countries -# are listed alphabetically by country code. The table is sorted -# first by country code, then (if possible) by an order within the -# country that (1) makes some geographical sense, and (2) puts the -# most populous timezones first, where that does not contradict (1). -# -# This table is intended as an aid for users, to help them select timezones -# appropriate for their practical needs. It is not intended to take or -# endorse any position on legal or territorial claims. -# -#country- -#codes coordinates TZ comments -AD +4230+00131 Europe/Andorra -AE,OM +2518+05518 Asia/Dubai -AF +3431+06912 Asia/Kabul -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) -AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER, FM, MN, SE, SF) -AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN) -AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) -AR -2649-06513 America/Argentina/Tucuman Tucumán (TM) -AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH) -AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) -AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) -AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) -AR -3319-06621 America/Argentina/San_Luis San Luis (SL) -AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) -AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) -AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway -AT +4813+01620 Europe/Vienna -AU -3133+15905 Australia/Lord_Howe Lord Howe Island -AU -5430+15857 Antarctica/Macquarie Macquarie Island -AU -4253+14719 Australia/Hobart Tasmania (most areas) -AU -3956+14352 Australia/Currie Tasmania (King Island) -AU -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) -AU -2728+15302 Australia/Brisbane Queensland (most areas) -AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands) -AU -3455+13835 Australia/Adelaide South Australia -AU -1228+13050 Australia/Darwin Northern Territory -AU -3157+11551 Australia/Perth Western Australia (most areas) -AU -3143+12852 Australia/Eucla Western Australia (Eucla) -AZ +4023+04951 Asia/Baku -BB +1306-05937 America/Barbados -BD +2343+09025 Asia/Dhaka -BE +5050+00420 Europe/Brussels -BG +4241+02319 Europe/Sofia -BM +3217-06446 Atlantic/Bermuda -BN +0456+11455 Asia/Brunei -BO -1630-06809 America/La_Paz -BR -0351-03225 America/Noronha Atlantic islands -BR -0127-04829 America/Belem Pará (east); Amapá -BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB) -BR -0803-03454 America/Recife Pernambuco -BR -0712-04812 America/Araguaina Tocantins -BR -0940-03543 America/Maceio Alagoas, Sergipe -BR -1259-03831 America/Bahia Bahia -BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS) -BR -2027-05437 America/Campo_Grande Mato Grosso do Sul -BR -1535-05605 America/Cuiaba Mato Grosso -BR -0226-05452 America/Santarem Pará (west) -BR -0846-06354 America/Porto_Velho Rondônia -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 -CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast) -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 +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) -CA +624900-0920459 America/Rankin_Inlet Central - NU (central) -CA +5024-10439 America/Regina CST - SK (most areas) -CA +5017-10750 America/Swift_Current CST - SK (midwest) -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 +4916-12307 America/Vancouver Pacific - BC (most areas) -CA +6043-13503 America/Whitehorse Pacific - Yukon (east) -CA +6404-13925 America/Dawson Pacific - Yukon (west) -CC -1210+09655 Indian/Cocos -CH,DE,LI +4723+00832 Europe/Zurich Swiss time -CI,BF,GM,GN,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan -CK -2114-15946 Pacific/Rarotonga -CL -3327-07040 America/Santiago Chile (most areas) -CL -5309-07055 America/Punta_Arenas Region of Magallanes -CL -2709-10926 Pacific/Easter Easter Island -CN +3114+12128 Asia/Shanghai Beijing Time -CN +4348+08735 Asia/Urumqi Xinjiang Time -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 -CZ,SK +5005+01426 Europe/Prague -DE +5230+01322 Europe/Berlin Germany (most areas) -DK +5540+01235 Europe/Copenhagen -DO +1828-06954 America/Santo_Domingo -DZ +3647+00303 Africa/Algiers -EC -0210-07950 America/Guayaquil Ecuador (mainland) -EC -0054-08936 Pacific/Galapagos Galápagos Islands -EE +5925+02445 Europe/Tallinn -EG +3003+03115 Africa/Cairo -EH +2709-01312 Africa/El_Aaiun -ES +4024-00341 Europe/Madrid Spain (mainland) -ES +3553-00519 Africa/Ceuta Ceuta, Melilla -ES +2806-01524 Atlantic/Canary Canary Islands -FI,AX +6010+02458 Europe/Helsinki -FJ -1808+17825 Pacific/Fiji -FK -5142-05751 Atlantic/Stanley -FM +0725+15147 Pacific/Chuuk Chuuk/Truk, Yap -FM +0658+15813 Pacific/Pohnpei Pohnpei/Ponape -FM +0519+16259 Pacific/Kosrae Kosrae -FO +6201-00646 Atlantic/Faroe -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 +7646-01840 America/Danmarkshavn National Park (east coast) -GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit -GL +7634-06847 America/Thule Thule/Pituffik -GR +3758+02343 Europe/Athens -GS -5416-03632 Atlantic/South_Georgia -GT +1438-09031 America/Guatemala -GU,MP +1328+14445 Pacific/Guam -GW +1151-01535 Africa/Bissau -GY +0648-05810 America/Guyana -HK +2217+11409 Asia/Hong_Kong -HN +1406-08713 America/Tegucigalpa -HT +1832-07220 America/Port-au-Prince -HU +4730+01905 Europe/Budapest -ID -0610+10648 Asia/Jakarta Java, Sumatra -ID -0002+10920 Asia/Pontianak Borneo (west, central) -ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west) -ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas -IE +5320-00615 Europe/Dublin -IL +314650+0351326 Asia/Jerusalem -IN +2232+08822 Asia/Kolkata -IO -0720+07225 Indian/Chagos -IQ +3321+04425 Asia/Baghdad -IR +3540+05126 Asia/Tehran -IS +6409-02151 Atlantic/Reykjavik -IT,SM,VA +4154+01229 Europe/Rome -JM +175805-0764736 America/Jamaica -JO +3157+03556 Asia/Amman -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 -0308-17105 Pacific/Enderbury Phoenix Islands -KI +0152-15720 Pacific/Kiritimati Line Islands -KP +3901+12545 Asia/Pyongyang -KR +3733+12658 Asia/Seoul -KZ +4315+07657 Asia/Almaty Kazakhstan (most areas) -KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda -KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay -KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe -KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau -KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev -KZ +5113+05121 Asia/Oral West Kazakhstan -LB +3353+03530 Asia/Beirut -LK +0656+07951 Asia/Colombo -LR +0618-01047 Africa/Monrovia -LT +5441+02519 Europe/Vilnius -LU +4936+00609 Europe/Luxembourg -LV +5657+02406 Europe/Riga -LY +3254+01311 Africa/Tripoli -MA +3339-00735 Africa/Casablanca -MC +4342+00723 Europe/Monaco -MD +4700+02850 Europe/Chisinau -MH +0709+17112 Pacific/Majuro Marshall Islands (most areas) -MH +0905+16720 Pacific/Kwajalein Kwajalein -MM +1647+09610 Asia/Yangon -MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas) -MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan -MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar -MO +221150+1133230 Asia/Macau -MQ +1436-06105 America/Martinique -MT +3554+01431 Europe/Malta -MU -2010+05730 Indian/Mauritius -MV +0410+07330 Indian/Maldives -MX +1924-09909 America/Mexico_City Central Time -MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo -MX +2058-08937 America/Merida Central Time - Campeche, Yucatán -MX +2540-10019 America/Monterrey Central Time - Durango; Coahuila, Nuevo León, Tamaulipas (most areas) -MX +2550-09730 America/Matamoros Central Time US - Coahuila, Nuevo León, Tamaulipas (US border) -MX +2313-10625 America/Mazatlan Mountain Time - Baja California Sur, Nayarit, Sinaloa -MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua (most areas) -MX +2934-10425 America/Ojinaga Mountain Time US - Chihuahua (US border) -MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora -MX +3232-11701 America/Tijuana Pacific Time US - Baja California -MX +2048-10515 America/Bahia_Banderas Central Time - Bahía de Banderas -MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula) -MY +0133+11020 Asia/Kuching Sabah, Sarawak -MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time -NA -2234+01706 Africa/Windhoek -NC -2216+16627 Pacific/Noumea -NF -2903+16758 Pacific/Norfolk -NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time -NI +1209-08617 America/Managua -NL +5222+00454 Europe/Amsterdam -NO,SJ +5955+01045 Europe/Oslo -NP +2743+08519 Asia/Kathmandu -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,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 -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 +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) -PT +3238-01654 Atlantic/Madeira Madeira Islands -PT +3744-02540 Atlantic/Azores Azores -PW +0720+13429 Pacific/Palau -PY -2516-05740 America/Asuncion -QA,BH +2517+05132 Asia/Qatar -RE,TF -2052+05528 Indian/Reunion Réunion, Crozet, Scattered Islands -RO +4426+02606 Europe/Bucharest -RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade -RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad -RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area -# Mention RU and UA alphabetically. See "territorial claims" above. -RU,UA +4457+03406 Europe/Simferopol Crimea -RU +5836+04939 Europe/Kirov MSK+00 - Kirov -RU +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 -RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals -RU +5500+07324 Asia/Omsk MSK+03 - Omsk -RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk -RU +5322+08345 Asia/Barnaul MSK+04 - Altai -RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk -RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo -RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area -RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia -RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky -RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River -RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky -RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River -RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky -RU +5934+15048 Asia/Magadan MSK+08 - Magadan -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,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 +0117+10351 Asia/Singapore -SR +0550-05510 America/Paramaribo -SS +0451+03137 Africa/Juba -ST +0020+00644 Africa/Sao_Tome -SV +1342-08912 America/El_Salvador -SY +3330+03618 Asia/Damascus -TC +2128-07108 America/Grand_Turk -TD +1207+01503 Africa/Ndjamena -TF -492110+0701303 Indian/Kerguelen Kerguelen, St Paul Island, Amsterdam Island -TH,KH,LA,VN +1345+10031 Asia/Bangkok Indochina (most areas) -TJ +3835+06848 Asia/Dushanbe -TK -0922-17114 Pacific/Fakaofo -TL -0833+12535 Asia/Dili -TM +3757+05823 Asia/Ashgabat -TN +3648+01011 Africa/Tunis -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 -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) -US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area) -US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne) -US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas) -US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn) -US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski) -US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford) -US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike) -US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland) -US +415100-0873900 America/Chicago Central (most areas) -US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry) -US +411745-0863730 America/Indiana/Knox Central - IN (Starke) -US +450628-0873651 America/Menominee Central - MI (Wisconsin border) -US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver) -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 +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 -US +571035-1351807 America/Sitka Alaska - Sitka area -US +550737-1313435 America/Metlakatla Alaska - Annette Island -US +593249-1394338 America/Yakutat Alaska - Yakutat -US +643004-1652423 America/Nome Alaska (west) -US +515248-1763929 America/Adak Aleutian Islands -US,UM +211825-1575130 Pacific/Honolulu Hawaii -UY -345433-0561245 America/Montevideo -UZ +3940+06648 Asia/Samarkand Uzbekistan (west) -UZ +4120+06918 Asia/Tashkent Uzbekistan (east) -VE +1030-06656 America/Caracas -VN +1045+10640 Asia/Ho_Chi_Minh Vietnam (south) -VU -1740+16825 Pacific/Efate -WF -1318-17610 Pacific/Wallis -WS -1350-17144 Pacific/Apia -ZA,LS,SZ -2615+02800 Africa/Johannesburg diff --git a/third_party/abseil_cpp/absl/time/internal/get_current_time_chrono.inc b/third_party/abseil_cpp/absl/time/internal/get_current_time_chrono.inc deleted file mode 100644 index 5eeb6406aaf3..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/get_current_time_chrono.inc +++ /dev/null @@ -1,31 +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 <chrono> -#include <cstdint> - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { - return std::chrono::duration_cast<std::chrono::nanoseconds>( - std::chrono::system_clock::now() - - std::chrono::system_clock::from_time_t(0)) - .count(); -} - -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/get_current_time_posix.inc b/third_party/abseil_cpp/absl/time/internal/get_current_time_posix.inc deleted file mode 100644 index 42072000ae3c..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/get_current_time_posix.inc +++ /dev/null @@ -1,24 +0,0 @@ -#include "absl/time/clock.h" - -#include <sys/time.h> -#include <ctime> -#include <cstdint> - -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { - const int64_t kNanosPerSecond = 1000 * 1000 * 1000; - struct timespec ts; - ABSL_RAW_CHECK(clock_gettime(CLOCK_REALTIME, &ts) == 0, - "Failed to read real-time clock."); - return (int64_t{ts.tv_sec} * kNanosPerSecond + - int64_t{ts.tv_nsec}); -} - -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/test_util.cc b/third_party/abseil_cpp/absl/time/internal/test_util.cc deleted file mode 100644 index 9a485a0750e4..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/test_util.cc +++ /dev/null @@ -1,131 +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/time/internal/test_util.h" - -#include <algorithm> -#include <cstddef> -#include <cstring> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/time/internal/cctz/include/cctz/zone_info_source.h" - -namespace cctz = absl::time_internal::cctz; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { - -TimeZone LoadTimeZone(const std::string& name) { - TimeZone tz; - ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str()); - return tz; -} - -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz_extension { -namespace { - -// Embed the zoneinfo data for time zones used during tests and benchmarks. -// The data was generated using "xxd -i zoneinfo-file". There is no need -// to update the data as long as the tests do not depend on recent changes -// (and the past rules remain the same). -#include "absl/time/internal/zoneinfo.inc" - -const struct ZoneInfo { - const char* name; - const char* data; - std::size_t length; -} kZoneInfo[] = { - // The three real time zones used by :time_test and :time_benchmark. - {"America/Los_Angeles", // - reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len}, - {"America/New_York", // - reinterpret_cast<char*>(America_New_York), America_New_York_len}, - {"Australia/Sydney", // - reinterpret_cast<char*>(Australia_Sydney), Australia_Sydney_len}, - - // Other zones named in tests but which should fail to load. - {"Invalid/TimeZone", nullptr, 0}, - {"", nullptr, 0}, - - // Also allow for loading the local time zone under TZ=US/Pacific. - {"US/Pacific", // - reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len}, - - // Allows use of the local time zone from a system-specific location. -#ifdef _MSC_VER - {"localtime", // - reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len}, -#else - {"/etc/localtime", // - reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len}, -#endif -}; - -class TestZoneInfoSource : public cctz::ZoneInfoSource { - public: - TestZoneInfoSource(const char* data, std::size_t size) - : data_(data), end_(data + size) {} - - std::size_t Read(void* ptr, std::size_t size) override { - const std::size_t len = std::min<std::size_t>(size, end_ - data_); - memcpy(ptr, data_, len); - data_ += len; - return len; - } - - int Skip(std::size_t offset) override { - data_ += std::min<std::size_t>(offset, end_ - data_); - return 0; - } - - private: - const char* data_; - const char* const end_; -}; - -std::unique_ptr<cctz::ZoneInfoSource> TestFactory( - const std::string& name, - const std::function<std::unique_ptr<cctz::ZoneInfoSource>( - const std::string& name)>& /*fallback_factory*/) { - for (const ZoneInfo& zoneinfo : kZoneInfo) { - if (name == zoneinfo.name) { - if (zoneinfo.data == nullptr) return nullptr; - return std::unique_ptr<cctz::ZoneInfoSource>( - new TestZoneInfoSource(zoneinfo.data, zoneinfo.length)); - } - } - ABSL_RAW_LOG(FATAL, "Unexpected time zone \"%s\" in test", name.c_str()); - return nullptr; -} - -} // namespace - -#if !defined(__MINGW32__) -// MinGW does not support the weak symbol extension mechanism. -ZoneInfoSourceFactory zone_info_source_factory = TestFactory; -#endif - -} // namespace cctz_extension -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/internal/test_util.h b/third_party/abseil_cpp/absl/time/internal/test_util.h deleted file mode 100644 index 5c4bf1f680ee..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/test_util.h +++ /dev/null @@ -1,33 +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. - -#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_ -#define ABSL_TIME_INTERNAL_TEST_UTIL_H_ - -#include <string> - -#include "absl/time/time.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace time_internal { - -// Loads the named timezone, but dies on any failure. -absl::TimeZone LoadTimeZone(const std::string& name); - -} // namespace time_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_ diff --git a/third_party/abseil_cpp/absl/time/internal/zoneinfo.inc b/third_party/abseil_cpp/absl/time/internal/zoneinfo.inc deleted file mode 100644 index bfed82990dd5..000000000000 --- a/third_party/abseil_cpp/absl/time/internal/zoneinfo.inc +++ /dev/null @@ -1,729 +0,0 @@ -unsigned char America_Los_Angeles[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, - 0x9e, 0xa6, 0x48, 0xa0, 0x9f, 0xbb, 0x15, 0x90, 0xa0, 0x86, 0x2a, 0xa0, - 0xa1, 0x9a, 0xf7, 0x90, 0xcb, 0x89, 0x1a, 0xa0, 0xd2, 0x23, 0xf4, 0x70, - 0xd2, 0x61, 0x26, 0x10, 0xd6, 0xfe, 0x74, 0x5c, 0xd8, 0x80, 0xad, 0x90, - 0xda, 0xfe, 0xc3, 0x90, 0xdb, 0xc0, 0x90, 0x10, 0xdc, 0xde, 0xa5, 0x90, - 0xdd, 0xa9, 0xac, 0x90, 0xde, 0xbe, 0x87, 0x90, 0xdf, 0x89, 0x8e, 0x90, - 0xe0, 0x9e, 0x69, 0x90, 0xe1, 0x69, 0x70, 0x90, 0xe2, 0x7e, 0x4b, 0x90, - 0xe3, 0x49, 0x52, 0x90, 0xe4, 0x5e, 0x2d, 0x90, 0xe5, 0x29, 0x34, 0x90, - 0xe6, 0x47, 0x4a, 0x10, 0xe7, 0x12, 0x51, 0x10, 0xe8, 0x27, 0x2c, 0x10, - 0xe8, 0xf2, 0x33, 0x10, 0xea, 0x07, 0x0e, 0x10, 0xea, 0xd2, 0x15, 0x10, - 0xeb, 0xe6, 0xf0, 0x10, 0xec, 0xb1, 0xf7, 0x10, 0xed, 0xc6, 0xd2, 0x10, - 0xee, 0x91, 0xd9, 0x10, 0xef, 0xaf, 0xee, 0x90, 0xf0, 0x71, 0xbb, 0x10, - 0xf1, 0x8f, 0xd0, 0x90, 0xf2, 0x7f, 0xc1, 0x90, 0xf3, 0x6f, 0xb2, 0x90, - 0xf4, 0x5f, 0xa3, 0x90, 0xf5, 0x4f, 0x94, 0x90, 0xf6, 0x3f, 0x85, 0x90, - 0xf7, 0x2f, 0x76, 0x90, 0xf8, 0x28, 0xa2, 0x10, 0xf9, 0x0f, 0x58, 0x90, - 0xfa, 0x08, 0x84, 0x10, 0xfa, 0xf8, 0x83, 0x20, 0xfb, 0xe8, 0x66, 0x10, - 0xfc, 0xd8, 0x65, 0x20, 0xfd, 0xc8, 0x48, 0x10, 0xfe, 0xb8, 0x47, 0x20, - 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x98, 0x29, 0x20, 0x01, 0x88, 0x0c, 0x10, - 0x02, 0x78, 0x0b, 0x20, 0x03, 0x71, 0x28, 0x90, 0x04, 0x61, 0x27, 0xa0, - 0x05, 0x51, 0x0a, 0x90, 0x06, 0x41, 0x09, 0xa0, 0x07, 0x30, 0xec, 0x90, - 0x07, 0x8d, 0x43, 0xa0, 0x09, 0x10, 0xce, 0x90, 0x09, 0xad, 0xbf, 0x20, - 0x0a, 0xf0, 0xb0, 0x90, 0x0b, 0xe0, 0xaf, 0xa0, 0x0c, 0xd9, 0xcd, 0x10, - 0x0d, 0xc0, 0x91, 0xa0, 0x0e, 0xb9, 0xaf, 0x10, 0x0f, 0xa9, 0xae, 0x20, - 0x10, 0x99, 0x91, 0x10, 0x11, 0x89, 0x90, 0x20, 0x12, 0x79, 0x73, 0x10, - 0x13, 0x69, 0x72, 0x20, 0x14, 0x59, 0x55, 0x10, 0x15, 0x49, 0x54, 0x20, - 0x16, 0x39, 0x37, 0x10, 0x17, 0x29, 0x36, 0x20, 0x18, 0x22, 0x53, 0x90, - 0x19, 0x09, 0x18, 0x20, 0x1a, 0x02, 0x35, 0x90, 0x1a, 0xf2, 0x34, 0xa0, - 0x1b, 0xe2, 0x17, 0x90, 0x1c, 0xd2, 0x16, 0xa0, 0x1d, 0xc1, 0xf9, 0x90, - 0x1e, 0xb1, 0xf8, 0xa0, 0x1f, 0xa1, 0xdb, 0x90, 0x20, 0x76, 0x2b, 0x20, - 0x21, 0x81, 0xbd, 0x90, 0x22, 0x56, 0x0d, 0x20, 0x23, 0x6a, 0xda, 0x10, - 0x24, 0x35, 0xef, 0x20, 0x25, 0x4a, 0xbc, 0x10, 0x26, 0x15, 0xd1, 0x20, - 0x27, 0x2a, 0x9e, 0x10, 0x27, 0xfe, 0xed, 0xa0, 0x29, 0x0a, 0x80, 0x10, - 0x29, 0xde, 0xcf, 0xa0, 0x2a, 0xea, 0x62, 0x10, 0x2b, 0xbe, 0xb1, 0xa0, - 0x2c, 0xd3, 0x7e, 0x90, 0x2d, 0x9e, 0x93, 0xa0, 0x2e, 0xb3, 0x60, 0x90, - 0x2f, 0x7e, 0x75, 0xa0, 0x30, 0x93, 0x42, 0x90, 0x31, 0x67, 0x92, 0x20, - 0x32, 0x73, 0x24, 0x90, 0x33, 0x47, 0x74, 0x20, 0x34, 0x53, 0x06, 0x90, - 0x35, 0x27, 0x56, 0x20, 0x36, 0x32, 0xe8, 0x90, 0x37, 0x07, 0x38, 0x20, - 0x38, 0x1c, 0x05, 0x10, 0x38, 0xe7, 0x1a, 0x20, 0x39, 0xfb, 0xe7, 0x10, - 0x3a, 0xc6, 0xfc, 0x20, 0x3b, 0xdb, 0xc9, 0x10, 0x3c, 0xb0, 0x18, 0xa0, - 0x3d, 0xbb, 0xab, 0x10, 0x3e, 0x8f, 0xfa, 0xa0, 0x3f, 0x9b, 0x8d, 0x10, - 0x40, 0x6f, 0xdc, 0xa0, 0x41, 0x84, 0xa9, 0x90, 0x42, 0x4f, 0xbe, 0xa0, - 0x43, 0x64, 0x8b, 0x90, 0x44, 0x2f, 0xa0, 0xa0, 0x45, 0x44, 0x6d, 0x90, - 0x45, 0xf3, 0xd3, 0x20, 0x47, 0x2d, 0x8a, 0x10, 0x47, 0xd3, 0xb5, 0x20, - 0x49, 0x0d, 0x6c, 0x10, 0x49, 0xb3, 0x97, 0x20, 0x4a, 0xed, 0x4e, 0x10, - 0x4b, 0x9c, 0xb3, 0xa0, 0x4c, 0xd6, 0x6a, 0x90, 0x4d, 0x7c, 0x95, 0xa0, - 0x4e, 0xb6, 0x4c, 0x90, 0x4f, 0x5c, 0x77, 0xa0, 0x50, 0x96, 0x2e, 0x90, - 0x51, 0x3c, 0x59, 0xa0, 0x52, 0x76, 0x10, 0x90, 0x53, 0x1c, 0x3b, 0xa0, - 0x54, 0x55, 0xf2, 0x90, 0x54, 0xfc, 0x1d, 0xa0, 0x56, 0x35, 0xd4, 0x90, - 0x56, 0xe5, 0x3a, 0x20, 0x58, 0x1e, 0xf1, 0x10, 0x58, 0xc5, 0x1c, 0x20, - 0x59, 0xfe, 0xd3, 0x10, 0x5a, 0xa4, 0xfe, 0x20, 0x5b, 0xde, 0xb5, 0x10, - 0x5c, 0x84, 0xe0, 0x20, 0x5d, 0xbe, 0x97, 0x10, 0x5e, 0x64, 0xc2, 0x20, - 0x5f, 0x9e, 0x79, 0x10, 0x60, 0x4d, 0xde, 0xa0, 0x61, 0x87, 0x95, 0x90, - 0x62, 0x2d, 0xc0, 0xa0, 0x63, 0x67, 0x77, 0x90, 0x64, 0x0d, 0xa2, 0xa0, - 0x65, 0x47, 0x59, 0x90, 0x65, 0xed, 0x84, 0xa0, 0x67, 0x27, 0x3b, 0x90, - 0x67, 0xcd, 0x66, 0xa0, 0x69, 0x07, 0x1d, 0x90, 0x69, 0xad, 0x48, 0xa0, - 0x6a, 0xe6, 0xff, 0x90, 0x6b, 0x96, 0x65, 0x20, 0x6c, 0xd0, 0x1c, 0x10, - 0x6d, 0x76, 0x47, 0x20, 0x6e, 0xaf, 0xfe, 0x10, 0x6f, 0x56, 0x29, 0x20, - 0x70, 0x8f, 0xe0, 0x10, 0x71, 0x36, 0x0b, 0x20, 0x72, 0x6f, 0xc2, 0x10, - 0x73, 0x15, 0xed, 0x20, 0x74, 0x4f, 0xa4, 0x10, 0x74, 0xff, 0x09, 0xa0, - 0x76, 0x38, 0xc0, 0x90, 0x76, 0xde, 0xeb, 0xa0, 0x78, 0x18, 0xa2, 0x90, - 0x78, 0xbe, 0xcd, 0xa0, 0x79, 0xf8, 0x84, 0x90, 0x7a, 0x9e, 0xaf, 0xa0, - 0x7b, 0xd8, 0x66, 0x90, 0x7c, 0x7e, 0x91, 0xa0, 0x7d, 0xb8, 0x48, 0x90, - 0x7e, 0x5e, 0x73, 0xa0, 0x7f, 0x98, 0x2a, 0x90, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, - 0x01, 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, - 0x01, 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, - 0x50, 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, - 0x50, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xbb, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x04, - 0x1a, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x48, 0xa0, 0xff, 0xff, - 0xff, 0xff, 0x9f, 0xbb, 0x15, 0x90, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, - 0x2a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xf7, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xcb, 0x89, 0x1a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x23, - 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x61, 0x26, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xd6, 0xfe, 0x74, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x80, - 0xad, 0x90, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xc3, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xdb, 0xc0, 0x90, 0x10, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xde, - 0xa5, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0xac, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xde, 0xbe, 0x87, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x89, - 0x8e, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x69, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xe1, 0x69, 0x70, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x7e, - 0x4b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x52, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xe4, 0x5e, 0x2d, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x29, - 0x34, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x4a, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xe7, 0x12, 0x51, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x27, - 0x2c, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf2, 0x33, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xea, 0x07, 0x0e, 0x10, 0xff, 0xff, 0xff, 0xff, 0xea, 0xd2, - 0x15, 0x10, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xf0, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xec, 0xb1, 0xf7, 0x10, 0xff, 0xff, 0xff, 0xff, 0xed, 0xc6, - 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xee, 0x91, 0xd9, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xaf, 0xee, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x71, - 0xbb, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xd0, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf2, 0x7f, 0xc1, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x6f, - 0xb2, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0xa3, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf5, 0x4f, 0x94, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x3f, - 0x85, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x76, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x28, 0xa2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0f, - 0x58, 0x90, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x84, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0xf8, 0x83, 0x20, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe8, - 0x66, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x65, 0x20, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xc8, 0x48, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb8, - 0x47, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x98, 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, - 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x0b, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x71, 0x28, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x61, - 0x27, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x51, 0x0a, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x41, 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, - 0xec, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x43, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x09, 0x10, 0xce, 0x90, 0x00, 0x00, 0x00, 0x00, 0x09, 0xad, - 0xbf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0xb0, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x0b, 0xe0, 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd9, - 0xcd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x91, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0xb9, 0xaf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa9, - 0xae, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x91, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x89, 0x90, 0x20, 0x00, 0x00, 0x00, 0x00, 0x12, 0x79, - 0x73, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x72, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x14, 0x59, 0x55, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, - 0x54, 0x20, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x37, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x29, 0x36, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x22, - 0x53, 0x90, 0x00, 0x00, 0x00, 0x00, 0x19, 0x09, 0x18, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x1a, 0x02, 0x35, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xf2, - 0x34, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe2, 0x17, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0xd2, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, - 0xf9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xf8, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0xa1, 0xdb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x76, - 0x2b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0xbd, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x56, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x23, 0x6a, - 0xda, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xef, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4a, 0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x15, - 0xd1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x9e, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x27, 0xfe, 0xed, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x29, 0x0a, - 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xcf, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x2a, 0xea, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xbe, - 0xb1, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x7e, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x9e, 0x93, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb3, - 0x60, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x75, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x93, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x67, - 0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x73, 0x24, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x33, 0x47, 0x74, 0x20, 0x00, 0x00, 0x00, 0x00, 0x34, 0x53, - 0x06, 0x90, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x56, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x36, 0x32, 0xe8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, - 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x05, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x38, 0xe7, 0x1a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb, - 0xe7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xfc, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x3b, 0xdb, 0xc9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb0, - 0x18, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0xab, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x8f, 0xfa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b, - 0x8d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xdc, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x41, 0x84, 0xa9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4f, - 0xbe, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x8b, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x44, 0x2f, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, - 0x6d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xd3, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x47, 0x2d, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xd3, - 0xb5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x6c, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x49, 0xb3, 0x97, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xed, - 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0xb3, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x4c, 0xd6, 0x6a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x7c, - 0x95, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x4c, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x5c, 0x77, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, - 0x2e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x59, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x52, 0x76, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x1c, - 0x3b, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xf2, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x54, 0xfc, 0x1d, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x35, - 0xd4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x3a, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x58, 0x1e, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xc5, - 0x1c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xd3, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x5a, 0xa4, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xde, - 0xb5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xe0, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x5d, 0xbe, 0x97, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x64, - 0xc2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x79, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x4d, 0xde, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x87, - 0x95, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0xc0, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x67, 0x77, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0d, - 0xa2, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x59, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x65, 0xed, 0x84, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x27, - 0x3b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x66, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x69, 0x07, 0x1d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xad, - 0x48, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xff, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x96, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd0, - 0x1c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x47, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x6e, 0xaf, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x56, - 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xe0, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x71, 0x36, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, - 0xc2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xed, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x74, 0x4f, 0xa4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x74, 0xff, - 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0xc0, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xde, 0xeb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, - 0xa2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xcd, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x79, 0xf8, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x9e, - 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x66, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0x7e, 0x91, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xb8, - 0x48, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x73, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x98, 0x2a, 0x90, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, 0x01, - 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, 0x01, - 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x50, - 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50, - 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x0a, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x2c, 0x4d, 0x33, - 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31, 0x2e, 0x30, - 0x0a -}; -unsigned int America_Los_Angeles_len = 2845; -unsigned char America_New_York[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, - 0x9e, 0xa6, 0x1e, 0x70, 0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, - 0xa1, 0x9a, 0xcd, 0x60, 0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, - 0xa4, 0x6a, 0xae, 0x70, 0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, - 0xa7, 0x15, 0x89, 0x60, 0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, - 0xaa, 0x13, 0x8e, 0xf0, 0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, - 0xac, 0xbe, 0x69, 0xe0, 0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, - 0xaf, 0xb3, 0x34, 0xf0, 0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, - 0xb2, 0x67, 0x4a, 0x60, 0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, - 0xb5, 0x5c, 0x15, 0x70, 0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, - 0xb8, 0x06, 0xf0, 0x60, 0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, - 0xbb, 0x04, 0xf5, 0xf0, 0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, - 0xbd, 0xaf, 0xd0, 0xe0, 0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, - 0xc0, 0xa4, 0x9b, 0xf0, 0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, - 0xc3, 0x4f, 0x76, 0xe0, 0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, - 0xc6, 0x4d, 0x7c, 0x70, 0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, - 0xc8, 0xf8, 0x57, 0x60, 0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, - 0xcb, 0x88, 0xf0, 0x70, 0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, - 0xd3, 0x75, 0xe4, 0xf0, 0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, - 0xd6, 0x20, 0xbf, 0xe0, 0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, - 0xd9, 0x15, 0x8a, 0xf0, 0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, - 0xdb, 0xc0, 0x65, 0xe0, 0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, - 0xde, 0xbe, 0x6b, 0x70, 0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, - 0xe1, 0x69, 0x46, 0x60, 0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, - 0xe4, 0x5e, 0x11, 0x70, 0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, - 0xe7, 0x37, 0x10, 0xe0, 0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, - 0xea, 0x06, 0xf1, 0xf0, 0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, - 0xec, 0xd6, 0xb6, 0xe0, 0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, - 0xef, 0xaf, 0xd2, 0x70, 0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, - 0xf2, 0x7f, 0x97, 0x60, 0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, - 0xf5, 0x4f, 0x78, 0x70, 0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, - 0xf8, 0x28, 0x77, 0xe0, 0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, - 0xfa, 0xf8, 0x58, 0xf0, 0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, - 0xfd, 0xc8, 0x1d, 0xe0, 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, - 0x00, 0x97, 0xfe, 0xf0, 0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, - 0x03, 0x70, 0xfe, 0x60, 0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, - 0x06, 0x40, 0xdf, 0x70, 0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, - 0x09, 0x10, 0xa4, 0x60, 0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, - 0x0b, 0xe0, 0x85, 0x70, 0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, - 0x0e, 0xb9, 0x84, 0xe0, 0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, - 0x11, 0x89, 0x65, 0xf0, 0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, - 0x14, 0x59, 0x2a, 0xe0, 0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, - 0x17, 0x29, 0x0b, 0xf0, 0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, - 0x1a, 0x02, 0x0b, 0x60, 0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, - 0x1c, 0xd1, 0xec, 0x70, 0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, - 0x1f, 0xa1, 0xb1, 0x60, 0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, - 0x22, 0x55, 0xe2, 0xf0, 0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, - 0x25, 0x4a, 0x91, 0xe0, 0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, - 0x27, 0xfe, 0xc3, 0x70, 0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, - 0x2a, 0xea, 0x37, 0xe0, 0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, - 0x2d, 0x9e, 0x69, 0x70, 0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, - 0x30, 0x93, 0x18, 0x60, 0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, - 0x33, 0x47, 0x49, 0xf0, 0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, - 0x36, 0x32, 0xbe, 0x60, 0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, - 0x38, 0xe6, 0xef, 0xf0, 0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, - 0x3b, 0xdb, 0x9e, 0xe0, 0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, - 0x3e, 0x8f, 0xd0, 0x70, 0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, - 0x41, 0x84, 0x7f, 0x60, 0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, - 0x44, 0x2f, 0x76, 0x70, 0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, - 0x47, 0x2d, 0x5f, 0xe0, 0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, - 0x49, 0xb3, 0x6c, 0xf0, 0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, - 0x4c, 0xd6, 0x40, 0x60, 0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, - 0x4f, 0x5c, 0x4d, 0x70, 0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, - 0x52, 0x75, 0xe6, 0x60, 0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, - 0x54, 0xfb, 0xf3, 0x70, 0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, - 0x58, 0x1e, 0xc6, 0xe0, 0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, - 0x5a, 0xa4, 0xd3, 0xf0, 0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, - 0x5d, 0xbe, 0x6c, 0xe0, 0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, - 0x60, 0x4d, 0xb4, 0x70, 0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, - 0x63, 0x67, 0x4d, 0x60, 0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, - 0x65, 0xed, 0x5a, 0x70, 0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, - 0x69, 0x06, 0xf3, 0x60, 0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, - 0x6b, 0x96, 0x3a, 0xf0, 0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, - 0x6e, 0xaf, 0xd3, 0xe0, 0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, - 0x71, 0x35, 0xe0, 0xf0, 0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, - 0x74, 0x4f, 0x79, 0xe0, 0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, - 0x76, 0xde, 0xc1, 0x70, 0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, - 0x79, 0xf8, 0x5a, 0x60, 0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, - 0x7c, 0x7e, 0x67, 0x70, 0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, - 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x04, - 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, - 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x45, 0x44, - 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, - 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, - 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, - 0x9f, 0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xa2, 0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xa8, 0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xaa, 0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xad, 0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xb0, 0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xb3, 0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xb6, 0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xb9, 0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xbb, 0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xbe, 0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xc1, 0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xc4, 0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xc7, 0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xca, 0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xd2, 0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xd4, 0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xd7, 0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xdc, 0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xe2, 0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xe5, 0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xe8, 0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xea, 0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xed, 0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xf3, 0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xf6, 0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x09, 0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x12, 0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x15, 0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x1d, 0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x23, 0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x29, 0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x2e, 0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x31, 0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x37, 0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x39, 0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x42, 0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x47, 0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x4a, 0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x4d, 0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x50, 0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x53, 0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x58, 0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x5e, 0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x61, 0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x69, 0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x6f, 0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x74, 0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x7a, 0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x7d, 0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x00, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, - 0xff, 0xc7, 0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, - 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, - 0x4d, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, - 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, - 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, - 0x2e, 0x31, 0x2e, 0x30, 0x0a -}; -unsigned int America_New_York_len = 3545; -unsigned char Australia_Sydney[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, 0x80, 0x00, 0x00, 0x00, - 0x9c, 0x4e, 0xa6, 0x9c, 0x9c, 0xbc, 0x20, 0xf0, 0xcb, 0x54, 0xb3, 0x00, - 0xcb, 0xc7, 0x57, 0x70, 0xcc, 0xb7, 0x56, 0x80, 0xcd, 0xa7, 0x39, 0x70, - 0xce, 0xa0, 0x73, 0x00, 0xcf, 0x87, 0x1b, 0x70, 0x03, 0x70, 0x39, 0x80, - 0x04, 0x0d, 0x1c, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x05, 0xf6, 0x38, 0x80, - 0x07, 0x2f, 0xfd, 0x80, 0x07, 0xd6, 0x1a, 0x80, 0x09, 0x0f, 0xdf, 0x80, - 0x09, 0xb5, 0xfc, 0x80, 0x0a, 0xef, 0xc1, 0x80, 0x0b, 0x9f, 0x19, 0x00, - 0x0c, 0xd8, 0xde, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x0e, 0xb8, 0xc0, 0x00, - 0x0f, 0x5e, 0xdd, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x11, 0x3e, 0xbf, 0x00, - 0x12, 0x78, 0x84, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x14, 0x58, 0x66, 0x00, - 0x14, 0xfe, 0x83, 0x00, 0x16, 0x38, 0x48, 0x00, 0x17, 0x0c, 0x89, 0x80, - 0x18, 0x21, 0x64, 0x80, 0x18, 0xc7, 0x81, 0x80, 0x1a, 0x01, 0x46, 0x80, - 0x1a, 0xa7, 0x63, 0x80, 0x1b, 0xe1, 0x28, 0x80, 0x1c, 0x87, 0x45, 0x80, - 0x1d, 0xc1, 0x0a, 0x80, 0x1e, 0x79, 0x9c, 0x80, 0x1f, 0x97, 0xb2, 0x00, - 0x20, 0x59, 0x7e, 0x80, 0x21, 0x80, 0xce, 0x80, 0x22, 0x42, 0x9b, 0x00, - 0x23, 0x69, 0xeb, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x25, 0x49, 0xcd, 0x00, - 0x25, 0xef, 0xea, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x27, 0xcf, 0xcc, 0x00, - 0x29, 0x09, 0x91, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x2a, 0xe9, 0x73, 0x00, - 0x2b, 0x98, 0xca, 0x80, 0x2c, 0xd2, 0x8f, 0x80, 0x2d, 0x78, 0xac, 0x80, - 0x2e, 0xb2, 0x71, 0x80, 0x2f, 0x58, 0x8e, 0x80, 0x30, 0x92, 0x53, 0x80, - 0x31, 0x5d, 0x5a, 0x80, 0x32, 0x72, 0x35, 0x80, 0x33, 0x3d, 0x3c, 0x80, - 0x34, 0x52, 0x17, 0x80, 0x35, 0x1d, 0x1e, 0x80, 0x36, 0x31, 0xf9, 0x80, - 0x36, 0xfd, 0x00, 0x80, 0x38, 0x1b, 0x16, 0x00, 0x38, 0xdc, 0xe2, 0x80, - 0x39, 0xa7, 0xe9, 0x80, 0x3a, 0xbc, 0xc4, 0x80, 0x3b, 0xda, 0xda, 0x00, - 0x3c, 0xa5, 0xe1, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x3e, 0x85, 0xc3, 0x00, - 0x3f, 0x9a, 0x9e, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x41, 0x83, 0xba, 0x80, - 0x42, 0x45, 0x87, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x44, 0x2e, 0xa3, 0x80, - 0x45, 0x43, 0x7e, 0x80, 0x46, 0x05, 0x4b, 0x00, 0x47, 0x23, 0x60, 0x80, - 0x47, 0xf7, 0xa2, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x49, 0xd7, 0x84, 0x00, - 0x4a, 0xc7, 0x75, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x4c, 0xa7, 0x57, 0x00, - 0x4d, 0x97, 0x48, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x4f, 0x77, 0x2a, 0x00, - 0x50, 0x70, 0x55, 0x80, 0x51, 0x60, 0x46, 0x80, 0x52, 0x50, 0x37, 0x80, - 0x53, 0x40, 0x28, 0x80, 0x54, 0x30, 0x19, 0x80, 0x55, 0x20, 0x0a, 0x80, - 0x56, 0x0f, 0xfb, 0x80, 0x56, 0xff, 0xec, 0x80, 0x57, 0xef, 0xdd, 0x80, - 0x58, 0xdf, 0xce, 0x80, 0x59, 0xcf, 0xbf, 0x80, 0x5a, 0xbf, 0xb0, 0x80, - 0x5b, 0xb8, 0xdc, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x5d, 0x98, 0xbe, 0x00, - 0x5e, 0x88, 0xaf, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x60, 0x68, 0x91, 0x00, - 0x61, 0x58, 0x82, 0x00, 0x62, 0x48, 0x73, 0x00, 0x63, 0x38, 0x64, 0x00, - 0x64, 0x28, 0x55, 0x00, 0x65, 0x18, 0x46, 0x00, 0x66, 0x11, 0x71, 0x80, - 0x67, 0x01, 0x62, 0x80, 0x67, 0xf1, 0x53, 0x80, 0x68, 0xe1, 0x44, 0x80, - 0x69, 0xd1, 0x35, 0x80, 0x6a, 0xc1, 0x26, 0x80, 0x6b, 0xb1, 0x17, 0x80, - 0x6c, 0xa1, 0x08, 0x80, 0x6d, 0x90, 0xf9, 0x80, 0x6e, 0x80, 0xea, 0x80, - 0x6f, 0x70, 0xdb, 0x80, 0x70, 0x6a, 0x07, 0x00, 0x71, 0x59, 0xf8, 0x00, - 0x72, 0x49, 0xe9, 0x00, 0x73, 0x39, 0xda, 0x00, 0x74, 0x29, 0xcb, 0x00, - 0x75, 0x19, 0xbc, 0x00, 0x76, 0x09, 0xad, 0x00, 0x76, 0xf9, 0x9e, 0x00, - 0x77, 0xe9, 0x8f, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x79, 0xc9, 0x71, 0x00, - 0x7a, 0xb9, 0x62, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x7c, 0xa2, 0x7e, 0x80, - 0x7d, 0x92, 0x6f, 0x80, 0x7e, 0x82, 0x60, 0x80, 0x7f, 0x72, 0x51, 0x80, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x00, 0x00, - 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, - 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, - 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x45, 0x44, 0x54, - 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x73, 0x16, 0x7f, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x4e, 0xa6, 0x9c, - 0xff, 0xff, 0xff, 0xff, 0x9c, 0xbc, 0x20, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xcb, 0x54, 0xb3, 0x00, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xc7, 0x57, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xcc, 0xb7, 0x56, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xcd, 0xa7, 0x39, 0x70, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa0, 0x73, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xcf, 0x87, 0x1b, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x70, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0d, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x05, 0xf6, 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2f, 0xfd, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xd6, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x0f, 0xdf, 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xb5, 0xfc, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0xef, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x9f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd8, 0xde, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0e, 0xb8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x5e, 0xdd, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x78, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0x58, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xfe, 0x83, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x16, 0x38, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x0c, 0x89, 0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x21, 0x64, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x18, 0xc7, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x01, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xa7, 0x63, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1c, 0x87, 0x45, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, 0x0a, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x97, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x59, 0x7e, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0xce, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x42, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x69, 0xeb, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x49, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xef, 0xea, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0xcf, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x09, 0x91, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0xe9, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x98, 0xca, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd2, 0x8f, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x2d, 0x78, 0xac, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb2, 0x71, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0x58, 0x8e, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x92, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d, 0x5a, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x33, 0x3d, 0x3c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x17, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x1e, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x31, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0xdc, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa7, 0xe9, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbc, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x3b, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa5, 0xe1, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x85, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9a, 0x9e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x41, 0x83, 0xba, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0x87, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x2e, 0xa3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43, 0x7e, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x23, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x47, 0xf7, 0xa2, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x49, 0xd7, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xc7, 0x75, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4c, 0xa7, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x97, 0x48, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x77, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x70, 0x55, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x60, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x52, 0x50, 0x37, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x40, 0x28, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x30, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x20, 0x0a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0f, 0xfb, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0xec, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x57, 0xef, 0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x58, 0xdf, 0xce, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x59, 0xcf, 0xbf, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x5a, 0xbf, 0xb0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xb8, 0xdc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0x98, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x88, 0xaf, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x68, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x58, 0x82, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0x48, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x63, 0x38, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x55, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0x18, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x11, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x62, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x67, 0xf1, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xe1, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xd1, 0x35, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x6a, 0xc1, 0x26, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x6b, 0xb1, 0x17, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xa1, 0x08, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x6d, 0x90, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x6e, 0x80, 0xea, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0xdb, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x70, 0x6a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x71, 0x59, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x49, 0xe9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x73, 0x39, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, 0x29, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x19, 0xbc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x09, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xf9, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xe9, 0x8f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x79, 0xc9, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb9, 0x62, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xa2, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x92, 0x6f, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x82, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x72, 0x51, 0x80, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x00, 0x00, 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, - 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, - 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, - 0x00, 0x41, 0x45, 0x44, 0x54, 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x45, - 0x53, 0x54, 0x2d, 0x31, 0x30, 0x41, 0x45, 0x44, 0x54, 0x2c, 0x4d, 0x31, - 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x4d, 0x34, 0x2e, 0x31, 0x2e, 0x30, - 0x2f, 0x33, 0x0a -}; -unsigned int Australia_Sydney_len = 2223; diff --git a/third_party/abseil_cpp/absl/time/time.cc b/third_party/abseil_cpp/absl/time/time.cc deleted file mode 100644 index 1ec2026e254f..000000000000 --- a/third_party/abseil_cpp/absl/time/time.cc +++ /dev/null @@ -1,500 +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. - -// The implementation of the absl::Time class, which is declared in -// //absl/time.h. -// -// The representation for an absl::Time is an absl::Duration offset from the -// epoch. We use the traditional Unix epoch (1970-01-01 00:00:00 +0000) -// for convenience, but this is not exposed in the API and could be changed. -// -// NOTE: To keep type verbosity to a minimum, the following variable naming -// conventions are used throughout this file. -// -// tz: An absl::TimeZone -// ci: An absl::TimeZone::CivilInfo -// ti: An absl::TimeZone::TimeInfo -// cd: An absl::CivilDay or a cctz::civil_day -// cs: An absl::CivilSecond or a cctz::civil_second -// bd: An absl::Time::Breakdown -// cl: A cctz::time_zone::civil_lookup -// al: A cctz::time_zone::absolute_lookup - -#include "absl/time/time.h" - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <cstring> -#include <ctime> -#include <limits> - -#include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace cctz = absl::time_internal::cctz; - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -inline cctz::time_point<cctz::seconds> unix_epoch() { - return std::chrono::time_point_cast<cctz::seconds>( - std::chrono::system_clock::from_time_t(0)); -} - -// Floors d to the next unit boundary closer to negative infinity. -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; -} - -inline absl::Time::Breakdown InfiniteFutureBreakdown() { - absl::Time::Breakdown bd; - bd.year = std::numeric_limits<int64_t>::max(); - bd.month = 12; - bd.day = 31; - bd.hour = 23; - bd.minute = 59; - bd.second = 59; - bd.subsecond = absl::InfiniteDuration(); - bd.weekday = 4; - bd.yearday = 365; - bd.offset = 0; - bd.is_dst = false; - bd.zone_abbr = "-00"; - return bd; -} - -inline absl::Time::Breakdown InfinitePastBreakdown() { - Time::Breakdown bd; - bd.year = std::numeric_limits<int64_t>::min(); - bd.month = 1; - bd.day = 1; - bd.hour = 0; - bd.minute = 0; - bd.second = 0; - bd.subsecond = -absl::InfiniteDuration(); - bd.weekday = 7; - bd.yearday = 1; - bd.offset = 0; - bd.is_dst = false; - bd.zone_abbr = "-00"; - return bd; -} - -inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() { - TimeZone::CivilInfo ci; - ci.cs = CivilSecond::max(); - ci.subsecond = InfiniteDuration(); - ci.offset = 0; - ci.is_dst = false; - ci.zone_abbr = "-00"; - return ci; -} - -inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() { - TimeZone::CivilInfo ci; - ci.cs = CivilSecond::min(); - ci.subsecond = -InfiniteDuration(); - ci.offset = 0; - ci.is_dst = false; - ci.zone_abbr = "-00"; - return ci; -} - -inline absl::TimeConversion InfiniteFutureTimeConversion() { - absl::TimeConversion tc; - tc.pre = tc.trans = tc.post = absl::InfiniteFuture(); - tc.kind = absl::TimeConversion::UNIQUE; - tc.normalized = true; - return tc; -} - -inline TimeConversion InfinitePastTimeConversion() { - absl::TimeConversion tc; - tc.pre = tc.trans = tc.post = absl::InfinitePast(); - tc.kind = absl::TimeConversion::UNIQUE; - tc.normalized = true; - return tc; -} - -// Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as -// necessary. If sec is min/max, then consult cs+tz to check for overlow. -Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec, - const cctz::civil_second& cs, - const cctz::time_zone& tz, - bool* normalized = nullptr) { - const auto max = cctz::time_point<cctz::seconds>::max(); - const auto min = cctz::time_point<cctz::seconds>::min(); - if (sec == max) { - const auto al = tz.lookup(max); - if (cs > al.cs) { - if (normalized) *normalized = true; - return absl::InfiniteFuture(); - } - } - if (sec == min) { - const auto al = tz.lookup(min); - if (cs < al.cs) { - if (normalized) *normalized = true; - return absl::InfinitePast(); - } - } - const auto hi = (sec - unix_epoch()).count(); - return time_internal::FromUnixDuration(time_internal::MakeDuration(hi)); -} - -// Returns Mon=1..Sun=7. -inline int MapWeekday(const cctz::weekday& wd) { - switch (wd) { - case cctz::weekday::monday: - return 1; - case cctz::weekday::tuesday: - return 2; - case cctz::weekday::wednesday: - return 3; - case cctz::weekday::thursday: - return 4; - case cctz::weekday::friday: - return 5; - case cctz::weekday::saturday: - return 6; - case cctz::weekday::sunday: - return 7; - } - return 1; -} - -bool FindTransition(const cctz::time_zone& tz, - bool (cctz::time_zone::*find_transition)( - const cctz::time_point<cctz::seconds>& tp, - cctz::time_zone::civil_transition* trans) const, - Time t, TimeZone::CivilTransition* trans) { - // Transitions are second-aligned, so we can discard any fractional part. - const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t)); - cctz::time_zone::civil_transition tr; - if (!(tz.*find_transition)(tp, &tr)) return false; - trans->from = CivilSecond(tr.from); - trans->to = CivilSecond(tr.to); - return true; -} - -} // namespace - -// -// Time -// - -absl::Time::Breakdown Time::In(absl::TimeZone tz) const { - if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown(); - if (*this == absl::InfinitePast()) return InfinitePastBreakdown(); - - const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_)); - const auto al = cctz::time_zone(tz).lookup(tp); - const auto cs = al.cs; - const auto cd = cctz::civil_day(cs); - - absl::Time::Breakdown bd; - bd.year = cs.year(); - bd.month = cs.month(); - bd.day = cs.day(); - bd.hour = cs.hour(); - bd.minute = cs.minute(); - bd.second = cs.second(); - bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_)); - bd.weekday = MapWeekday(cctz::get_weekday(cd)); - bd.yearday = cctz::get_yearday(cd); - bd.offset = al.offset; - bd.is_dst = al.is_dst; - bd.zone_abbr = al.abbr; - return bd; -} - -// -// Conversions from/to other time types. -// - -absl::Time FromUDate(double udate) { - return time_internal::FromUnixDuration(absl::Milliseconds(udate)); -} - -absl::Time FromUniversal(int64_t universal) { - return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal); -} - -int64_t ToUnixNanos(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * - 1000 * 1000 * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4); - } - return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1)); -} - -int64_t ToUnixMicros(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * - 1000 * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000); - } - return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1)); -} - -int64_t ToUnixMillis(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / - (4000 * 1000)); - } - return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1)); -} - -int64_t ToUnixSeconds(Time t) { - return time_internal::GetRepHi(time_internal::ToUnixDuration(t)); -} - -time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; } - -double ToUDate(Time t) { - return absl::FDivDuration(time_internal::ToUnixDuration(t), - absl::Milliseconds(1)); -} - -int64_t ToUniversal(absl::Time t) { - return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100)); -} - -absl::Time TimeFromTimespec(timespec ts) { - return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts)); -} - -absl::Time TimeFromTimeval(timeval tv) { - return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv)); -} - -timespec ToTimespec(Time t) { - timespec ts; - absl::Duration d = time_internal::ToUnixDuration(t); - if (!time_internal::IsInfiniteDuration(d)) { - ts.tv_sec = time_internal::GetRepHi(d); - if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing - ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor - return ts; - } - } - if (d >= absl::ZeroDuration()) { - ts.tv_sec = std::numeric_limits<time_t>::max(); - ts.tv_nsec = 1000 * 1000 * 1000 - 1; - } else { - ts.tv_sec = std::numeric_limits<time_t>::min(); - ts.tv_nsec = 0; - } - return ts; -} - -timeval ToTimeval(Time t) { - timeval tv; - timespec ts = absl::ToTimespec(t); - tv.tv_sec = ts.tv_sec; - if (tv.tv_sec != ts.tv_sec) { // narrowing - if (ts.tv_sec < 0) { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); - tv.tv_usec = 0; - } else { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); - tv.tv_usec = 1000 * 1000 - 1; - } - return tv; - } - tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t - return tv; -} - -Time FromChrono(const std::chrono::system_clock::time_point& tp) { - return time_internal::FromUnixDuration(time_internal::FromChrono( - tp - std::chrono::system_clock::from_time_t(0))); -} - -std::chrono::system_clock::time_point ToChronoTime(absl::Time t) { - using D = std::chrono::system_clock::duration; - auto d = time_internal::ToUnixDuration(t); - if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1})); - return std::chrono::system_clock::from_time_t(0) + - time_internal::ToChronoDuration<D>(d); -} - -// -// TimeZone -// - -absl::TimeZone::CivilInfo TimeZone::At(Time t) const { - if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo(); - if (t == absl::InfinitePast()) return InfinitePastCivilInfo(); - - const auto ud = time_internal::ToUnixDuration(t); - const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud)); - const auto al = cz_.lookup(tp); - - TimeZone::CivilInfo ci; - ci.cs = CivilSecond(al.cs); - ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud)); - ci.offset = al.offset; - ci.is_dst = al.is_dst; - ci.zone_abbr = al.abbr; - return ci; -} - -absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const { - const cctz::civil_second cs(ct); - const auto cl = cz_.lookup(cs); - - TimeZone::TimeInfo ti; - switch (cl.kind) { - case cctz::time_zone::civil_lookup::UNIQUE: - ti.kind = TimeZone::TimeInfo::UNIQUE; - break; - case cctz::time_zone::civil_lookup::SKIPPED: - ti.kind = TimeZone::TimeInfo::SKIPPED; - break; - case cctz::time_zone::civil_lookup::REPEATED: - ti.kind = TimeZone::TimeInfo::REPEATED; - break; - } - ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_); - ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_); - ti.post = MakeTimeWithOverflow(cl.post, cs, cz_); - return ti; -} - -bool TimeZone::NextTransition(Time t, CivilTransition* trans) const { - return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans); -} - -bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const { - return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans); -} - -// -// Conversions involving time zones. -// - -absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz) { - // Avoids years that are too extreme for CivilSecond to normalize. - if (year > 300000000000) return InfiniteFutureTimeConversion(); - if (year < -300000000000) return InfinitePastTimeConversion(); - - const CivilSecond cs(year, mon, day, hour, min, sec); - const auto ti = tz.At(cs); - - TimeConversion tc; - tc.pre = ti.pre; - tc.trans = ti.trans; - tc.post = ti.post; - switch (ti.kind) { - case TimeZone::TimeInfo::UNIQUE: - tc.kind = TimeConversion::UNIQUE; - break; - case TimeZone::TimeInfo::SKIPPED: - tc.kind = TimeConversion::SKIPPED; - break; - case TimeZone::TimeInfo::REPEATED: - tc.kind = TimeConversion::REPEATED; - break; - } - tc.normalized = false; - if (year != cs.year() || mon != cs.month() || day != cs.day() || - hour != cs.hour() || min != cs.minute() || sec != cs.second()) { - tc.normalized = true; - } - return tc; -} - -absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) { - civil_year_t tm_year = tm.tm_year; - // Avoids years that are too extreme for CivilSecond to normalize. - if (tm_year > 300000000000ll) return InfiniteFuture(); - if (tm_year < -300000000000ll) return InfinitePast(); - int tm_mon = tm.tm_mon; - if (tm_mon == std::numeric_limits<int>::max()) { - tm_mon -= 12; - tm_year += 1; - } - const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); - return tm.tm_isdst == 0 ? ti.post : ti.pre; -} - -struct tm ToTM(absl::Time t, absl::TimeZone tz) { - struct tm tm = {}; - - const auto ci = tz.At(t); - const auto& cs = ci.cs; - tm.tm_sec = cs.second(); - tm.tm_min = cs.minute(); - tm.tm_hour = cs.hour(); - tm.tm_mday = cs.day(); - tm.tm_mon = cs.month() - 1; - - // Saturates tm.tm_year in cases of over/underflow, accounting for the fact - // that tm.tm_year is years since 1900. - if (cs.year() < std::numeric_limits<int>::min() + 1900) { - tm.tm_year = std::numeric_limits<int>::min(); - } else if (cs.year() > std::numeric_limits<int>::max()) { - tm.tm_year = std::numeric_limits<int>::max() - 1900; - } else { - tm.tm_year = static_cast<int>(cs.year() - 1900); - } - - switch (GetWeekday(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 = GetYearDay(cs) - 1; - tm.tm_isdst = ci.is_dst ? 1 : 0; - - return tm; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/time/time.h b/third_party/abseil_cpp/absl/time/time.h deleted file mode 100644 index 72508031acd6..000000000000 --- a/third_party/abseil_cpp/absl/time/time.h +++ /dev/null @@ -1,1581 +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. -// -// ----------------------------------------------------------------------------- -// File: time.h -// ----------------------------------------------------------------------------- -// -// This header file defines abstractions for computing with absolute points -// in time, durations of time, and formatting and parsing time within a given -// time zone. The following abstractions are defined: -// -// * `absl::Time` defines an absolute, specific instance in time -// * `absl::Duration` defines a signed, fixed-length span of time -// * `absl::TimeZone` defines geopolitical time zone regions (as collected -// within the IANA Time Zone database (https://www.iana.org/time-zones)). -// -// Note: Absolute times are distinct from civil times, which refer to the -// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping -// between absolute and civil times can be specified by use of time zones -// (`absl::TimeZone` within this API). That is: -// -// Civil Time = F(Absolute Time, Time Zone) -// Absolute Time = G(Civil Time, Time Zone) -// -// See civil_time.h for abstractions related to constructing and manipulating -// civil time. -// -// Example: -// -// absl::TimeZone nyc; -// // LoadTimeZone() may fail so it's always better to check for success. -// if (!absl::LoadTimeZone("America/New_York", &nyc)) { -// // handle error case -// } -// -// // My flight leaves NYC on Jan 2, 2017 at 03:04:05 -// absl::CivilSecond cs(2017, 1, 2, 3, 4, 5); -// absl::Time takeoff = absl::FromCivil(cs, nyc); -// -// absl::Duration flight_duration = absl::Hours(21) + absl::Minutes(35); -// absl::Time landing = takeoff + flight_duration; -// -// absl::TimeZone syd; -// if (!absl::LoadTimeZone("Australia/Sydney", &syd)) { -// // handle error case -// } -// std::string s = absl::FormatTime( -// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S", -// landing, syd); - -#ifndef ABSL_TIME_TIME_H_ -#define ABSL_TIME_TIME_H_ - -#if !defined(_MSC_VER) -#include <sys/time.h> -#else -// We don't include `winsock2.h` because it drags in `windows.h` and friends, -// and they define conflicting macros like OPAQUE, ERROR, and more. This has the -// potential to break Abseil users. -// -// Instead we only forward declare `timeval` and require Windows users include -// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is -// including 'windows.h' so we are picking the lesser of two evils here. -struct timeval; -#endif -#include <chrono> // NOLINT(build/c++11) -#include <cmath> -#include <cstdint> -#include <ctime> -#include <ostream> -#include <string> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/strings/string_view.h" -#include "absl/time/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class Duration; // Defined below -class Time; // Defined below -class TimeZone; // Defined below - -namespace time_internal { -int64_t IDivDuration(bool satq, Duration num, Duration den, Duration* rem); -constexpr Time FromUnixDuration(Duration d); -constexpr Duration ToUnixDuration(Time t); -constexpr int64_t GetRepHi(Duration d); -constexpr uint32_t GetRepLo(Duration d); -constexpr Duration MakeDuration(int64_t hi, uint32_t lo); -constexpr Duration MakeDuration(int64_t hi, int64_t lo); -inline Duration MakePosDoubleDuration(double n); -constexpr int64_t kTicksPerNanosecond = 4; -constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond; -template <std::intmax_t N> -constexpr Duration FromInt64(int64_t v, std::ratio<1, N>); -constexpr Duration FromInt64(int64_t v, std::ratio<60>); -constexpr Duration FromInt64(int64_t v, std::ratio<3600>); -template <typename T> -using EnableIfIntegral = typename std::enable_if< - std::is_integral<T>::value || std::is_enum<T>::value, int>::type; -template <typename T> -using EnableIfFloat = - typename std::enable_if<std::is_floating_point<T>::value, int>::type; -} // namespace time_internal - -// Duration -// -// The `absl::Duration` class represents a signed, fixed-length span of time. -// A `Duration` is generated using a unit-specific factory function, or is -// the result of subtracting one `absl::Time` from another. Durations behave -// like unit-safe integers and they support all the natural integer-like -// arithmetic operations. Arithmetic overflows and saturates at +/- infinity. -// `Duration` should be passed by value rather than const reference. -// -// Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`, -// `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for -// creation of constexpr `Duration` values -// -// Examples: -// -// constexpr absl::Duration ten_ns = absl::Nanoseconds(10); -// constexpr absl::Duration min = absl::Minutes(1); -// constexpr absl::Duration hour = absl::Hours(1); -// absl::Duration dur = 60 * min; // dur == hour -// absl::Duration half_sec = absl::Milliseconds(500); -// absl::Duration quarter_sec = 0.25 * absl::Seconds(1); -// -// `Duration` values can be easily converted to an integral number of units -// using the division operator. -// -// Example: -// -// constexpr absl::Duration dur = absl::Milliseconds(1500); -// int64_t ns = dur / absl::Nanoseconds(1); // ns == 1500000000 -// int64_t ms = dur / absl::Milliseconds(1); // ms == 1500 -// int64_t sec = dur / absl::Seconds(1); // sec == 1 (subseconds truncated) -// int64_t min = dur / absl::Minutes(1); // min == 0 -// -// See the `IDivDuration()` and `FDivDuration()` functions below for details on -// how to access the fractional parts of the quotient. -// -// Alternatively, conversions can be performed using helpers such as -// `ToInt64Microseconds()` and `ToDoubleSeconds()`. -class Duration { - public: - // Value semantics. - constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration - - // Copyable. -#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910 - // Explicitly defining the constexpr copy constructor avoids an MSVC bug. - constexpr Duration(const Duration& d) - : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {} -#else - constexpr Duration(const Duration& d) = default; -#endif - Duration& operator=(const Duration& d) = default; - - // Compound assignment operators. - Duration& operator+=(Duration d); - Duration& operator-=(Duration d); - Duration& operator*=(int64_t r); - Duration& operator*=(double r); - Duration& operator/=(int64_t r); - Duration& operator/=(double r); - Duration& operator%=(Duration rhs); - - // Overloads that forward to either the int64_t or double overloads above. - // Integer operands must be representable as int64_t. - template <typename T> - Duration& operator*=(T r) { - int64_t x = r; - return *this *= x; - } - template <typename T> - Duration& operator/=(T r) { - int64_t 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) { - return H::combine(std::move(h), d.rep_hi_, d.rep_lo_); - } - - private: - friend constexpr int64_t time_internal::GetRepHi(Duration d); - friend constexpr uint32_t time_internal::GetRepLo(Duration d); - friend constexpr Duration time_internal::MakeDuration(int64_t hi, - uint32_t lo); - constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {} - int64_t rep_hi_; - uint32_t rep_lo_; -}; - -// Relational Operators -constexpr bool operator<(Duration lhs, Duration rhs); -constexpr bool operator>(Duration lhs, Duration rhs) { return rhs < lhs; } -constexpr bool operator>=(Duration lhs, Duration rhs) { return !(lhs < rhs); } -constexpr bool operator<=(Duration lhs, Duration rhs) { return !(rhs < lhs); } -constexpr bool operator==(Duration lhs, Duration rhs); -constexpr bool operator!=(Duration lhs, Duration rhs) { return !(lhs == rhs); } - -// Additive Operators -constexpr Duration operator-(Duration d); -inline Duration operator+(Duration lhs, Duration rhs) { return lhs += rhs; } -inline Duration operator-(Duration lhs, Duration rhs) { return lhs -= rhs; } - -// Multiplicative Operators -// Integer operands must be representable as int64_t. -template <typename T> -Duration operator*(Duration lhs, T rhs) { - return lhs *= rhs; -} -template <typename T> -Duration operator*(T lhs, Duration rhs) { - return rhs *= lhs; -} -template <typename T> -Duration operator/(Duration lhs, T rhs) { - return lhs /= rhs; -} -inline int64_t operator/(Duration lhs, Duration rhs) { - return time_internal::IDivDuration(true, lhs, rhs, - &lhs); // trunc towards zero -} -inline Duration operator%(Duration lhs, Duration rhs) { return lhs %= rhs; } - -// IDivDuration() -// -// Divides a numerator `Duration` by a denominator `Duration`, returning the -// quotient and remainder. The remainder always has the same sign as the -// numerator. The returned quotient and remainder respect the identity: -// -// numerator = denominator * quotient + remainder -// -// Returned quotients are capped to the range of `int64_t`, with the difference -// spilling into the remainder to uphold the above identity. This means that the -// remainder returned could differ from the remainder returned by -// `Duration::operator%` for huge quotients. -// -// See also the notes on `InfiniteDuration()` below regarding the behavior of -// division involving zero and infinite durations. -// -// Example: -// -// constexpr absl::Duration a = -// absl::Seconds(std::numeric_limits<int64_t>::max()); // big -// constexpr absl::Duration b = absl::Nanoseconds(1); // small -// -// absl::Duration rem = a % b; -// // rem == absl::ZeroDuration() -// -// // Here, q would overflow int64_t, so rem accounts for the difference. -// int64_t q = absl::IDivDuration(a, b, &rem); -// // q == std::numeric_limits<int64_t>::max(), rem == a - b * q -inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) { - return time_internal::IDivDuration(true, num, den, - rem); // trunc towards zero -} - -// FDivDuration() -// -// Divides a `Duration` numerator into a fractional number of units of a -// `Duration` denominator. -// -// See also the notes on `InfiniteDuration()` below regarding the behavior of -// division involving zero and infinite durations. -// -// Example: -// -// double d = absl::FDivDuration(absl::Milliseconds(1500), absl::Seconds(1)); -// // d == 1.5 -double FDivDuration(Duration num, Duration den); - -// ZeroDuration() -// -// Returns a zero-length duration. This function behaves just like the default -// constructor, but the name helps make the semantics clear at call sites. -constexpr Duration ZeroDuration() { return Duration(); } - -// AbsDuration() -// -// Returns the absolute value of a duration. -inline Duration AbsDuration(Duration d) { - return (d < ZeroDuration()) ? -d : d; -} - -// Trunc() -// -// Truncates a duration (toward zero) to a multiple of a non-zero unit. -// -// Example: -// -// absl::Duration d = absl::Nanoseconds(123456789); -// absl::Duration a = absl::Trunc(d, absl::Microseconds(1)); // 123456us -Duration Trunc(Duration d, Duration unit); - -// Floor() -// -// Floors a duration using the passed duration unit to its largest value not -// greater than the duration. -// -// Example: -// -// absl::Duration d = absl::Nanoseconds(123456789); -// absl::Duration b = absl::Floor(d, absl::Microseconds(1)); // 123456us -Duration Floor(Duration d, Duration unit); - -// Ceil() -// -// Returns the ceiling of a duration using the passed duration unit to its -// smallest value not less than the duration. -// -// Example: -// -// absl::Duration d = absl::Nanoseconds(123456789); -// absl::Duration c = absl::Ceil(d, absl::Microseconds(1)); // 123457us -Duration Ceil(Duration d, Duration unit); - -// InfiniteDuration() -// -// Returns an infinite `Duration`. To get a `Duration` representing negative -// infinity, use `-InfiniteDuration()`. -// -// Duration arithmetic overflows to +/- infinity and saturates. In general, -// arithmetic with `Duration` infinities is similar to IEEE 754 infinities -// except where IEEE 754 NaN would be involved, in which case +/- -// `InfiniteDuration()` is used in place of a "nan" Duration. -// -// Examples: -// -// constexpr absl::Duration inf = absl::InfiniteDuration(); -// const absl::Duration d = ... any finite duration ... -// -// inf == inf + inf -// inf == inf + d -// inf == inf - inf -// -inf == d - inf -// -// inf == d * 1e100 -// inf == inf / 2 -// 0 == d / inf -// INT64_MAX == inf / d -// -// d < inf -// -inf < d -// -// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate. -// inf == d / 0 -// INT64_MAX == d / absl::ZeroDuration() -// -// The examples involving the `/` operator above also apply to `IDivDuration()` -// and `FDivDuration()`. -constexpr Duration InfiniteDuration(); - -// Nanoseconds() -// Microseconds() -// Milliseconds() -// Seconds() -// Minutes() -// Hours() -// -// Factory functions for constructing `Duration` values from an integral number -// of the unit indicated by the factory function's name. The number must be -// representable as int64_t. -// -// NOTE: no "Days()" factory function exists because "a day" is ambiguous. -// Civil days are not always 24 hours long, and a 24-hour duration often does -// not correspond with a civil day. If a 24-hour duration is needed, use -// `absl::Hours(24)`. If you actually want a civil day, use absl::CivilDay -// from civil_time.h. -// -// Example: -// -// absl::Duration a = absl::Seconds(60); -// absl::Duration b = absl::Minutes(1); // b == a -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 -// exist for convenience, but they are not as efficient as the integral -// factories, which should be preferred. -// -// Example: -// -// auto a = absl::Seconds(1.5); // OK -// auto b = absl::Milliseconds(1500); // BETTER -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Nanoseconds(T n) { - return n * Nanoseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Microseconds(T n) { - return n * Microseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Milliseconds(T n) { - return n * Milliseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Seconds(T n) { - if (n >= 0) { // Note: `NaN >= 0` is false. - if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) { - return InfiniteDuration(); - } - return time_internal::MakePosDoubleDuration(n); - } else { - if (std::isnan(n)) - return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration(); - if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration(); - return -time_internal::MakePosDoubleDuration(-n); - } -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Minutes(T n) { - return n * Minutes(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Hours(T n) { - return n * Hours(1); -} - -// ToInt64Nanoseconds() -// ToInt64Microseconds() -// ToInt64Milliseconds() -// ToInt64Seconds() -// ToInt64Minutes() -// ToInt64Hours() -// -// Helper functions that convert a Duration to an integral count of the -// 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 -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() -// ToDoubleMilliseconds() -// ToDoubleSeconds() -// ToDoubleMinutes() -// ToDoubleHours() -// -// Helper functions that convert a Duration to a floating point count of the -// indicated unit. These functions are shorthand for the `FDivDuration()` -// function above; see its documentation for details about overflow, etc. -// -// Example: -// -// absl::Duration d = absl::Milliseconds(1500); -// double dsec = absl::ToDoubleSeconds(d); // dsec == 1.5 -double ToDoubleNanoseconds(Duration d); -double ToDoubleMicroseconds(Duration d); -double ToDoubleMilliseconds(Duration d); -double ToDoubleSeconds(Duration d); -double ToDoubleMinutes(Duration d); -double ToDoubleHours(Duration d); - -// FromChrono() -// -// Converts any of the pre-defined std::chrono durations to an absl::Duration. -// -// Example: -// -// std::chrono::milliseconds ms(123); -// absl::Duration d = absl::FromChrono(ms); -constexpr Duration FromChrono(const std::chrono::nanoseconds& d); -constexpr Duration FromChrono(const std::chrono::microseconds& d); -constexpr Duration FromChrono(const std::chrono::milliseconds& d); -constexpr Duration FromChrono(const std::chrono::seconds& d); -constexpr Duration FromChrono(const std::chrono::minutes& d); -constexpr Duration FromChrono(const std::chrono::hours& d); - -// ToChronoNanoseconds() -// ToChronoMicroseconds() -// ToChronoMilliseconds() -// ToChronoSeconds() -// ToChronoMinutes() -// ToChronoHours() -// -// Converts an absl::Duration to any of the pre-defined std::chrono durations. -// If overflow would occur, the returned value will saturate at the min/max -// chrono duration value instead. -// -// Example: -// -// absl::Duration d = absl::Microseconds(123); -// auto x = absl::ToChronoMicroseconds(d); -// auto y = absl::ToChronoNanoseconds(d); // x == y -// auto z = absl::ToChronoSeconds(absl::InfiniteDuration()); -// // z == std::chrono::seconds::max() -std::chrono::nanoseconds ToChronoNanoseconds(Duration d); -std::chrono::microseconds ToChronoMicroseconds(Duration d); -std::chrono::milliseconds ToChronoMilliseconds(Duration d); -std::chrono::seconds ToChronoSeconds(Duration d); -std::chrono::minutes ToChronoMinutes(Duration d); -std::chrono::hours ToChronoHours(Duration d); - -// FormatDuration() -// -// Returns a string representing the duration in the form "72h3m0.5s". -// Returns "inf" or "-inf" for +/- `InfiniteDuration()`. -std::string FormatDuration(Duration d); - -// Output stream operator. -inline std::ostream& operator<<(std::ostream& os, Duration d) { - return os << FormatDuration(d); -} - -// ParseDuration() -// -// Parses a duration string consisting of a possibly signed sequence of -// decimal numbers, each with an optional fractional part and a unit -// 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); - -// Support for flag values of type Duration. Duration flags must be specified -// in a format that is valid input for absl::ParseDuration(). -bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error); -std::string AbslUnparseFlag(Duration d); -ABSL_DEPRECATED("Use AbslParseFlag() instead.") -bool ParseFlag(const std::string& text, Duration* dst, std::string* error); -ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") -std::string UnparseFlag(Duration d); - -// Time -// -// An `absl::Time` represents a specific instant in time. Arithmetic operators -// are provided for naturally expressing time calculations. Instances are -// created using `absl::Now()` and the `absl::From*()` factory functions that -// accept the gamut of other time representations. Formatting and parsing -// functions are provided for conversion to and from strings. `absl::Time` -// should be passed by value rather than const reference. -// -// `absl::Time` assumes there are 60 seconds in a minute, which means the -// underlying time scales must be "smeared" to eliminate leap seconds. -// See https://developers.google.com/time/smear. -// -// Even though `absl::Time` supports a wide range of timestamps, exercise -// caution when using values in the distant past. `absl::Time` uses the -// Proleptic Gregorian calendar, which extends the Gregorian calendar backward -// to dates before its introduction in 1582. -// See https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar -// for more information. Use the ICU calendar classes to convert a date in -// some other calendar (http://userguide.icu-project.org/datetime/calendar). -// -// Similarly, standardized time zones are a reasonably recent innovation, with -// the Greenwich prime meridian being established in 1884. The TZ database -// itself does not profess accurate offsets for timestamps prior to 1970. The -// breakdown of future timestamps is subject to the whim of regional -// governments. -// -// The `absl::Time` class represents an instant in time as a count of clock -// ticks of some granularity (resolution) from some starting point (epoch). -// -// `absl::Time` uses a resolution that is high enough to avoid loss in -// precision, and a range that is wide enough to avoid overflow, when -// converting between tick counts in most Google time scales (i.e., resolution -// of at least one nanosecond, and range +/-100 billion years). Conversions -// between the time scales are performed by truncating (towards negative -// infinity) to the nearest representable point. -// -// Examples: -// -// absl::Time t1 = ...; -// absl::Time t2 = t1 + absl::Minutes(2); -// absl::Duration d = t2 - t1; // == absl::Minutes(2) -// -class Time { - public: - // Value semantics. - - // Returns the Unix epoch. However, those reading your code may not know - // or expect the Unix epoch as the default value, so make your code more - // readable by explicitly initializing all instances before use. - // - // Example: - // absl::Time t = absl::UnixEpoch(); - // absl::Time t = absl::Now(); - // absl::Time t = absl::TimeFromTimeval(tv); - // absl::Time t = absl::InfinitePast(); - constexpr Time() = default; - - // Copyable. - constexpr Time(const Time& t) = default; - Time& operator=(const Time& t) = default; - - // Assignment operators. - Time& operator+=(Duration d) { - rep_ += d; - return *this; - } - Time& operator-=(Duration d) { - rep_ -= d; - return *this; - } - - // Time::Breakdown - // - // The calendar and wall-clock (aka "civil time") components of an - // `absl::Time` in a certain `absl::TimeZone`. This struct is not - // intended to represent an instant in time. So, rather than passing - // a `Time::Breakdown` to a function, pass an `absl::Time` and an - // `absl::TimeZone`. - // - // Deprecated. Use `absl::TimeZone::CivilInfo`. - struct - Breakdown { - 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] - int minute; // minute of hour [0:59] - int second; // second of minute [0:59] - Duration subsecond; // [Seconds(0):Seconds(1)) if finite - int weekday; // 1==Mon, ..., 7=Sun - int yearday; // day of year [1:366] - - // Note: The following fields exist for backward compatibility - // with older APIs. Accessing these fields directly is a sign of - // imprudent logic in the calling code. Modern time-related code - // should only access this data indirectly by way of FormatTime(). - // These fields are undefined for InfiniteFuture() and InfinitePast(). - int offset; // seconds east of UTC - bool is_dst; // is offset non-standard? - const char* zone_abbr; // time-zone abbreviation (e.g., "PST") - }; - - // Time::In() - // - // Returns the breakdown of this instant in the given TimeZone. - // - // Deprecated. Use `absl::TimeZone::At(Time)`. - Breakdown In(TimeZone tz) const; - - template <typename H> - friend H AbslHashValue(H h, Time t) { - return H::combine(std::move(h), t.rep_); - } - - private: - friend constexpr Time time_internal::FromUnixDuration(Duration d); - friend constexpr Duration time_internal::ToUnixDuration(Time t); - friend constexpr bool operator<(Time lhs, Time rhs); - friend constexpr bool operator==(Time lhs, Time rhs); - friend Duration operator-(Time lhs, Time rhs); - friend constexpr Time UniversalEpoch(); - friend constexpr Time InfiniteFuture(); - friend constexpr Time InfinitePast(); - constexpr explicit Time(Duration rep) : rep_(rep) {} - Duration rep_; -}; - -// Relational Operators -constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; } -constexpr bool operator>(Time lhs, Time rhs) { return rhs < lhs; } -constexpr bool operator>=(Time lhs, Time rhs) { return !(lhs < rhs); } -constexpr bool operator<=(Time lhs, Time rhs) { return !(rhs < lhs); } -constexpr bool operator==(Time lhs, Time rhs) { return lhs.rep_ == rhs.rep_; } -constexpr bool operator!=(Time lhs, Time rhs) { return !(lhs == rhs); } - -// Additive Operators -inline Time operator+(Time lhs, Duration rhs) { return lhs += rhs; } -inline Time operator+(Duration lhs, Time rhs) { return rhs += lhs; } -inline Time operator-(Time lhs, Duration rhs) { return lhs -= rhs; } -inline Duration operator-(Time lhs, Time rhs) { return lhs.rep_ - rhs.rep_; } - -// UnixEpoch() -// -// Returns the `absl::Time` representing "1970-01-01 00:00:00.0 +0000". -constexpr Time UnixEpoch() { return Time(); } - -// UniversalEpoch() -// -// Returns the `absl::Time` representing "0001-01-01 00:00:00.0 +0000", the -// epoch of the ICU Universal Time Scale. -constexpr Time UniversalEpoch() { - // 719162 is the number of days from 0001-01-01 to 1970-01-01, - // assuming the Gregorian calendar. - return Time(time_internal::MakeDuration(-24 * 719162 * int64_t{3600}, 0U)); -} - -// InfiniteFuture() -// -// Returns an `absl::Time` that is infinitely far in the future. -constexpr Time InfiniteFuture() { - return Time( - time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U)); -} - -// InfinitePast() -// -// Returns an `absl::Time` that is infinitely far in the past. -constexpr Time InfinitePast() { - return Time( - time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U)); -} - -// FromUnixNanos() -// FromUnixMicros() -// FromUnixMillis() -// FromUnixSeconds() -// FromTimeT() -// FromUDate() -// FromUniversal() -// -// Creates an `absl::Time` from a variety of other representations. -constexpr Time FromUnixNanos(int64_t ns); -constexpr Time FromUnixMicros(int64_t us); -constexpr Time FromUnixMillis(int64_t ms); -constexpr Time FromUnixSeconds(int64_t s); -constexpr Time FromTimeT(time_t t); -Time FromUDate(double udate); -Time FromUniversal(int64_t universal); - -// ToUnixNanos() -// ToUnixMicros() -// ToUnixMillis() -// ToUnixSeconds() -// ToTimeT() -// ToUDate() -// ToUniversal() -// -// Converts an `absl::Time` to a variety of other representations. Note that -// these operations round down toward negative infinity where necessary to -// adjust to the resolution of the result type. Beware of possible time_t -// over/underflow in ToTime{T,val,spec}() on 32-bit platforms. -int64_t ToUnixNanos(Time t); -int64_t ToUnixMicros(Time t); -int64_t ToUnixMillis(Time t); -int64_t ToUnixSeconds(Time t); -time_t ToTimeT(Time t); -double ToUDate(Time t); -int64_t ToUniversal(Time t); - -// DurationFromTimespec() -// DurationFromTimeval() -// ToTimespec() -// ToTimeval() -// TimeFromTimespec() -// TimeFromTimeval() -// ToTimespec() -// ToTimeval() -// -// Some APIs use a timespec or a timeval as a Duration (e.g., nanosleep(2) -// and select(2)), while others use them as a Time (e.g. clock_gettime(2) -// and gettimeofday(2)), so conversion functions are provided for both cases. -// The "to timespec/val" direction is easily handled via overloading, but -// for "from timespec/val" the desired type is part of the function name. -Duration DurationFromTimespec(timespec ts); -Duration DurationFromTimeval(timeval tv); -timespec ToTimespec(Duration d); -timeval ToTimeval(Duration d); -Time TimeFromTimespec(timespec ts); -Time TimeFromTimeval(timeval tv); -timespec ToTimespec(Time t); -timeval ToTimeval(Time t); - -// FromChrono() -// -// Converts a std::chrono::system_clock::time_point to an absl::Time. -// -// Example: -// -// auto tp = std::chrono::system_clock::from_time_t(123); -// absl::Time t = absl::FromChrono(tp); -// // t == absl::FromTimeT(123) -Time FromChrono(const std::chrono::system_clock::time_point& tp); - -// ToChronoTime() -// -// Converts an absl::Time to a std::chrono::system_clock::time_point. If -// overflow would occur, the returned value will saturate at the min/max time -// point value instead. -// -// Example: -// -// absl::Time t = absl::FromTimeT(123); -// auto tp = absl::ToChronoTime(t); -// // tp == std::chrono::system_clock::from_time_t(123); -std::chrono::system_clock::time_point ToChronoTime(Time); - -// 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 -// -// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required. -// -// Additionally, if you'd like to specify a time as a count of -// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag -// and add that duration to absl::UnixEpoch() to get an absl::Time. -bool AbslParseFlag(absl::string_view text, Time* t, std::string* error); -std::string AbslUnparseFlag(Time t); -ABSL_DEPRECATED("Use AbslParseFlag() instead.") -bool ParseFlag(const std::string& text, Time* t, std::string* error); -ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") -std::string UnparseFlag(Time t); - -// TimeZone -// -// The `absl::TimeZone` is an opaque, small, value-type class representing a -// geo-political region within which particular rules are used for converting -// between absolute and civil times (see https://git.io/v59Ly). `absl::TimeZone` -// values are named using the TZ identifiers from the IANA Time Zone Database, -// such as "America/Los_Angeles" or "Australia/Sydney". `absl::TimeZone` values -// are created from factory functions such as `absl::LoadTimeZone()`. Note: -// strings like "PST" and "EDT" are not valid TZ identifiers. Prefer to pass by -// value rather than const reference. -// -// For more on the fundamental concepts of time zones, absolute times, and civil -// times, see https://github.com/google/cctz#fundamental-concepts -// -// Examples: -// -// absl::TimeZone utc = absl::UTCTimeZone(); -// absl::TimeZone pst = absl::FixedTimeZone(-8 * 60 * 60); -// absl::TimeZone loc = absl::LocalTimeZone(); -// absl::TimeZone lax; -// if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) { -// // handle error case -// } -// -// See also: -// - https://github.com/google/cctz -// - https://www.iana.org/time-zones -// - https://en.wikipedia.org/wiki/Zoneinfo -class TimeZone { - public: - explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {} - TimeZone() = default; // UTC, but prefer UTCTimeZone() to be explicit. - - // Copyable. - TimeZone(const TimeZone&) = default; - TimeZone& operator=(const TimeZone&) = default; - - explicit operator time_internal::cctz::time_zone() const { return cz_; } - - std::string name() const { return cz_.name(); } - - // TimeZone::CivilInfo - // - // Information about the civil time corresponding to an absolute time. - // This struct is not intended to represent an instant in time. So, rather - // than passing a `TimeZone::CivilInfo` to a function, pass an `absl::Time` - // and an `absl::TimeZone`. - struct CivilInfo { - CivilSecond cs; - Duration subsecond; - - // Note: The following fields exist for backward compatibility - // with older APIs. Accessing these fields directly is a sign of - // imprudent logic in the calling code. Modern time-related code - // should only access this data indirectly by way of FormatTime(). - // These fields are undefined for InfiniteFuture() and InfinitePast(). - int offset; // seconds east of UTC - bool is_dst; // is offset non-standard? - const char* zone_abbr; // time-zone abbreviation (e.g., "PST") - }; - - // TimeZone::At(Time) - // - // Returns the civil time for this TimeZone at a certain `absl::Time`. - // If the input time is infinite, the output civil second will be set to - // CivilSecond::max() or min(), and the subsecond will be infinite. - // - // Example: - // - // const auto epoch = lax.At(absl::UnixEpoch()); - // // epoch.cs == 1969-12-31 16:00:00 - // // epoch.subsecond == absl::ZeroDuration() - // // epoch.offset == -28800 - // // epoch.is_dst == false - // // epoch.abbr == "PST" - CivilInfo At(Time t) const; - - // TimeZone::TimeInfo - // - // Information about the absolute times corresponding to a civil time. - // (Subseconds must be handled separately.) - // - // It is possible for a caller to pass a civil-time value that does - // not represent an actual or unique instant in time (due to a shift - // in UTC offset in the TimeZone, which results in a discontinuity in - // the civil-time components). For example, a daylight-saving-time - // transition skips or repeats civil times---in the United States, - // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15 - // occurred twice---so requests for such times are not well-defined. - // To account for these possibilities, `absl::TimeZone::TimeInfo` is - // richer than just a single `absl::Time`. - struct TimeInfo { - enum CivilKind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist (pre >= trans > post) - REPEATED, // the civil time was ambiguous (pre < trans <= post) - } kind; - Time pre; // time calculated using the pre-transition offset - Time trans; // when the civil-time discontinuity occurred - Time post; // time calculated using the post-transition offset - }; - - // TimeZone::At(CivilSecond) - // - // Returns an `absl::TimeInfo` containing the absolute time(s) for this - // TimeZone at an `absl::CivilSecond`. When the civil time is skipped or - // repeated, returns times calculated using the pre-transition and post- - // transition UTC offsets, plus the transition time itself. - // - // Examples: - // - // // A unique civil time - // const auto jan01 = lax.At(absl::CivilSecond(2011, 1, 1, 0, 0, 0)); - // // jan01.kind == TimeZone::TimeInfo::UNIQUE - // // jan01.pre is 2011-01-01 00:00:00 -0800 - // // jan01.trans is 2011-01-01 00:00:00 -0800 - // // jan01.post is 2011-01-01 00:00:00 -0800 - // - // // A Spring DST transition, when there is a gap in civil time - // const auto mar13 = lax.At(absl::CivilSecond(2011, 3, 13, 2, 15, 0)); - // // mar13.kind == TimeZone::TimeInfo::SKIPPED - // // mar13.pre is 2011-03-13 03:15:00 -0700 - // // mar13.trans is 2011-03-13 03:00:00 -0700 - // // mar13.post is 2011-03-13 01:15:00 -0800 - // - // // A Fall DST transition, when civil times are repeated - // const auto nov06 = lax.At(absl::CivilSecond(2011, 11, 6, 1, 15, 0)); - // // nov06.kind == TimeZone::TimeInfo::REPEATED - // // nov06.pre is 2011-11-06 01:15:00 -0700 - // // nov06.trans is 2011-11-06 01:00:00 -0800 - // // nov06.post is 2011-11-06 01:15:00 -0800 - TimeInfo At(CivilSecond ct) const; - - // TimeZone::NextTransition() - // TimeZone::PrevTransition() - // - // Finds the time of the next/previous offset change in this time zone. - // - // By definition, `NextTransition(t, &trans)` returns false when `t` is - // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false - // when `t` is `InfinitePast()`. If the zone has no transitions, the - // result will also be false no matter what the argument. - // - // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)` - // returns true and sets `trans` to the first recorded transition. Chains - // of calls to `NextTransition()/PrevTransition()` will eventually return - // false, but it is unspecified exactly when `NextTransition(t, &trans)` - // jumps to false, or what time is set by `PrevTransition(t, &trans)` for - // a very distant `t`. - // - // Note: Enumeration of time-zone transitions is for informational purposes - // only. Modern time-related code should not care about when offset changes - // occur. - // - // Example: - // absl::TimeZone nyc; - // if (!absl::LoadTimeZone("America/New_York", &nyc)) { ... } - // const auto now = absl::Now(); - // auto t = absl::InfinitePast(); - // absl::TimeZone::CivilTransition trans; - // while (t <= now && nyc.NextTransition(t, &trans)) { - // // transition: trans.from -> trans.to - // t = nyc.At(trans.to).trans; - // } - struct CivilTransition { - CivilSecond from; // the civil time we jump from - CivilSecond to; // the civil time we jump to - }; - bool NextTransition(Time t, CivilTransition* trans) const; - bool PrevTransition(Time t, CivilTransition* trans) const; - - template <typename H> - friend H AbslHashValue(H h, TimeZone tz) { - return H::combine(std::move(h), tz.cz_); - } - - private: - friend bool operator==(TimeZone a, TimeZone b) { return a.cz_ == b.cz_; } - friend bool operator!=(TimeZone a, TimeZone b) { return a.cz_ != b.cz_; } - friend std::ostream& operator<<(std::ostream& os, TimeZone tz) { - return os << tz.name(); - } - - time_internal::cctz::time_zone cz_; -}; - -// LoadTimeZone() -// -// 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) { - 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); - *tz = TimeZone(cz); - return b; -} - -// FixedTimeZone() -// -// Returns a TimeZone that is a fixed offset (seconds east) from UTC. -// Note: If the absolute value of the offset is greater than 24 hours -// you'll get UTC (i.e., no offset) instead. -inline TimeZone FixedTimeZone(int seconds) { - return TimeZone( - time_internal::cctz::fixed_time_zone(std::chrono::seconds(seconds))); -} - -// UTCTimeZone() -// -// Convenience method returning the UTC time zone. -inline TimeZone UTCTimeZone() { - return TimeZone(time_internal::cctz::utc_time_zone()); -} - -// LocalTimeZone() -// -// Convenience method returning the local time zone, or UTC if there is -// no configured local zone. Warning: Be wary of using LocalTimeZone(), -// and particularly so in a server process, as the zone configured for the -// local machine should be irrelevant. Prefer an explicit zone name. -inline TimeZone LocalTimeZone() { - return TimeZone(time_internal::cctz::local_time_zone()); -} - -// ToCivilSecond() -// ToCivilMinute() -// ToCivilHour() -// ToCivilDay() -// ToCivilMonth() -// ToCivilYear() -// -// Helpers for TimeZone::At(Time) to return particularly aligned civil times. -// -// Example: -// -// absl::Time t = ...; -// absl::TimeZone tz = ...; -// const auto cd = absl::ToCivilDay(t, tz); -inline CivilSecond ToCivilSecond(Time t, TimeZone tz) { - return tz.At(t).cs; // already a CivilSecond -} -inline CivilMinute ToCivilMinute(Time t, TimeZone tz) { - return CivilMinute(tz.At(t).cs); -} -inline CivilHour ToCivilHour(Time t, TimeZone tz) { - return CivilHour(tz.At(t).cs); -} -inline CivilDay ToCivilDay(Time t, TimeZone tz) { - return CivilDay(tz.At(t).cs); -} -inline CivilMonth ToCivilMonth(Time t, TimeZone tz) { - return CivilMonth(tz.At(t).cs); -} -inline CivilYear ToCivilYear(Time t, TimeZone tz) { - return CivilYear(tz.At(t).cs); -} - -// FromCivil() -// -// Helper for TimeZone::At(CivilSecond) that provides "order-preserving -// semantics." If the civil time maps to a unique time, that time is -// returned. If the civil time is repeated in the given time zone, the -// time using the pre-transition offset is returned. Otherwise, the -// civil time is skipped in the given time zone, and the transition time -// is returned. This means that for any two civil times, ct1 and ct2, -// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case -// being when two non-existent civil times map to the same transition time. -// -// Note: Accepts civil times of any alignment. -inline Time FromCivil(CivilSecond ct, TimeZone tz) { - const auto ti = tz.At(ct); - if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans; - return ti.pre; -} - -// TimeConversion -// -// An `absl::TimeConversion` represents the conversion of year, month, day, -// hour, minute, and second values (i.e., a civil time), in a particular -// `absl::TimeZone`, to a time instant (an absolute time), as returned by -// `absl::ConvertDateTime()`. Legacy version of `absl::TimeZone::TimeInfo`. -// -// Deprecated. Use `absl::TimeZone::TimeInfo`. -struct - TimeConversion { - Time pre; // time calculated using the pre-transition offset - Time trans; // when the civil-time discontinuity occurred - Time post; // time calculated using the post-transition offset - - enum Kind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist - REPEATED, // the civil time was ambiguous - }; - Kind kind; - - bool normalized; // input values were outside their valid ranges -}; - -// ConvertDateTime() -// -// Legacy version of `absl::TimeZone::At(absl::CivilSecond)` that takes -// the civil time as six, separate values (YMDHMS). -// -// The input month, day, hour, minute, and second values can be outside -// of their valid ranges, in which case they will be "normalized" during -// the conversion. -// -// Example: -// -// // "October 32" normalizes to "November 1". -// absl::TimeConversion tc = -// absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax); -// // tc.kind == TimeConversion::UNIQUE && tc.normalized == true -// // absl::ToCivilDay(tc.pre, tz).month() == 11 -// // absl::ToCivilDay(tc.pre, tz).day() == 1 -// -// Deprecated. Use `absl::TimeZone::At(CivilSecond)`. -TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz); - -// FromDateTime() -// -// A convenience wrapper for `absl::ConvertDateTime()` that simply returns -// the "pre" `absl::Time`. That is, the unique result, or the instant that -// is correct using the pre-transition offset (as if the transition never -// happened). -// -// Example: -// -// absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax); -// // t = 2017-09-26 09:30:00 -0700 -// -// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the -// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil -// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`. -inline Time FromDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz) { - return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre; -} - -// FromTM() -// -// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and -// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3) -// for a description of the expected values of the tm fields. If the indicated -// time instant is not unique (see `absl::TimeZone::At(absl::CivilSecond)` -// above), the `tm_isdst` field is consulted to select the desired instant -// (`tm_isdst` > 0 means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0 -// means use the post-transition offset). -Time FromTM(const struct tm& tm, TimeZone tz); - -// ToTM() -// -// Converts the given `absl::Time` to a struct tm using the given time zone. -// See ctime(3) for a description of the values of the tm fields. -struct tm ToTM(Time t, TimeZone tz); - -// RFC3339_full -// RFC3339_sec -// -// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings, -// with trailing zeros trimmed or with fractional seconds omitted altogether. -// -// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and -// 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 - -// 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 - -// FormatTime() -// -// Formats the given `absl::Time` in the `absl::TimeZone` according to the -// provided format string. Uses strftime()-like formatting options, with -// the following extensions: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %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'. -// -// Note that %Y produces as many characters as it takes to fully render the -// year. A year outside of [-999:9999] when formatted with %E4Y will produce -// more than four characters, just like %Y. -// -// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z) -// so that the result uniquely identifies a time instant. -// -// Example: -// -// absl::CivilSecond cs(2013, 1, 2, 3, 4, 5); -// absl::Time t = absl::FromCivil(cs, lax); -// std::string f = absl::FormatTime("%H:%M:%S", t, lax); // "03:04:05" -// f = absl::FormatTime("%H:%M:%E3S", t, lax); // "03:04:05.000" -// -// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned -// string will be exactly "infinite-future". If the given `absl::Time` is -// `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); - -// Convenience functions that format the given time using the RFC3339_full -// format. The first overload uses the provided TimeZone, while the second -// uses LocalTimeZone(). -std::string FormatTime(Time t, TimeZone tz); -std::string FormatTime(Time t); - -// Output stream operator. -inline std::ostream& operator<<(std::ostream& os, Time t) { - return os << FormatTime(t); -} - -// ParseTime() -// -// Parses an input string according to the provided format string and -// 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'. -// -// %Y consumes as many numeric characters as it can, so the matching data -// should always be terminated with a non-numeric. %E4Y always consumes -// exactly four characters, including any sign. -// -// Unspecified fields are taken from the default date and time of ... -// -// "1970-01-01 00:00:00.0 +0000" -// -// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time -// that represents "1970-01-01 15:45:00.0 +0000". -// -// Note that since ParseTime() returns time instants, it makes the most sense -// to parse fully-specified date/time strings that include a UTC offset (%z, -// %Ez, or %E*z). -// -// Note also that `absl::ParseTime()` only heeds the fields year, month, day, -// hour, minute, (fractional) second, and UTC offset. Other fields, like -// weekday (%a or %A), while parsed for syntactic validity, are ignored -// in the conversion. -// -// Date and time fields that are out-of-range will be treated as errors -// rather than normalizing them like `absl::CivilSecond` does. For example, -// it is an error to parse the date "Oct 32, 2013" because 32 is out of range. -// -// A leap second of ":60" is normalized to ":00" of the following minute -// with fractional seconds discarded. The following table shows how the -// given seconds and subseconds will be parsed: -// -// "59.x" -> 59.x // exact -// "60.x" -> 00.0 // normalized -// "00.x" -> 00.x // exact -// -// Errors are indicated by returning false and assigning an error message -// to the "err" out param if it is non-null. -// -// Note: If the input string is exactly "infinite-future", the returned -// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned. -// 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, - std::string* err); - -// Like ParseTime() above, but if the format string does not contain a UTC -// offset specification (%z/%Ez/%E*z) then the input is interpreted in the -// given TimeZone. This means that the input, by itself, does not identify a -// unique instant. Being time-zone dependent, it also admits the possibility -// 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, - Time* time, std::string* err); - -// ============================================================================ -// Implementation Details Follow -// ============================================================================ - -namespace time_internal { - -// Creates a Duration with a given representation. -// REQUIRES: hi,lo is a valid representation of a Duration as specified -// in time/duration.cc. -constexpr Duration MakeDuration(int64_t hi, uint32_t lo = 0) { - return Duration(hi, lo); -} - -constexpr Duration MakeDuration(int64_t hi, int64_t lo) { - return MakeDuration(hi, static_cast<uint32_t>(lo)); -} - -// Make a Duration value from a floating-point number, as long as that number -// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as -// it's positive and can be converted to int64_t without risk of UB. -inline Duration MakePosDoubleDuration(double n) { - const int64_t int_secs = static_cast<int64_t>(n); - const uint32_t ticks = static_cast<uint32_t>( - (n - static_cast<double>(int_secs)) * kTicksPerSecond + 0.5); - return ticks < kTicksPerSecond - ? MakeDuration(int_secs, ticks) - : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); -} - -// Creates a normalized Duration from an almost-normalized (sec,ticks) -// pair. sec may be positive or negative. ticks must be in the range -// -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it -// will be normalized to a positive value in the resulting Duration. -constexpr Duration MakeNormalizedDuration(int64_t sec, int64_t ticks) { - return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond) - : MakeDuration(sec, ticks); -} - -// Provide access to the Duration representation. -constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; } -constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; } - -// Returns true iff d is positive or negative infinity. -constexpr bool IsInfiniteDuration(Duration d) { return GetRepLo(d) == ~0U; } - -// Returns an infinite Duration with the opposite sign. -// REQUIRES: IsInfiniteDuration(d) -constexpr Duration OppositeInfinity(Duration d) { - return GetRepHi(d) < 0 - ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U) - : MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U); -} - -// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow. -constexpr int64_t NegateAndSubtractOne(int64_t n) { - // Note: Good compilers will optimize this expression to ~n when using - // a two's-complement representation (which is required for int64_t). - return (n < 0) ? -(n + 1) : (-n) - 1; -} - -// Map between a Time and a Duration since the Unix epoch. Note that these -// functions depend on the above mentioned choice of the Unix epoch for the -// Time representation (and both need to be Time friends). Without this -// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively. -constexpr Time FromUnixDuration(Duration d) { return Time(d); } -constexpr Duration ToUnixDuration(Time t) { return t.rep_; } - -template <std::intmax_t N> -constexpr Duration FromInt64(int64_t v, std::ratio<1, N>) { - static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio"); - // Subsecond ratios cannot overflow. - return MakeNormalizedDuration( - v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N); -} -constexpr Duration FromInt64(int64_t v, std::ratio<60>) { - return (v <= (std::numeric_limits<int64_t>::max)() / 60 && - v >= (std::numeric_limits<int64_t>::min)() / 60) - ? MakeDuration(v * 60) - : v > 0 ? InfiniteDuration() : -InfiniteDuration(); -} -constexpr Duration FromInt64(int64_t v, std::ratio<3600>) { - return (v <= (std::numeric_limits<int64_t>::max)() / 3600 && - v >= (std::numeric_limits<int64_t>::min)() / 3600) - ? MakeDuration(v * 3600) - : v > 0 ? InfiniteDuration() : -InfiniteDuration(); -} - -// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is -// valid. That is, if a T can be assigned to an int64_t without narrowing. -template <typename T> -constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) { - return true; -} -template <typename T> -constexpr auto IsValidRep64(char) -> bool { - return false; -} - -// Converts a std::chrono::duration to an absl::Duration. -template <typename Rep, typename Period> -constexpr Duration FromChrono(const std::chrono::duration<Rep, Period>& d) { - static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); - return FromInt64(int64_t{d.count()}, Period{}); -} - -template <typename Ratio> -int64_t ToInt64(Duration d, Ratio) { - // Note: This may be used on MSVC, which may have a system_clock period of - // std::ratio<1, 10 * 1000 * 1000> - return ToInt64Seconds(d * Ratio::den / Ratio::num); -} -// Fastpath implementations for the 6 common duration units. -inline int64_t ToInt64(Duration d, std::nano) { - return ToInt64Nanoseconds(d); -} -inline int64_t ToInt64(Duration d, std::micro) { - return ToInt64Microseconds(d); -} -inline int64_t ToInt64(Duration d, std::milli) { - return ToInt64Milliseconds(d); -} -inline int64_t ToInt64(Duration d, std::ratio<1>) { - return ToInt64Seconds(d); -} -inline int64_t ToInt64(Duration d, std::ratio<60>) { - return ToInt64Minutes(d); -} -inline int64_t ToInt64(Duration d, std::ratio<3600>) { - return ToInt64Hours(d); -} - -// Converts an absl::Duration to a chrono duration of type T. -template <typename T> -T ToChronoDuration(Duration d) { - using Rep = typename T::rep; - using Period = typename T::period; - static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); - if (time_internal::IsInfiniteDuration(d)) - return d < ZeroDuration() ? (T::min)() : (T::max)(); - const auto v = ToInt64(d, Period{}); - if (v > (std::numeric_limits<Rep>::max)()) return (T::max)(); - if (v < (std::numeric_limits<Rep>::min)()) return (T::min)(); - return T{v}; -} - -} // 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); -} - -constexpr bool operator==(Duration lhs, Duration rhs) { - return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && - time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs); -} - -constexpr Duration operator-(Duration d) { - // This is a little interesting because of the special cases. - // - // If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're - // dealing with an integral number of seconds, and the only special case is - // the maximum negative finite duration, which can't be negated. - // - // Infinities stay infinite, and just change direction. - // - // Finally we're in the case where rep_lo_ is non-zero, and we can borrow - // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1 - // is safe). - return time_internal::GetRepLo(d) == 0 - ? time_internal::GetRepHi(d) == - (std::numeric_limits<int64_t>::min)() - ? InfiniteDuration() - : time_internal::MakeDuration(-time_internal::GetRepHi(d)) - : time_internal::IsInfiniteDuration(d) - ? time_internal::OppositeInfinity(d) - : time_internal::MakeDuration( - time_internal::NegateAndSubtractOne( - time_internal::GetRepHi(d)), - time_internal::kTicksPerSecond - - time_internal::GetRepLo(d)); -} - -constexpr Duration InfiniteDuration() { - return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), - ~0U); -} - -constexpr Duration FromChrono(const std::chrono::nanoseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::microseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::milliseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::seconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::minutes& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::hours& d) { - return time_internal::FromChrono(d); -} - -constexpr Time FromUnixNanos(int64_t ns) { - return time_internal::FromUnixDuration(Nanoseconds(ns)); -} - -constexpr Time FromUnixMicros(int64_t us) { - return time_internal::FromUnixDuration(Microseconds(us)); -} - -constexpr Time FromUnixMillis(int64_t ms) { - return time_internal::FromUnixDuration(Milliseconds(ms)); -} - -constexpr Time FromUnixSeconds(int64_t s) { - return time_internal::FromUnixDuration(Seconds(s)); -} - -constexpr Time FromTimeT(time_t t) { - return time_internal::FromUnixDuration(Seconds(t)); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TIME_TIME_H_ diff --git a/third_party/abseil_cpp/absl/time/time_benchmark.cc b/third_party/abseil_cpp/absl/time/time_benchmark.cc deleted file mode 100644 index 99e6279984e6..000000000000 --- a/third_party/abseil_cpp/absl/time/time_benchmark.cc +++ /dev/null @@ -1,316 +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/time/time.h" - -#if !defined(_WIN32) -#include <sys/time.h> -#endif // _WIN32 -#include <algorithm> -#include <cmath> -#include <cstddef> -#include <cstring> -#include <ctime> -#include <memory> -#include <string> - -#include "absl/time/clock.h" -#include "absl/time/internal/test_util.h" -#include "benchmark/benchmark.h" - -namespace { - -// -// Addition/Subtraction of a duration -// - -void BM_Time_Arithmetic(benchmark::State& state) { - const absl::Duration nano = absl::Nanoseconds(1); - const absl::Duration sec = absl::Seconds(1); - absl::Time t = absl::UnixEpoch(); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(t += nano); - benchmark::DoNotOptimize(t -= sec); - } -} -BENCHMARK(BM_Time_Arithmetic); - -// -// Time difference -// - -void BM_Time_Difference(benchmark::State& state) { - absl::Time start = absl::Now(); - absl::Time end = start + absl::Nanoseconds(1); - absl::Duration diff; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(diff += end - start); - } -} -BENCHMARK(BM_Time_Difference); - -// -// ToDateTime -// -// In each "ToDateTime" benchmark we switch between two instants -// separated by at least one transition in order to defeat any -// internal caching of previous results (e.g., see local_time_hint_). -// -// The "UTC" variants use UTC instead of the Google/local time zone. -// - -void BM_Time_ToDateTime_Absl(benchmark::State& state) { - const absl::TimeZone tz = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - absl::Time t = absl::FromUnixSeconds(1384569027); - absl::Time t2 = absl::FromUnixSeconds(1418962578); - while (state.KeepRunning()) { - std::swap(t, t2); - t += absl::Seconds(1); - benchmark::DoNotOptimize(t.In(tz)); - } -} -BENCHMARK(BM_Time_ToDateTime_Absl); - -void BM_Time_ToDateTime_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - time_t t = 1384569027; - time_t t2 = 1418962578; - while (state.KeepRunning()) { - std::swap(t, t2); - t += 1; - struct tm tm; -#if !defined(_WIN32) - benchmark::DoNotOptimize(localtime_r(&t, &tm)); -#else // _WIN32 - benchmark::DoNotOptimize(localtime_s(&tm, &t)); -#endif // _WIN32 - } -} -BENCHMARK(BM_Time_ToDateTime_Libc); - -void BM_Time_ToDateTimeUTC_Absl(benchmark::State& state) { - const absl::TimeZone tz = absl::UTCTimeZone(); - absl::Time t = absl::FromUnixSeconds(1384569027); - while (state.KeepRunning()) { - t += absl::Seconds(1); - benchmark::DoNotOptimize(t.In(tz)); - } -} -BENCHMARK(BM_Time_ToDateTimeUTC_Absl); - -void BM_Time_ToDateTimeUTC_Libc(benchmark::State& state) { - time_t t = 1384569027; - while (state.KeepRunning()) { - t += 1; - struct tm tm; -#if !defined(_WIN32) - benchmark::DoNotOptimize(gmtime_r(&t, &tm)); -#else // _WIN32 - benchmark::DoNotOptimize(gmtime_s(&tm, &t)); -#endif // _WIN32 - } -} -BENCHMARK(BM_Time_ToDateTimeUTC_Libc); - -// -// FromUnixMicros -// - -void BM_Time_FromUnixMicros(benchmark::State& state) { - int i = 0; - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::FromUnixMicros(i)); - ++i; - } -} -BENCHMARK(BM_Time_FromUnixMicros); - -void BM_Time_ToUnixNanos(benchmark::State& state) { - const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(ToUnixNanos(t)); - } -} -BENCHMARK(BM_Time_ToUnixNanos); - -void BM_Time_ToUnixMicros(benchmark::State& state) { - const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(ToUnixMicros(t)); - } -} -BENCHMARK(BM_Time_ToUnixMicros); - -void BM_Time_ToUnixMillis(benchmark::State& state) { - const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(ToUnixMillis(t)); - } -} -BENCHMARK(BM_Time_ToUnixMillis); - -void BM_Time_ToUnixSeconds(benchmark::State& state) { - const absl::Time t = absl::UnixEpoch() + absl::Seconds(123); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToUnixSeconds(t)); - } -} -BENCHMARK(BM_Time_ToUnixSeconds); - -// -// FromCivil -// -// In each "FromCivil" benchmark we switch between two YMDhms values -// separated by at least one transition in order to defeat any internal -// caching of previous results (e.g., see time_local_hint_). -// -// The "UTC" variants use UTC instead of the Google/local time zone. -// The "Day0" variants require normalization of the day of month. -// - -void BM_Time_FromCivil_Absl(benchmark::State& state) { - const absl::TimeZone tz = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - int i = 0; - while (state.KeepRunning()) { - if ((i & 1) == 0) { - absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz); - } else { - absl::FromCivil(absl::CivilSecond(2013, 11, 15, 18, 30, 27), tz); - } - ++i; - } -} -BENCHMARK(BM_Time_FromCivil_Absl); - -void BM_Time_FromCivil_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - int i = 0; - while (state.KeepRunning()) { - struct tm tm; - if ((i & 1) == 0) { - tm.tm_year = 2014 - 1900; - tm.tm_mon = 12 - 1; - tm.tm_mday = 18; - tm.tm_hour = 20; - tm.tm_min = 16; - tm.tm_sec = 18; - } else { - tm.tm_year = 2013 - 1900; - tm.tm_mon = 11 - 1; - tm.tm_mday = 15; - tm.tm_hour = 18; - tm.tm_min = 30; - tm.tm_sec = 27; - } - tm.tm_isdst = -1; - mktime(&tm); - ++i; - } -} -BENCHMARK(BM_Time_FromCivil_Libc); - -void BM_Time_FromCivilUTC_Absl(benchmark::State& state) { - const absl::TimeZone tz = absl::UTCTimeZone(); - while (state.KeepRunning()) { - absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz); - } -} -BENCHMARK(BM_Time_FromCivilUTC_Absl); - -void BM_Time_FromCivilDay0_Absl(benchmark::State& state) { - const absl::TimeZone tz = - absl::time_internal::LoadTimeZone("America/Los_Angeles"); - int i = 0; - while (state.KeepRunning()) { - if ((i & 1) == 0) { - absl::FromCivil(absl::CivilSecond(2014, 12, 0, 20, 16, 18), tz); - } else { - absl::FromCivil(absl::CivilSecond(2013, 11, 0, 18, 30, 27), tz); - } - ++i; - } -} -BENCHMARK(BM_Time_FromCivilDay0_Absl); - -void BM_Time_FromCivilDay0_Libc(benchmark::State& state) { - // No timezone support, so just use localtime. - int i = 0; - while (state.KeepRunning()) { - struct tm tm; - if ((i & 1) == 0) { - tm.tm_year = 2014 - 1900; - tm.tm_mon = 12 - 1; - tm.tm_mday = 0; - tm.tm_hour = 20; - tm.tm_min = 16; - tm.tm_sec = 18; - } else { - tm.tm_year = 2013 - 1900; - tm.tm_mon = 11 - 1; - tm.tm_mday = 0; - tm.tm_hour = 18; - tm.tm_min = 30; - tm.tm_sec = 27; - } - tm.tm_isdst = -1; - mktime(&tm); - ++i; - } -} -BENCHMARK(BM_Time_FromCivilDay0_Libc); - -// -// To/FromTimespec -// - -void BM_Time_ToTimespec(benchmark::State& state) { - absl::Time now = absl::Now(); - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::ToTimespec(now)); - } -} -BENCHMARK(BM_Time_ToTimespec); - -void BM_Time_FromTimespec(benchmark::State& state) { - timespec ts = absl::ToTimespec(absl::Now()); - while (state.KeepRunning()) { - if (++ts.tv_nsec == 1000 * 1000 * 1000) { - ++ts.tv_sec; - ts.tv_nsec = 0; - } - benchmark::DoNotOptimize(absl::TimeFromTimespec(ts)); - } -} -BENCHMARK(BM_Time_FromTimespec); - -// -// Comparison with InfiniteFuture/Past -// - -void BM_Time_InfiniteFuture(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::InfiniteFuture()); - } -} -BENCHMARK(BM_Time_InfiniteFuture); - -void BM_Time_InfinitePast(benchmark::State& state) { - while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::InfinitePast()); - } -} -BENCHMARK(BM_Time_InfinitePast); - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/time_test.cc b/third_party/abseil_cpp/absl/time/time_test.cc deleted file mode 100644 index cde9423feb1a..000000000000 --- a/third_party/abseil_cpp/absl/time/time_test.cc +++ /dev/null @@ -1,1280 +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/time/time.h" - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <chrono> // NOLINT(build/c++11) -#include <cstring> -#include <ctime> -#include <iomanip> -#include <limits> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/numeric/int128.h" -#include "absl/time/clock.h" -#include "absl/time/internal/test_util.h" - -namespace { - -#if defined(GTEST_USES_SIMPLE_RE) && GTEST_USES_SIMPLE_RE -const char kZoneAbbrRE[] = ".*"; // just punt -#else -const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?"; -#endif - -// This helper is a macro so that failed expectations show up with the -// correct line numbers. -#define EXPECT_CIVIL_INFO(ci, y, m, d, h, min, s, off, isdst) \ - do { \ - EXPECT_EQ(y, ci.cs.year()); \ - EXPECT_EQ(m, ci.cs.month()); \ - EXPECT_EQ(d, ci.cs.day()); \ - EXPECT_EQ(h, ci.cs.hour()); \ - EXPECT_EQ(min, ci.cs.minute()); \ - EXPECT_EQ(s, ci.cs.second()); \ - EXPECT_EQ(off, ci.offset); \ - EXPECT_EQ(isdst, ci.is_dst); \ - EXPECT_THAT(ci.zone_abbr, testing::MatchesRegex(kZoneAbbrRE)); \ - } while (0) - -// A gMock matcher to match timespec values. Use this matcher like: -// 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; - *result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} "; - *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}"; - return false; -} - -// A gMock matcher to match timeval values. Use this matcher like: -// 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; - *result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} "; - *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}"; - return false; -} - -TEST(Time, ConstExpr) { - constexpr absl::Time t0 = absl::UnixEpoch(); - static_assert(t0 == absl::Time(), "UnixEpoch"); - constexpr absl::Time t1 = absl::InfiniteFuture(); - static_assert(t1 != absl::Time(), "InfiniteFuture"); - constexpr absl::Time t2 = absl::InfinitePast(); - static_assert(t2 != absl::Time(), "InfinitePast"); - constexpr absl::Time t3 = absl::FromUnixNanos(0); - static_assert(t3 == absl::Time(), "FromUnixNanos"); - constexpr absl::Time t4 = absl::FromUnixMicros(0); - static_assert(t4 == absl::Time(), "FromUnixMicros"); - constexpr absl::Time t5 = absl::FromUnixMillis(0); - static_assert(t5 == absl::Time(), "FromUnixMillis"); - constexpr absl::Time t6 = absl::FromUnixSeconds(0); - static_assert(t6 == absl::Time(), "FromUnixSeconds"); - constexpr absl::Time t7 = absl::FromTimeT(0); - static_assert(t7 == absl::Time(), "FromTimeT"); -} - -TEST(Time, ValueSemantics) { - absl::Time a; // Default construction - absl::Time b = a; // Copy construction - EXPECT_EQ(a, b); - absl::Time c(a); // Copy construction (again) - EXPECT_EQ(a, b); - EXPECT_EQ(a, c); - EXPECT_EQ(b, c); - b = c; // Assignment - EXPECT_EQ(a, b); - EXPECT_EQ(a, c); - EXPECT_EQ(b, c); -} - -TEST(Time, UnixEpoch) { - const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch()); - EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs); - EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs)); -} - -TEST(Time, Breakdown) { - absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/New_York"); - absl::Time t = absl::UnixEpoch(); - - // The Unix epoch as seen in NYC. - auto ci = tz.At(t); - EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false); - EXPECT_EQ(absl::ZeroDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs)); - - // Just before the epoch. - t -= absl::Nanoseconds(1); - ci = tz.At(t); - EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false); - EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond); - EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs)); - - // Some time later. - t += absl::Hours(24) * 2735; - t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) + - absl::Nanoseconds(9); - ci = tz.At(t); - EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true); - EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1)); - EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ci.cs)); -} - -TEST(Time, AdditiveOperators) { - const absl::Duration d = absl::Nanoseconds(1); - const absl::Time t0; - const absl::Time t1 = t0 + d; - - EXPECT_EQ(d, t1 - t0); - EXPECT_EQ(-d, t0 - t1); - EXPECT_EQ(t0, t1 - d); - - absl::Time t(t0); - EXPECT_EQ(t0, t); - t += d; - EXPECT_EQ(t0 + d, t); - EXPECT_EQ(d, t - t0); - t -= d; - EXPECT_EQ(t0, t); - - // Tests overflow between subseconds and seconds. - t = absl::UnixEpoch(); - t += absl::Milliseconds(500); - EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(500), t); - t += absl::Milliseconds(600); - EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(1100), t); - t -= absl::Milliseconds(600); - EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(500), t); - t -= absl::Milliseconds(500); - EXPECT_EQ(absl::UnixEpoch(), t); -} - -TEST(Time, RelationalOperators) { - constexpr absl::Time t1 = absl::FromUnixNanos(0); - constexpr absl::Time t2 = absl::FromUnixNanos(1); - constexpr absl::Time t3 = absl::FromUnixNanos(2); - - static_assert(absl::Time() == t1, ""); - static_assert(t1 == t1, ""); - static_assert(t2 == t2, ""); - static_assert(t3 == t3, ""); - - static_assert(t1 < t2, ""); - static_assert(t2 < t3, ""); - static_assert(t1 < t3, ""); - - static_assert(t1 <= t1, ""); - static_assert(t1 <= t2, ""); - static_assert(t2 <= t2, ""); - static_assert(t2 <= t3, ""); - static_assert(t3 <= t3, ""); - static_assert(t1 <= t3, ""); - - static_assert(t2 > t1, ""); - static_assert(t3 > t2, ""); - static_assert(t3 > t1, ""); - - static_assert(t2 >= t2, ""); - static_assert(t2 >= t1, ""); - static_assert(t3 >= t3, ""); - static_assert(t3 >= t2, ""); - static_assert(t1 >= t1, ""); - static_assert(t3 >= t1, ""); -} - -TEST(Time, Infinity) { - constexpr absl::Time ifuture = absl::InfiniteFuture(); - constexpr absl::Time ipast = absl::InfinitePast(); - - static_assert(ifuture == ifuture, ""); - static_assert(ipast == ipast, ""); - static_assert(ipast < ifuture, ""); - static_assert(ifuture > ipast, ""); - - // Arithmetic saturates - EXPECT_EQ(ifuture, ifuture + absl::Seconds(1)); - EXPECT_EQ(ifuture, ifuture - absl::Seconds(1)); - EXPECT_EQ(ipast, ipast + absl::Seconds(1)); - EXPECT_EQ(ipast, ipast - absl::Seconds(1)); - - EXPECT_EQ(absl::InfiniteDuration(), ifuture - ifuture); - EXPECT_EQ(absl::InfiniteDuration(), ifuture - ipast); - EXPECT_EQ(-absl::InfiniteDuration(), ipast - ifuture); - EXPECT_EQ(-absl::InfiniteDuration(), ipast - ipast); - - 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) { -#define TEST_FLOOR_CONVERSION(TO, FROM) \ - EXPECT_EQ(1, TO(FROM(1001))); \ - EXPECT_EQ(1, TO(FROM(1000))); \ - EXPECT_EQ(0, TO(FROM(999))); \ - EXPECT_EQ(0, TO(FROM(1))); \ - EXPECT_EQ(0, TO(FROM(0))); \ - EXPECT_EQ(-1, TO(FROM(-1))); \ - EXPECT_EQ(-1, TO(FROM(-999))); \ - EXPECT_EQ(-1, TO(FROM(-1000))); \ - EXPECT_EQ(-2, TO(FROM(-1001))); - - TEST_FLOOR_CONVERSION(absl::ToUnixMicros, absl::FromUnixNanos); - TEST_FLOOR_CONVERSION(absl::ToUnixMillis, absl::FromUnixMicros); - TEST_FLOOR_CONVERSION(absl::ToUnixSeconds, absl::FromUnixMillis); - TEST_FLOOR_CONVERSION(absl::ToTimeT, absl::FromUnixMillis); - -#undef TEST_FLOOR_CONVERSION - - // Tests ToUnixNanos. - EXPECT_EQ(1, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(3) / 2)); - EXPECT_EQ(1, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(1))); - EXPECT_EQ(0, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(1) / 2)); - EXPECT_EQ(0, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(0))); - EXPECT_EQ(-1, - absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(1) / 2)); - EXPECT_EQ(-1, absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(1))); - EXPECT_EQ(-2, - absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(3) / 2)); - - // Tests ToUniversal, which uses a different epoch than the tests above. - EXPECT_EQ(1, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(101))); - EXPECT_EQ(1, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(100))); - EXPECT_EQ(0, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(99))); - EXPECT_EQ(0, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(1))); - EXPECT_EQ(0, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(0))); - EXPECT_EQ(-1, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-1))); - EXPECT_EQ(-1, - absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-99))); - EXPECT_EQ( - -1, absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-100))); - EXPECT_EQ( - -2, absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-101))); - - // Tests ToTimespec()/TimeFromTimespec() - const struct { - absl::Time t; - timespec ts; - } to_ts[] = { - {absl::FromUnixSeconds(1) + absl::Nanoseconds(1), {1, 1}}, - {absl::FromUnixSeconds(1) + absl::Nanoseconds(1) / 2, {1, 0}}, - {absl::FromUnixSeconds(1) + absl::Nanoseconds(0), {1, 0}}, - {absl::FromUnixSeconds(0) + absl::Nanoseconds(0), {0, 0}}, - {absl::FromUnixSeconds(0) - absl::Nanoseconds(1) / 2, {-1, 999999999}}, - {absl::FromUnixSeconds(0) - absl::Nanoseconds(1), {-1, 999999999}}, - {absl::FromUnixSeconds(-1) + absl::Nanoseconds(1), {-1, 1}}, - {absl::FromUnixSeconds(-1) + absl::Nanoseconds(1) / 2, {-1, 0}}, - {absl::FromUnixSeconds(-1) + absl::Nanoseconds(0), {-1, 0}}, - {absl::FromUnixSeconds(-1) - absl::Nanoseconds(1) / 2, {-2, 999999999}}, - }; - for (const auto& test : to_ts) { - EXPECT_THAT(absl::ToTimespec(test.t), TimespecMatcher(test.ts)); - } - const struct { - timespec ts; - absl::Time t; - } from_ts[] = { - {{1, 1}, absl::FromUnixSeconds(1) + absl::Nanoseconds(1)}, - {{1, 0}, absl::FromUnixSeconds(1) + absl::Nanoseconds(0)}, - {{0, 0}, absl::FromUnixSeconds(0) + absl::Nanoseconds(0)}, - {{0, -1}, absl::FromUnixSeconds(0) - absl::Nanoseconds(1)}, - {{-1, 999999999}, absl::FromUnixSeconds(0) - absl::Nanoseconds(1)}, - {{-1, 1}, absl::FromUnixSeconds(-1) + absl::Nanoseconds(1)}, - {{-1, 0}, absl::FromUnixSeconds(-1) + absl::Nanoseconds(0)}, - {{-1, -1}, absl::FromUnixSeconds(-1) - absl::Nanoseconds(1)}, - {{-2, 999999999}, absl::FromUnixSeconds(-1) - absl::Nanoseconds(1)}, - }; - for (const auto& test : from_ts) { - EXPECT_EQ(test.t, absl::TimeFromTimespec(test.ts)); - } - - // Tests ToTimeval()/TimeFromTimeval() (same as timespec above) - const struct { - absl::Time t; - timeval tv; - } to_tv[] = { - {absl::FromUnixSeconds(1) + absl::Microseconds(1), {1, 1}}, - {absl::FromUnixSeconds(1) + absl::Microseconds(1) / 2, {1, 0}}, - {absl::FromUnixSeconds(1) + absl::Microseconds(0), {1, 0}}, - {absl::FromUnixSeconds(0) + absl::Microseconds(0), {0, 0}}, - {absl::FromUnixSeconds(0) - absl::Microseconds(1) / 2, {-1, 999999}}, - {absl::FromUnixSeconds(0) - absl::Microseconds(1), {-1, 999999}}, - {absl::FromUnixSeconds(-1) + absl::Microseconds(1), {-1, 1}}, - {absl::FromUnixSeconds(-1) + absl::Microseconds(1) / 2, {-1, 0}}, - {absl::FromUnixSeconds(-1) + absl::Microseconds(0), {-1, 0}}, - {absl::FromUnixSeconds(-1) - absl::Microseconds(1) / 2, {-2, 999999}}, - }; - for (const auto& test : to_tv) { - EXPECT_THAT(ToTimeval(test.t), TimevalMatcher(test.tv)); - } - const struct { - timeval tv; - absl::Time t; - } from_tv[] = { - {{1, 1}, absl::FromUnixSeconds(1) + absl::Microseconds(1)}, - {{1, 0}, absl::FromUnixSeconds(1) + absl::Microseconds(0)}, - {{0, 0}, absl::FromUnixSeconds(0) + absl::Microseconds(0)}, - {{0, -1}, absl::FromUnixSeconds(0) - absl::Microseconds(1)}, - {{-1, 999999}, absl::FromUnixSeconds(0) - absl::Microseconds(1)}, - {{-1, 1}, absl::FromUnixSeconds(-1) + absl::Microseconds(1)}, - {{-1, 0}, absl::FromUnixSeconds(-1) + absl::Microseconds(0)}, - {{-1, -1}, absl::FromUnixSeconds(-1) - absl::Microseconds(1)}, - {{-2, 999999}, absl::FromUnixSeconds(-1) - absl::Microseconds(1)}, - }; - for (const auto& test : from_tv) { - EXPECT_EQ(test.t, absl::TimeFromTimeval(test.tv)); - } - - // Tests flooring near negative infinity. - 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)); - - // 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)); - 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)); -} - -TEST(Time, RoundtripConversion) { -#define TEST_CONVERSION_ROUND_TRIP(SOURCE, FROM, TO, MATCHER) \ - EXPECT_THAT(TO(FROM(SOURCE)), MATCHER(SOURCE)) - - // FromUnixNanos() and ToUnixNanos() - int64_t now_ns = absl::GetCurrentTimeNanos(); - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixNanos, absl::ToUnixNanos, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixNanos, absl::ToUnixNanos, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixNanos, absl::ToUnixNanos, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_ns, absl::FromUnixNanos, absl::ToUnixNanos, - testing::Eq) - << now_ns; - - // FromUnixMicros() and ToUnixMicros() - int64_t now_us = absl::GetCurrentTimeNanos() / 1000; - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixMicros, absl::ToUnixMicros, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixMicros, absl::ToUnixMicros, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixMicros, absl::ToUnixMicros, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_us, absl::FromUnixMicros, absl::ToUnixMicros, - testing::Eq) - << now_us; - - // FromUnixMillis() and ToUnixMillis() - int64_t now_ms = absl::GetCurrentTimeNanos() / 1000000; - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixMillis, absl::ToUnixMillis, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixMillis, absl::ToUnixMillis, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixMillis, absl::ToUnixMillis, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_ms, absl::FromUnixMillis, absl::ToUnixMillis, - testing::Eq) - << now_ms; - - // FromUnixSeconds() and ToUnixSeconds() - int64_t now_s = std::time(nullptr); - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixSeconds, absl::ToUnixSeconds, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixSeconds, absl::ToUnixSeconds, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixSeconds, absl::ToUnixSeconds, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_s, absl::FromUnixSeconds, absl::ToUnixSeconds, - testing::Eq) - << now_s; - - // FromTimeT() and ToTimeT() - time_t now_time_t = std::time(nullptr); - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromTimeT, absl::ToTimeT, testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromTimeT, absl::ToTimeT, testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromTimeT, absl::ToTimeT, testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_time_t, absl::FromTimeT, absl::ToTimeT, - testing::Eq) - << now_time_t; - - // TimeFromTimeval() and ToTimeval() - timeval tv; - tv.tv_sec = -1; - tv.tv_usec = 0; - TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval, - TimevalMatcher); - tv.tv_sec = -1; - tv.tv_usec = 999999; - TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval, - TimevalMatcher); - tv.tv_sec = 0; - tv.tv_usec = 0; - TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval, - TimevalMatcher); - tv.tv_sec = 0; - tv.tv_usec = 1; - TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval, - TimevalMatcher); - tv.tv_sec = 1; - tv.tv_usec = 0; - TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval, - TimevalMatcher); - - // TimeFromTimespec() and ToTimespec() - timespec ts; - ts.tv_sec = -1; - ts.tv_nsec = 0; - TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec, - TimespecMatcher); - ts.tv_sec = -1; - ts.tv_nsec = 999999999; - TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec, - TimespecMatcher); - ts.tv_sec = 0; - ts.tv_nsec = 0; - TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec, - TimespecMatcher); - ts.tv_sec = 0; - ts.tv_nsec = 1; - TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec, - TimespecMatcher); - ts.tv_sec = 1; - ts.tv_nsec = 0; - TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec, - TimespecMatcher); - - // FromUDate() and ToUDate() - double now_ud = absl::GetCurrentTimeNanos() / 1000000; - TEST_CONVERSION_ROUND_TRIP(-1.5, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(-0.5, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(0.5, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(1.5, absl::FromUDate, absl::ToUDate, - testing::DoubleEq); - TEST_CONVERSION_ROUND_TRIP(now_ud, absl::FromUDate, absl::ToUDate, - testing::DoubleEq) - << std::fixed << std::setprecision(17) << now_ud; - - // FromUniversal() and ToUniversal() - int64_t now_uni = ((719162LL * (24 * 60 * 60)) * (1000 * 1000 * 10)) + - (absl::GetCurrentTimeNanos() / 100); - TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUniversal, absl::ToUniversal, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(0, absl::FromUniversal, absl::ToUniversal, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(1, absl::FromUniversal, absl::ToUniversal, - testing::Eq); - TEST_CONVERSION_ROUND_TRIP(now_uni, absl::FromUniversal, absl::ToUniversal, - testing::Eq) - << now_uni; - -#undef TEST_CONVERSION_ROUND_TRIP -} - -template <typename Duration> -std::chrono::system_clock::time_point MakeChronoUnixTime(const Duration& d) { - return std::chrono::system_clock::from_time_t(0) + d; -} - -TEST(Time, FromChrono) { - EXPECT_EQ(absl::FromTimeT(-1), - absl::FromChrono(std::chrono::system_clock::from_time_t(-1))); - EXPECT_EQ(absl::FromTimeT(0), - absl::FromChrono(std::chrono::system_clock::from_time_t(0))); - EXPECT_EQ(absl::FromTimeT(1), - absl::FromChrono(std::chrono::system_clock::from_time_t(1))); - - EXPECT_EQ( - absl::FromUnixMillis(-1), - absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(-1)))); - EXPECT_EQ(absl::FromUnixMillis(0), - absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(0)))); - EXPECT_EQ(absl::FromUnixMillis(1), - absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(1)))); - - // Chrono doesn't define exactly its range and precision (neither does - // absl::Time), so let's simply test +/- ~100 years to make sure things work. - const auto century_sec = 60 * 60 * 24 * 365 * int64_t{100}; - const auto century = std::chrono::seconds(century_sec); - const auto chrono_future = MakeChronoUnixTime(century); - const auto chrono_past = MakeChronoUnixTime(-century); - EXPECT_EQ(absl::FromUnixSeconds(century_sec), - absl::FromChrono(chrono_future)); - EXPECT_EQ(absl::FromUnixSeconds(-century_sec), absl::FromChrono(chrono_past)); - - // Roundtrip them both back to chrono. - EXPECT_EQ(chrono_future, - absl::ToChronoTime(absl::FromUnixSeconds(century_sec))); - EXPECT_EQ(chrono_past, - absl::ToChronoTime(absl::FromUnixSeconds(-century_sec))); -} - -TEST(Time, ToChronoTime) { - EXPECT_EQ(std::chrono::system_clock::from_time_t(-1), - absl::ToChronoTime(absl::FromTimeT(-1))); - EXPECT_EQ(std::chrono::system_clock::from_time_t(0), - absl::ToChronoTime(absl::FromTimeT(0))); - EXPECT_EQ(std::chrono::system_clock::from_time_t(1), - absl::ToChronoTime(absl::FromTimeT(1))); - - EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(-1)), - absl::ToChronoTime(absl::FromUnixMillis(-1))); - EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(0)), - absl::ToChronoTime(absl::FromUnixMillis(0))); - EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(1)), - absl::ToChronoTime(absl::FromUnixMillis(1))); - - // Time before the Unix epoch should floor, not trunc. - const auto tick = absl::Nanoseconds(1) / 4; - EXPECT_EQ(std::chrono::system_clock::from_time_t(0) - - std::chrono::system_clock::duration(1), - absl::ToChronoTime(absl::UnixEpoch() - tick)); -} - -// Check that absl::int128 works as a std::chrono::duration representation. -TEST(Time, Chrono128) { - // Define a std::chrono::time_point type whose time[sic]_since_epoch() is - // a signed 128-bit count of attoseconds. This has a range and resolution - // (currently) beyond those of absl::Time, and undoubtedly also beyond those - // of std::chrono::system_clock::time_point. - // - // Note: The to/from-chrono support should probably be updated to handle - // such wide representations. - using Timestamp = - std::chrono::time_point<std::chrono::system_clock, - std::chrono::duration<absl::int128, std::atto>>; - - // Expect that we can round-trip the std::chrono::system_clock::time_point - // extremes through both absl::Time and Timestamp, and that Timestamp can - // handle the (current) absl::Time extremes. - // - // Note: We should use std::chrono::floor() instead of time_point_cast(), - // but floor() is only available since c++17. - for (const auto tp : {std::chrono::system_clock::time_point::min(), - std::chrono::system_clock::time_point::max()}) { - EXPECT_EQ(tp, absl::ToChronoTime(absl::FromChrono(tp))); - EXPECT_EQ(tp, std::chrono::time_point_cast< - std::chrono::system_clock::time_point::duration>( - std::chrono::time_point_cast<Timestamp::duration>(tp))); - } - Timestamp::duration::rep v = std::numeric_limits<int64_t>::min(); - v *= Timestamp::duration::period::den; - auto ts = Timestamp(Timestamp::duration(v)); - ts += std::chrono::duration<int64_t, std::atto>(0); - EXPECT_EQ(std::numeric_limits<int64_t>::min(), - ts.time_since_epoch().count() / Timestamp::duration::period::den); - EXPECT_EQ(0, - ts.time_since_epoch().count() % Timestamp::duration::period::den); - v = std::numeric_limits<int64_t>::max(); - v *= Timestamp::duration::period::den; - ts = Timestamp(Timestamp::duration(v)); - ts += std::chrono::duration<int64_t, std::atto>(999999999750000000); - EXPECT_EQ(std::numeric_limits<int64_t>::max(), - ts.time_since_epoch().count() / Timestamp::duration::period::den); - EXPECT_EQ(999999999750000000, - ts.time_since_epoch().count() % Timestamp::duration::period::den); -} - -TEST(Time, TimeZoneAt) { - const absl::TimeZone nyc = - absl::time_internal::LoadTimeZone("America/New_York"); - const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)"; - - // A non-transition where the civil time is unique. - absl::CivilSecond nov01(2013, 11, 1, 8, 30, 0); - const auto nov01_ci = nyc.At(nov01); - EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, nov01_ci.kind); - EXPECT_EQ("Fri, 1 Nov 2013 08:30:00 -0400 (EDT)", - absl::FormatTime(fmt, nov01_ci.pre, nyc)); - EXPECT_EQ(nov01_ci.pre, nov01_ci.trans); - EXPECT_EQ(nov01_ci.pre, nov01_ci.post); - EXPECT_EQ(nov01_ci.pre, absl::FromCivil(nov01, nyc)); - - // A Spring DST transition, when there is a gap in civil time - // and we prefer the later of the possible interpretations of a - // non-existent time. - absl::CivilSecond mar13(2011, 3, 13, 2, 15, 0); - const auto mar_ci = nyc.At(mar13); - EXPECT_EQ(absl::TimeZone::TimeInfo::SKIPPED, mar_ci.kind); - EXPECT_EQ("Sun, 13 Mar 2011 03:15:00 -0400 (EDT)", - absl::FormatTime(fmt, mar_ci.pre, nyc)); - EXPECT_EQ("Sun, 13 Mar 2011 03:00:00 -0400 (EDT)", - absl::FormatTime(fmt, mar_ci.trans, nyc)); - EXPECT_EQ("Sun, 13 Mar 2011 01:15:00 -0500 (EST)", - absl::FormatTime(fmt, mar_ci.post, nyc)); - EXPECT_EQ(mar_ci.trans, absl::FromCivil(mar13, nyc)); - - // A Fall DST transition, when civil times are repeated and - // we prefer the earlier of the possible interpretations of an - // ambiguous time. - absl::CivilSecond nov06(2011, 11, 6, 1, 15, 0); - const auto nov06_ci = nyc.At(nov06); - EXPECT_EQ(absl::TimeZone::TimeInfo::REPEATED, nov06_ci.kind); - EXPECT_EQ("Sun, 6 Nov 2011 01:15:00 -0400 (EDT)", - absl::FormatTime(fmt, nov06_ci.pre, nyc)); - EXPECT_EQ("Sun, 6 Nov 2011 01:00:00 -0500 (EST)", - absl::FormatTime(fmt, nov06_ci.trans, nyc)); - EXPECT_EQ("Sun, 6 Nov 2011 01:15:00 -0500 (EST)", - absl::FormatTime(fmt, nov06_ci.post, nyc)); - EXPECT_EQ(nov06_ci.pre, absl::FromCivil(nov06, nyc)); - - // Check that (time_t) -1 is handled correctly. - absl::CivilSecond minus1(1969, 12, 31, 18, 59, 59); - const auto minus1_cl = nyc.At(minus1); - EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, minus1_cl.kind); - EXPECT_EQ(-1, absl::ToTimeT(minus1_cl.pre)); - EXPECT_EQ("Wed, 31 Dec 1969 18:59:59 -0500 (EST)", - absl::FormatTime(fmt, minus1_cl.pre, nyc)); - EXPECT_EQ("Wed, 31 Dec 1969 23:59:59 +0000 (UTC)", - absl::FormatTime(fmt, minus1_cl.pre, absl::UTCTimeZone())); -} - -// FromCivil(CivilSecond(year, mon, day, hour, min, sec), UTCTimeZone()) -// has a specialized fastpath implementation, which we exercise here. -TEST(Time, FromCivilUTC) { - const absl::TimeZone utc = absl::UTCTimeZone(); - const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)"; - const int kMax = std::numeric_limits<int>::max(); - const int kMin = std::numeric_limits<int>::min(); - absl::Time t; - - // 292091940881 is the last positive year to use the fastpath. - t = absl::FromCivil( - absl::CivilSecond(292091940881, kMax, kMax, kMax, kMax, kMax), utc); - EXPECT_EQ("Fri, 25 Nov 292277026596 12:21:07 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); - t = absl::FromCivil( - absl::CivilSecond(292091940882, kMax, kMax, kMax, kMax, kMax), utc); - EXPECT_EQ("infinite-future", absl::FormatTime(fmt, t, utc)); // no overflow - - // -292091936940 is the last negative year to use the fastpath. - t = absl::FromCivil( - absl::CivilSecond(-292091936940, kMin, kMin, kMin, kMin, kMin), utc); - EXPECT_EQ("Fri, 1 Nov -292277022657 10:37:52 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); - t = absl::FromCivil( - absl::CivilSecond(-292091936941, kMin, kMin, kMin, kMin, kMin), utc); - EXPECT_EQ("infinite-past", absl::FormatTime(fmt, t, utc)); // no underflow - - // Check that we're counting leap years correctly. - t = absl::FromCivil(absl::CivilSecond(1900, 2, 28, 23, 59, 59), utc); - EXPECT_EQ("Wed, 28 Feb 1900 23:59:59 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); - t = absl::FromCivil(absl::CivilSecond(1900, 3, 1, 0, 0, 0), utc); - EXPECT_EQ("Thu, 1 Mar 1900 00:00:00 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); - t = absl::FromCivil(absl::CivilSecond(2000, 2, 29, 23, 59, 59), utc); - EXPECT_EQ("Tue, 29 Feb 2000 23:59:59 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); - t = absl::FromCivil(absl::CivilSecond(2000, 3, 1, 0, 0, 0), utc); - EXPECT_EQ("Wed, 1 Mar 2000 00:00:00 +0000 (UTC)", - absl::FormatTime(fmt, t, utc)); -} - -TEST(Time, ToTM) { - const absl::TimeZone utc = absl::UTCTimeZone(); - - // Compares the results of ToTM() to gmtime_r() for lots of times over the - // course of a few days. - const absl::Time start = - absl::FromCivil(absl::CivilSecond(2014, 1, 2, 3, 4, 5), utc); - const absl::Time end = - absl::FromCivil(absl::CivilSecond(2014, 1, 5, 3, 4, 5), utc); - for (absl::Time t = start; t < end; t += absl::Seconds(30)) { - const struct tm tm_bt = ToTM(t, utc); - const time_t tt = absl::ToTimeT(t); - struct tm tm_lc; -#ifdef _WIN32 - gmtime_s(&tm_lc, &tt); -#else - gmtime_r(&tt, &tm_lc); -#endif - EXPECT_EQ(tm_lc.tm_year, tm_bt.tm_year); - EXPECT_EQ(tm_lc.tm_mon, tm_bt.tm_mon); - EXPECT_EQ(tm_lc.tm_mday, tm_bt.tm_mday); - EXPECT_EQ(tm_lc.tm_hour, tm_bt.tm_hour); - EXPECT_EQ(tm_lc.tm_min, tm_bt.tm_min); - EXPECT_EQ(tm_lc.tm_sec, tm_bt.tm_sec); - EXPECT_EQ(tm_lc.tm_wday, tm_bt.tm_wday); - EXPECT_EQ(tm_lc.tm_yday, tm_bt.tm_yday); - EXPECT_EQ(tm_lc.tm_isdst, tm_bt.tm_isdst); - - ASSERT_FALSE(HasFailure()); - } - - // Checks that the tm_isdst field is correct when in standard time. - const absl::TimeZone nyc = - absl::time_internal::LoadTimeZone("America/New_York"); - absl::Time t = absl::FromCivil(absl::CivilSecond(2014, 3, 1, 0, 0, 0), nyc); - struct tm tm = ToTM(t, nyc); - EXPECT_FALSE(tm.tm_isdst); - - // Checks that the tm_isdst field is correct when in daylight time. - t = absl::FromCivil(absl::CivilSecond(2014, 4, 1, 0, 0, 0), nyc); - tm = ToTM(t, nyc); - EXPECT_TRUE(tm.tm_isdst); - - // Checks overflow. - tm = ToTM(absl::InfiniteFuture(), nyc); - EXPECT_EQ(std::numeric_limits<int>::max() - 1900, tm.tm_year); - EXPECT_EQ(11, tm.tm_mon); - EXPECT_EQ(31, tm.tm_mday); - EXPECT_EQ(23, tm.tm_hour); - EXPECT_EQ(59, tm.tm_min); - EXPECT_EQ(59, tm.tm_sec); - EXPECT_EQ(4, tm.tm_wday); - EXPECT_EQ(364, tm.tm_yday); - EXPECT_FALSE(tm.tm_isdst); - - // Checks underflow. - tm = ToTM(absl::InfinitePast(), nyc); - EXPECT_EQ(std::numeric_limits<int>::min(), tm.tm_year); - EXPECT_EQ(0, tm.tm_mon); - EXPECT_EQ(1, tm.tm_mday); - EXPECT_EQ(0, tm.tm_hour); - EXPECT_EQ(0, tm.tm_min); - EXPECT_EQ(0, tm.tm_sec); - EXPECT_EQ(0, tm.tm_wday); - EXPECT_EQ(0, tm.tm_yday); - EXPECT_FALSE(tm.tm_isdst); -} - -TEST(Time, FromTM) { - const absl::TimeZone nyc = - absl::time_internal::LoadTimeZone("America/New_York"); - - // Verifies that tm_isdst doesn't affect anything when the time is unique. - struct tm tm; - std::memset(&tm, 0, sizeof(tm)); - tm.tm_year = 2014 - 1900; - tm.tm_mon = 6 - 1; - tm.tm_mday = 28; - tm.tm_hour = 1; - tm.tm_min = 2; - tm.tm_sec = 3; - tm.tm_isdst = -1; - absl::Time t = FromTM(tm, nyc); - EXPECT_EQ("2014-06-28T01:02:03-04:00", absl::FormatTime(t, nyc)); // DST - tm.tm_isdst = 0; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-06-28T01:02:03-04:00", absl::FormatTime(t, nyc)); // DST - tm.tm_isdst = 1; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-06-28T01:02:03-04:00", absl::FormatTime(t, nyc)); // DST - - // Adjusts tm to refer to an ambiguous time. - tm.tm_year = 2014 - 1900; - tm.tm_mon = 11 - 1; - tm.tm_mday = 2; - tm.tm_hour = 1; - tm.tm_min = 30; - tm.tm_sec = 42; - tm.tm_isdst = -1; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-11-02T01:30:42-04:00", absl::FormatTime(t, nyc)); // DST - tm.tm_isdst = 0; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-11-02T01:30:42-05:00", absl::FormatTime(t, nyc)); // STD - tm.tm_isdst = 1; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-11-02T01:30:42-04:00", absl::FormatTime(t, nyc)); // DST - - // Adjusts tm to refer to a skipped time. - tm.tm_year = 2014 - 1900; - tm.tm_mon = 3 - 1; - tm.tm_mday = 9; - tm.tm_hour = 2; - tm.tm_min = 30; - tm.tm_sec = 42; - tm.tm_isdst = -1; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc)); // DST - tm.tm_isdst = 0; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-03-09T01:30:42-05:00", absl::FormatTime(t, nyc)); // STD - tm.tm_isdst = 1; - t = FromTM(tm, nyc); - EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc)); // DST - - // Adjusts tm to refer to a time with a year larger than 2147483647. - tm.tm_year = 2147483647 - 1900 + 1; - tm.tm_mon = 6 - 1; - tm.tm_mday = 28; - tm.tm_hour = 1; - tm.tm_min = 2; - tm.tm_sec = 3; - tm.tm_isdst = -1; - t = FromTM(tm, absl::UTCTimeZone()); - EXPECT_EQ("2147483648-06-28T01:02:03+00:00", - absl::FormatTime(t, absl::UTCTimeZone())); - - // Adjusts tm to refer to a time with a very large month. - tm.tm_year = 2019 - 1900; - tm.tm_mon = 2147483647; - tm.tm_mday = 28; - tm.tm_hour = 1; - tm.tm_min = 2; - tm.tm_sec = 3; - tm.tm_isdst = -1; - t = FromTM(tm, absl::UTCTimeZone()); - EXPECT_EQ("178958989-08-28T01:02:03+00:00", - absl::FormatTime(t, absl::UTCTimeZone())); -} - -TEST(Time, TMRoundTrip) { - const absl::TimeZone nyc = - absl::time_internal::LoadTimeZone("America/New_York"); - - // Test round-tripping across a skipped transition - absl::Time start = absl::FromCivil(absl::CivilHour(2014, 3, 9, 0), nyc); - absl::Time end = absl::FromCivil(absl::CivilHour(2014, 3, 9, 4), nyc); - for (absl::Time t = start; t < end; t += absl::Minutes(1)) { - struct tm tm = ToTM(t, nyc); - absl::Time rt = FromTM(tm, nyc); - EXPECT_EQ(rt, t); - } - - // Test round-tripping across an ambiguous transition - start = absl::FromCivil(absl::CivilHour(2014, 11, 2, 0), nyc); - end = absl::FromCivil(absl::CivilHour(2014, 11, 2, 4), nyc); - for (absl::Time t = start; t < end; t += absl::Minutes(1)) { - struct tm tm = ToTM(t, nyc); - absl::Time rt = FromTM(tm, nyc); - EXPECT_EQ(rt, t); - } - - // Test round-tripping of unique instants crossing a day boundary - start = absl::FromCivil(absl::CivilHour(2014, 6, 27, 22), nyc); - end = absl::FromCivil(absl::CivilHour(2014, 6, 28, 4), nyc); - for (absl::Time t = start; t < end; t += absl::Minutes(1)) { - struct tm tm = ToTM(t, nyc); - absl::Time rt = FromTM(tm, nyc); - EXPECT_EQ(rt, t); - } -} - -TEST(Time, Range) { - // The API's documented range is +/- 100 billion years. - const absl::Duration range = absl::Hours(24) * 365.2425 * 100000000000; - - // Arithmetic and comparison still works at +/-range around base values. - absl::Time bases[2] = {absl::UnixEpoch(), absl::Now()}; - for (const auto base : bases) { - absl::Time bottom = base - range; - EXPECT_GT(bottom, bottom - absl::Nanoseconds(1)); - EXPECT_LT(bottom, bottom + absl::Nanoseconds(1)); - absl::Time top = base + range; - EXPECT_GT(top, top - absl::Nanoseconds(1)); - EXPECT_LT(top, top + absl::Nanoseconds(1)); - absl::Duration full_range = 2 * range; - EXPECT_EQ(full_range, top - bottom); - EXPECT_EQ(-full_range, bottom - top); - } -} - -TEST(Time, Limits) { - // It is an implementation detail that Time().rep_ == ZeroDuration(), - // and that the resolution of a Duration is 1/4 of a nanosecond. - const absl::Time zero; - const absl::Time max = - zero + absl::Seconds(std::numeric_limits<int64_t>::max()) + - absl::Nanoseconds(999999999) + absl::Nanoseconds(3) / 4; - const absl::Time min = - zero + absl::Seconds(std::numeric_limits<int64_t>::min()); - - // Some simple max/min bounds checks. - EXPECT_LT(max, absl::InfiniteFuture()); - EXPECT_GT(min, absl::InfinitePast()); - EXPECT_LT(zero, max); - EXPECT_GT(zero, min); - EXPECT_GE(absl::UnixEpoch(), min); - EXPECT_LT(absl::UnixEpoch(), max); - - // Check sign of Time differences. - EXPECT_LT(absl::ZeroDuration(), max - zero); - EXPECT_LT(absl::ZeroDuration(), - zero - absl::Nanoseconds(1) / 4 - min); // avoid zero - min - - // Arithmetic works at max - 0.25ns and min + 0.25ns. - EXPECT_GT(max, max - absl::Nanoseconds(1) / 4); - EXPECT_LT(min, min + absl::Nanoseconds(1) / 4); -} - -TEST(Time, ConversionSaturation) { - const absl::TimeZone utc = absl::UTCTimeZone(); - absl::Time t; - - const auto max_time_t = std::numeric_limits<time_t>::max(); - const auto min_time_t = std::numeric_limits<time_t>::min(); - time_t tt = max_time_t - 1; - t = absl::FromTimeT(tt); - tt = absl::ToTimeT(t); - EXPECT_EQ(max_time_t - 1, tt); - t += absl::Seconds(1); - tt = absl::ToTimeT(t); - EXPECT_EQ(max_time_t, tt); - t += absl::Seconds(1); // no effect - tt = absl::ToTimeT(t); - EXPECT_EQ(max_time_t, tt); - - tt = min_time_t + 1; - t = absl::FromTimeT(tt); - tt = absl::ToTimeT(t); - EXPECT_EQ(min_time_t + 1, tt); - t -= absl::Seconds(1); - tt = absl::ToTimeT(t); - EXPECT_EQ(min_time_t, tt); - t -= absl::Seconds(1); // no effect - tt = absl::ToTimeT(t); - EXPECT_EQ(min_time_t, tt); - - const auto max_timeval_sec = - std::numeric_limits<decltype(timeval::tv_sec)>::max(); - const auto min_timeval_sec = - std::numeric_limits<decltype(timeval::tv_sec)>::min(); - timeval tv; - tv.tv_sec = max_timeval_sec; - tv.tv_usec = 999998; - t = absl::TimeFromTimeval(tv); - tv = ToTimeval(t); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999998, tv.tv_usec); - t += absl::Microseconds(1); - tv = ToTimeval(t); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999999, tv.tv_usec); - t += absl::Microseconds(1); // no effect - tv = ToTimeval(t); - EXPECT_EQ(max_timeval_sec, tv.tv_sec); - EXPECT_EQ(999999, tv.tv_usec); - - tv.tv_sec = min_timeval_sec; - tv.tv_usec = 1; - t = absl::TimeFromTimeval(tv); - tv = ToTimeval(t); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(1, tv.tv_usec); - t -= absl::Microseconds(1); - tv = ToTimeval(t); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(0, tv.tv_usec); - t -= absl::Microseconds(1); // no effect - tv = ToTimeval(t); - EXPECT_EQ(min_timeval_sec, tv.tv_sec); - EXPECT_EQ(0, tv.tv_usec); - - const auto max_timespec_sec = - std::numeric_limits<decltype(timespec::tv_sec)>::max(); - const auto min_timespec_sec = - std::numeric_limits<decltype(timespec::tv_sec)>::min(); - timespec ts; - ts.tv_sec = max_timespec_sec; - ts.tv_nsec = 999999998; - t = absl::TimeFromTimespec(ts); - ts = absl::ToTimespec(t); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999998, ts.tv_nsec); - t += absl::Nanoseconds(1); - ts = absl::ToTimespec(t); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999999, ts.tv_nsec); - t += absl::Nanoseconds(1); // no effect - ts = absl::ToTimespec(t); - EXPECT_EQ(max_timespec_sec, ts.tv_sec); - EXPECT_EQ(999999999, ts.tv_nsec); - - ts.tv_sec = min_timespec_sec; - ts.tv_nsec = 1; - t = absl::TimeFromTimespec(ts); - ts = absl::ToTimespec(t); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(1, ts.tv_nsec); - t -= absl::Nanoseconds(1); - ts = absl::ToTimespec(t); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(0, ts.tv_nsec); - t -= absl::Nanoseconds(1); // no effect - ts = absl::ToTimespec(t); - EXPECT_EQ(min_timespec_sec, ts.tv_sec); - EXPECT_EQ(0, ts.tv_nsec); - - // 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_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_EQ(-absl::InfiniteDuration(), ci.subsecond); - EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs)); - EXPECT_EQ(1, absl::GetYearDay(ci.cs)); - EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At() - - // Approach the maximal Time value from below. - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 6), utc); - EXPECT_EQ("292277026596-12-04T15:30:06+00:00", - absl::FormatTime(absl::RFC3339_full, t, utc)); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 7), utc); - 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); - - // Checks that we can also get the maximal Time value for a far-east zone. - const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 5, 30, 7), plus14); - 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); - - // One second later should push us to infinity. - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc); - EXPECT_EQ("infinite-future", absl::FormatTime(absl::RFC3339_full, t, utc)); - - // Approach the minimal Time value from above. - t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 53), utc); - EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", - absl::FormatTime(absl::RFC3339_full, t, utc)); - t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 52), utc); - 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); - - // Checks that we can also get the minimal Time value for a far-west zone. - const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60); - t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 26, 20, 29, 52), - minus12); - 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); - - // One second before should push us to -infinity. - t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc); - EXPECT_EQ("infinite-past", absl::FormatTime(absl::RFC3339_full, t, utc)); -} - -// In zones with POSIX-style recurring rules we use special logic to -// handle conversions in the distant future. Here we check the limits -// of those conversions, particularly with respect to integer overflow. -TEST(Time, ExtendedConversionSaturation) { - const absl::TimeZone syd = - absl::time_internal::LoadTimeZone("Australia/Sydney"); - const absl::TimeZone nyc = - absl::time_internal::LoadTimeZone("America/New_York"); - const absl::Time max = - absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()); - absl::TimeZone::CivilInfo ci; - absl::Time t; - - // The maximal time converted in each zone. - ci = syd.At(max); - EXPECT_CIVIL_INFO(ci, 292277026596, 12, 5, 2, 30, 7, 39600, true); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 7), syd); - EXPECT_EQ(max, t); - ci = nyc.At(max); - EXPECT_CIVIL_INFO(ci, 292277026596, 12, 4, 10, 30, 7, -18000, false); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 7), nyc); - EXPECT_EQ(max, t); - - // One second later should push us to infinity. - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 8), syd); - EXPECT_EQ(absl::InfiniteFuture(), t); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 8), nyc); - EXPECT_EQ(absl::InfiniteFuture(), t); - - // And we should stick there. - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 9), syd); - EXPECT_EQ(absl::InfiniteFuture(), t); - t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 9), nyc); - EXPECT_EQ(absl::InfiniteFuture(), t); - - // All the way up to a saturated date/time, without overflow. - t = absl::FromCivil(absl::CivilSecond::max(), syd); - EXPECT_EQ(absl::InfiniteFuture(), t); - t = absl::FromCivil(absl::CivilSecond::max(), nyc); - EXPECT_EQ(absl::InfiniteFuture(), t); -} - -TEST(Time, FromCivilAlignment) { - const absl::TimeZone utc = absl::UTCTimeZone(); - const absl::CivilSecond cs(2015, 2, 3, 4, 5, 6); - absl::Time t = absl::FromCivil(cs, utc); - EXPECT_EQ("2015-02-03T04:05:06+00:00", absl::FormatTime(t, utc)); - t = absl::FromCivil(absl::CivilMinute(cs), utc); - EXPECT_EQ("2015-02-03T04:05:00+00:00", absl::FormatTime(t, utc)); - t = absl::FromCivil(absl::CivilHour(cs), utc); - EXPECT_EQ("2015-02-03T04:00:00+00:00", absl::FormatTime(t, utc)); - t = absl::FromCivil(absl::CivilDay(cs), utc); - EXPECT_EQ("2015-02-03T00:00:00+00:00", absl::FormatTime(t, utc)); - t = absl::FromCivil(absl::CivilMonth(cs), utc); - EXPECT_EQ("2015-02-01T00:00:00+00:00", absl::FormatTime(t, utc)); - t = absl::FromCivil(absl::CivilYear(cs), utc); - EXPECT_EQ("2015-01-01T00:00:00+00:00", absl::FormatTime(t, utc)); -} - -TEST(Time, LegacyDateTime) { - const absl::TimeZone utc = absl::UTCTimeZone(); - const std::string ymdhms = "%Y-%m-%d %H:%M:%S"; - const int kMax = std::numeric_limits<int>::max(); - 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); - 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 - - // Check normalization. - EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized); - t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc); - EXPECT_EQ("2015-01-01 00:01:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc); - EXPECT_EQ("2015-01-01 01:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc); - EXPECT_EQ("2015-01-02 00:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc); - EXPECT_EQ("2015-02-01 00:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc); - EXPECT_EQ("2016-01-01 00:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc); - EXPECT_EQ("2016-02-03 13:01:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc); - EXPECT_EQ("2014-12-31 23:59:59", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc); - EXPECT_EQ("2014-12-31 23:59:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc); - EXPECT_EQ("2014-12-31 23:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc); - EXPECT_EQ("2014-12-30 00:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc); - EXPECT_EQ("2014-11-01 00:00:00", absl::FormatTime(ymdhms, t, utc)); - t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc); - EXPECT_EQ("2014-10-29 22:58:59", absl::FormatTime(ymdhms, t, utc)); -} - -TEST(Time, NextTransitionUTC) { - const auto tz = absl::UTCTimeZone(); - absl::TimeZone::CivilTransition trans; - - auto t = absl::InfinitePast(); - EXPECT_FALSE(tz.NextTransition(t, &trans)); - - t = absl::InfiniteFuture(); - EXPECT_FALSE(tz.NextTransition(t, &trans)); -} - -TEST(Time, PrevTransitionUTC) { - const auto tz = absl::UTCTimeZone(); - absl::TimeZone::CivilTransition trans; - - auto t = absl::InfiniteFuture(); - EXPECT_FALSE(tz.PrevTransition(t, &trans)); - - t = absl::InfinitePast(); - EXPECT_FALSE(tz.PrevTransition(t, &trans)); -} - -TEST(Time, NextTransitionNYC) { - const auto tz = absl::time_internal::LoadTimeZone("America/New_York"); - absl::TimeZone::CivilTransition trans; - - auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz); - EXPECT_TRUE(tz.NextTransition(t, &trans)); - EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 2, 0, 0), trans.from); - EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 1, 0, 0), trans.to); - - t = absl::InfiniteFuture(); - EXPECT_FALSE(tz.NextTransition(t, &trans)); - - t = absl::InfinitePast(); - EXPECT_TRUE(tz.NextTransition(t, &trans)); - if (trans.from == absl::CivilSecond(1918, 03, 31, 2, 0, 0)) { - // It looks like the tzdata is only 32 bit (probably macOS), - // which bottoms out at 1901-12-13T20:45:52+00:00. - EXPECT_EQ(absl::CivilSecond(1918, 3, 31, 3, 0, 0), trans.to); - } else { - EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 3, 58), trans.from); - EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 0, 0), trans.to); - } -} - -TEST(Time, PrevTransitionNYC) { - const auto tz = absl::time_internal::LoadTimeZone("America/New_York"); - absl::TimeZone::CivilTransition trans; - - auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz); - EXPECT_TRUE(tz.PrevTransition(t, &trans)); - EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 2, 0, 0), trans.from); - EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 3, 0, 0), trans.to); - - t = absl::InfinitePast(); - EXPECT_FALSE(tz.PrevTransition(t, &trans)); - - t = absl::InfiniteFuture(); - EXPECT_TRUE(tz.PrevTransition(t, &trans)); - // We have a transition but we don't know which one. -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/time/time_zone_test.cc b/third_party/abseil_cpp/absl/time/time_zone_test.cc deleted file mode 100644 index 229fcfccb0ad..000000000000 --- a/third_party/abseil_cpp/absl/time/time_zone_test.cc +++ /dev/null @@ -1,97 +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/time/internal/cctz/include/cctz/time_zone.h" - -#include "gtest/gtest.h" -#include "absl/time/internal/test_util.h" -#include "absl/time/time.h" - -namespace cctz = absl::time_internal::cctz; - -namespace { - -TEST(TimeZone, ValueSemantics) { - absl::TimeZone tz; - absl::TimeZone tz2 = tz; // Copy-construct - EXPECT_EQ(tz, tz2); - tz2 = tz; // Copy-assign - EXPECT_EQ(tz, tz2); -} - -TEST(TimeZone, Equality) { - absl::TimeZone a, b; - EXPECT_EQ(a, b); - EXPECT_EQ(a.name(), b.name()); - - absl::TimeZone implicit_utc; - absl::TimeZone explicit_utc = absl::UTCTimeZone(); - EXPECT_EQ(implicit_utc, explicit_utc); - EXPECT_EQ(implicit_utc.name(), explicit_utc.name()); - - absl::TimeZone la = absl::time_internal::LoadTimeZone("America/Los_Angeles"); - absl::TimeZone nyc = absl::time_internal::LoadTimeZone("America/New_York"); - EXPECT_NE(la, nyc); -} - -TEST(TimeZone, CCTZConversion) { - const cctz::time_zone cz = cctz::utc_time_zone(); - const absl::TimeZone tz(cz); - EXPECT_EQ(cz, cctz::time_zone(tz)); -} - -TEST(TimeZone, DefaultTimeZones) { - absl::TimeZone tz; - EXPECT_EQ("UTC", absl::TimeZone().name()); - EXPECT_EQ("UTC", absl::UTCTimeZone().name()); -} - -TEST(TimeZone, FixedTimeZone) { - const absl::TimeZone tz = absl::FixedTimeZone(123); - const cctz::time_zone cz = cctz::fixed_time_zone(cctz::seconds(123)); - EXPECT_EQ(tz, absl::TimeZone(cz)); -} - -TEST(TimeZone, LocalTimeZone) { - const absl::TimeZone local_tz = absl::LocalTimeZone(); - absl::TimeZone tz = absl::time_internal::LoadTimeZone("localtime"); - EXPECT_EQ(tz, local_tz); -} - -TEST(TimeZone, NamedTimeZones) { - absl::TimeZone nyc = absl::time_internal::LoadTimeZone("America/New_York"); - EXPECT_EQ("America/New_York", nyc.name()); - absl::TimeZone syd = absl::time_internal::LoadTimeZone("Australia/Sydney"); - EXPECT_EQ("Australia/Sydney", syd.name()); - absl::TimeZone fixed = absl::FixedTimeZone((((3 * 60) + 25) * 60) + 45); - EXPECT_EQ("Fixed/UTC+03:25:45", fixed.name()); -} - -TEST(TimeZone, Failures) { - absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz)); - EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC - - // Ensures that the load still fails on a subsequent attempt. - tz = absl::time_internal::LoadTimeZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz)); - EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC - - // Loading an empty string timezone should fail. - tz = absl::time_internal::LoadTimeZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("", &tz)); - EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/BUILD.bazel b/third_party/abseil_cpp/absl/types/BUILD.bazel deleted file mode 100644 index 83be9360ff99..000000000000 --- a/third_party/abseil_cpp/absl/types/BUILD.bazel +++ /dev/null @@ -1,336 +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. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "any", - hdrs = ["any.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_any_cast", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:fast_type_id", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_library( - name = "bad_any_cast", - hdrs = ["bad_any_cast.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_any_cast_impl", - "//absl/base:config", - ], -) - -cc_library( - name = "bad_any_cast_impl", - srcs = [ - "bad_any_cast.cc", - "bad_any_cast.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "any_test", - size = "small", - srcs = [ - "any_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":any", - "//absl/base:config", - "//absl/base:exception_testing", - "//absl/base:raw_logging_internal", - "//absl/container:test_instance_tracker", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "any_exception_safety_test", - srcs = ["any_exception_safety_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":any", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "span", - srcs = [ - "internal/span.h", - ], - hdrs = [ - "span.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/algorithm", - "//absl/base:core_headers", - "//absl/base:throw_delegate", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "span_test", - size = "small", - srcs = ["span_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":span", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:exception_testing", - "//absl/container:fixed_array", - "//absl/container:inlined_vector", - "//absl/hash:hash_testing", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "optional", - srcs = ["internal/optional.h"], - hdrs = ["optional.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_optional_access", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_library( - name = "bad_optional_access", - srcs = ["bad_optional_access.cc"], - hdrs = ["bad_optional_access.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "bad_variant_access", - srcs = ["bad_variant_access.cc"], - hdrs = ["bad_variant_access.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "optional_test", - size = "small", - srcs = [ - "optional_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":optional", - "//absl/base:config", - "//absl/base:raw_logging_internal", - "//absl/meta:type_traits", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "optional_exception_safety_test", - srcs = [ - "optional_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":optional", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "conformance_testing", - testonly = 1, - hdrs = [ - "internal/conformance_aliases.h", - "internal/conformance_archetype.h", - "internal/conformance_profile.h", - "internal/conformance_testing.h", - "internal/conformance_testing_helpers.h", - "internal/parentheses.h", - "internal/transform_args.h", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/algorithm:container", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/utility", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "conformance_testing_test", - size = "small", - srcs = [ - "internal/conformance_testing_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":conformance_testing", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "variant", - srcs = ["internal/variant.h"], - hdrs = ["variant.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_variant_access", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_test( - name = "variant_test", - size = "small", - srcs = ["variant_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":variant", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "variant_benchmark", - srcs = [ - "variant_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":variant", - "//absl/utility", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "variant_exception_safety_test", - size = "small", - srcs = [ - "variant_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":variant", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "compare", - hdrs = ["compare.h"], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base:core_headers", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "compare_test", - size = "small", - srcs = [ - "compare_test.cc", - ], - copts = ABSL_TEST_COPTS, - deps = [ - ":compare", - "//absl/base", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/types/CMakeLists.txt b/third_party/abseil_cpp/absl/types/CMakeLists.txt deleted file mode 100644 index 3f99ad8a4b4d..000000000000 --- a/third_party/abseil_cpp/absl/types/CMakeLists.txt +++ /dev/null @@ -1,373 +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. -# -absl_cc_library( - NAME - any - HDRS - "any.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_any_cast - absl::config - absl::core_headers - absl::fast_type_id - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_library( - NAME - bad_any_cast - HDRS - "bad_any_cast.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_any_cast_impl - absl::config - PUBLIC -) - -absl_cc_library( - NAME - bad_any_cast_impl - SRCS - "bad_any_cast.h" - "bad_any_cast.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal -) - -absl_cc_test( - NAME - any_test - SRCS - "any_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_testing - absl::raw_logging_internal - absl::test_instance_tracker - gmock_main -) - -absl_cc_test( - NAME - any_test_noexceptions - SRCS - "any_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_testing - absl::raw_logging_internal - absl::test_instance_tracker - gmock_main -) - -absl_cc_test( - NAME - any_exception_safety_test - SRCS - "any_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_safety_testing - gmock_main -) - -absl_cc_library( - NAME - span - HDRS - "span.h" - SRCS - "internal/span.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::core_headers - absl::throw_delegate - absl::type_traits - PUBLIC -) - -absl_cc_test( - NAME - span_test - SRCS - "span_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::span - absl::base - absl::config - absl::core_headers - absl::exception_testing - absl::fixed_array - absl::inlined_vector - absl::hash_testing - absl::strings - gmock_main -) - -absl_cc_test( - NAME - span_test_noexceptions - SRCS - "span_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::span - absl::base - absl::config - absl::core_headers - absl::exception_testing - absl::fixed_array - absl::inlined_vector - absl::hash_testing - absl::strings - gmock_main -) - -absl_cc_library( - NAME - optional - HDRS - "optional.h" - SRCS - "internal/optional.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_optional_access - absl::base_internal - absl::config - absl::core_headers - absl::memory - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_library( - NAME - bad_optional_access - HDRS - "bad_optional_access.h" - SRCS - "bad_optional_access.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal - PUBLIC -) - -absl_cc_library( - NAME - bad_variant_access - HDRS - "bad_variant_access.h" - SRCS - "bad_variant_access.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal - PUBLIC -) - -absl_cc_test( - NAME - optional_test - SRCS - "optional_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::optional - absl::config - absl::raw_logging_internal - absl::strings - absl::type_traits - gmock_main -) - -absl_cc_test( - NAME - optional_exception_safety_test - SRCS - "optional_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::optional - absl::config - absl::exception_safety_testing - gmock_main -) - -absl_cc_library( - NAME - conformance_testing - HDRS - "internal/conformance_aliases.h" - "internal/conformance_archetype.h" - "internal/conformance_profile.h" - "internal/conformance_testing.h" - "internal/conformance_testing_helpers.h" - "internal/parentheses.h" - "internal/transform_args.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::debugging - absl::type_traits - absl::strings - absl::utility - gmock_main - TESTONLY -) - -absl_cc_test( - NAME - conformance_testing_test - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - ${ABSL_EXCEPTIONS_FLAG} - LINKOPTS - ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} - DEPS - absl::conformance_testing - absl::type_traits - gmock_main -) - -absl_cc_test( - NAME - conformance_testing_test_no_exceptions - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::conformance_testing - absl::type_traits - gmock_main -) - -absl_cc_library( - NAME - variant - HDRS - "variant.h" - SRCS - "internal/variant.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_variant_access - absl::base_internal - absl::config - absl::core_headers - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_test( - NAME - variant_test - SRCS - "variant_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::variant - absl::config - absl::core_headers - absl::memory - absl::type_traits - absl::strings - gmock_main -) - -absl_cc_library( - NAME - compare - HDRS - "compare.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::type_traits - PUBLIC -) - -absl_cc_test( - NAME - compare_test - SRCS - "compare_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::compare - 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 - SRCS - "variant_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::variant - absl::config - absl::exception_safety_testing - absl::memory - gmock_main -) -endif() diff --git a/third_party/abseil_cpp/absl/types/any.h b/third_party/abseil_cpp/absl/types/any.h deleted file mode 100644 index fc5a07469f80..000000000000 --- a/third_party/abseil_cpp/absl/types/any.h +++ /dev/null @@ -1,528 +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. -// -// ----------------------------------------------------------------------------- -// any.h -// ----------------------------------------------------------------------------- -// -// This header file define the `absl::any` type for holding a type-safe value -// of any type. The 'absl::any` type is useful for providing a way to hold -// something that is, as yet, unspecified. Such unspecified types -// traditionally are passed between API boundaries until they are later cast to -// their "destination" types. To cast to such a destination type, use -// `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it -// to an explicit type; implicit conversions will throw. -// -// Example: -// -// auto a = absl::any(65); -// absl::any_cast<int>(a); // 65 -// absl::any_cast<char>(a); // throws absl::bad_any_cast -// absl::any_cast<std::string>(a); // throws absl::bad_any_cast -// -// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction -// and is designed to be a drop-in replacement for code compliant with C++17. -// -// Traditionally, the behavior of casting to a temporary unspecified type has -// been accomplished with the `void *` paradigm, where the pointer was to some -// other unspecified type. `absl::any` provides an "owning" version of `void *` -// that avoids issues of pointer management. -// -// Note: just as in the case of `void *`, use of `absl::any` (and its C++17 -// version `std::any`) is a code smell indicating that your API might not be -// constructed correctly. We have seen that most uses of `any` are unwarranted, -// and `absl::any`, like `std::any`, is difficult to use properly. Before using -// this abstraction, make sure that you should not instead be rewriting your -// code to be more specific. -// -// Abseil has also released an `absl::variant` type (a C++11 compatible version -// of the C++17 `std::variant`), which is generally preferred for use over -// `absl::any`. -#ifndef ABSL_TYPES_ANY_H_ -#define ABSL_TYPES_ANY_H_ - -#include "absl/base/config.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_ANY - -#include <any> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::any; -using std::any_cast; -using std::bad_any_cast; -using std::make_any; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_ANY - -#include <algorithm> -#include <cstddef> -#include <initializer_list> -#include <memory> -#include <stdexcept> -#include <type_traits> -#include <typeinfo> -#include <utility> - -#include "absl/base/internal/fast_type_id.h" -#include "absl/base/macros.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_any_cast.h" - -// NOTE: This macro is an implementation detail that is undefined at the bottom -// of the file. It is not intended for expansion directly from user code. -#ifdef ABSL_ANY_DETAIL_HAS_RTTI -#error ABSL_ANY_DETAIL_HAS_RTTI cannot be directly set -#elif !defined(__GNUC__) || defined(__GXX_RTTI) -#define ABSL_ANY_DETAIL_HAS_RTTI 1 -#endif // !defined(__GNUC__) || defined(__GXX_RTTI) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class any; - -// swap() -// -// Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are -// `absl::any` types. -void swap(any& x, any& y) noexcept; - -// make_any() -// -// Constructs an `absl::any` of type `T` with the given arguments. -template <typename T, typename... Args> -any make_any(Args&&... args); - -// Overload of `absl::make_any()` for constructing an `absl::any` type from an -// initializer list. -template <typename T, typename U, typename... Args> -any make_any(std::initializer_list<U> il, Args&&... args); - -// any_cast() -// -// Statically casts the value of a `const absl::any` type to the given type. -// This function will throw `absl::bad_any_cast` if the stored value type of the -// `absl::any` does not match the cast. -// -// `any_cast()` can also be used to get a reference to the internal storage iff -// a reference type is passed as its `ValueType`: -// -// Example: -// -// absl::any my_any = std::vector<int>(); -// absl::any_cast<std::vector<int>&>(my_any).push_back(42); -template <typename ValueType> -ValueType any_cast(const any& operand); - -// Overload of `any_cast()` to statically cast the value of a non-const -// `absl::any` type to the given type. This function will throw -// `absl::bad_any_cast` if the stored value type of the `absl::any` does not -// match the cast. -template <typename ValueType> -ValueType any_cast(any& operand); // NOLINT(runtime/references) - -// Overload of `any_cast()` to statically cast the rvalue of an `absl::any` -// type. This function will throw `absl::bad_any_cast` if the stored value type -// of the `absl::any` does not match the cast. -template <typename ValueType> -ValueType any_cast(any&& operand); - -// Overload of `any_cast()` to statically cast the value of a const pointer -// `absl::any` type to the given pointer type, or `nullptr` if the stored value -// type of the `absl::any` does not match the cast. -template <typename ValueType> -const ValueType* any_cast(const any* operand) noexcept; - -// Overload of `any_cast()` to statically cast the value of a pointer -// `absl::any` type to the given pointer type, or `nullptr` if the stored value -// type of the `absl::any` does not match the cast. -template <typename ValueType> -ValueType* any_cast(any* operand) noexcept; - -// ----------------------------------------------------------------------------- -// absl::any -// ----------------------------------------------------------------------------- -// -// An `absl::any` object provides the facility to either store an instance of a -// type, known as the "contained object", or no value. An `absl::any` is used to -// store values of types that are unknown at compile time. The `absl::any` -// object, when containing a value, must contain a value type; storing a -// reference type is neither desired nor supported. -// -// An `absl::any` can only store a type that is copy-constructible; move-only -// types are not allowed within an `any` object. -// -// Example: -// -// auto a = absl::any(65); // Literal, copyable -// auto b = absl::any(std::vector<int>()); // Default-initialized, copyable -// std::unique_ptr<Foo> my_foo; -// auto c = absl::any(std::move(my_foo)); // Error, not copy-constructible -// -// Note that `absl::any` makes use of decayed types (`absl::decay_t` in this -// context) to remove const-volatile qualifiers (known as "cv qualifiers"), -// decay functions to function pointers, etc. We essentially "decay" a given -// type into its essential type. -// -// `absl::any` makes use of decayed types when determining the basic type `T` of -// the value to store in the any's contained object. In the documentation below, -// we explicitly denote this by using the phrase "a decayed type of `T`". -// -// Example: -// -// const int a = 4; -// absl::any foo(a); // Decay ensures we store an "int", not a "const int&". -// -// void my_function() {} -// absl::any bar(my_function); // Decay ensures we store a function pointer. -// -// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction -// and is designed to be a drop-in replacement for code compliant with C++17. -class any { - private: - template <typename T> - struct IsInPlaceType; - - public: - // Constructors - - // Constructs an empty `absl::any` object (`any::has_value()` will return - // `false`). - constexpr any() noexcept; - - // Copy constructs an `absl::any` object with a "contained object" of the - // passed type of `other` (or an empty `absl::any` if `other.has_value()` is - // `false`. - any(const any& other) - : obj_(other.has_value() ? other.obj_->Clone() - : std::unique_ptr<ObjInterface>()) {} - - // Move constructs an `absl::any` object with a "contained object" of the - // passed type of `other` (or an empty `absl::any` if `other.has_value()` is - // `false`). - any(any&& other) noexcept = default; - - // Constructs an `absl::any` object with a "contained object" of the decayed - // type of `T`, which is initialized via `std::forward<T>(value)`. - // - // This constructor will not participate in overload resolution if the - // decayed type of `T` is not copy-constructible. - template < - typename T, typename VT = absl::decay_t<T>, - absl::enable_if_t<!absl::disjunction< - std::is_same<any, VT>, IsInPlaceType<VT>, - absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr> - any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {} - - // Constructs an `absl::any` object with a "contained object" of the decayed - // type of `T`, which is initialized via `std::forward<T>(value)`. - template <typename T, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<absl::conjunction< - std::is_copy_constructible<VT>, - std::is_constructible<VT, Args...>>::value>* = nullptr> - explicit any(in_place_type_t<T> /*tag*/, Args&&... args) - : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {} - - // Constructs an `absl::any` object with a "contained object" of the passed - // type `VT` as a decayed type of `T`. `VT` is initialized as if - // direct-non-list-initializing an object of type `VT` with the arguments - // `initializer_list, std::forward<Args>(args)...`. - template < - typename T, typename U, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t< - absl::conjunction<std::is_copy_constructible<VT>, - std::is_constructible<VT, std::initializer_list<U>&, - Args...>>::value>* = nullptr> - explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist, - Args&&... args) - : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {} - - // Assignment operators - - // Copy assigns an `absl::any` object with a "contained object" of the - // passed type. - any& operator=(const any& rhs) { - any(rhs).swap(*this); - return *this; - } - - // Move assigns an `absl::any` object with a "contained object" of the - // passed type. `rhs` is left in a valid but otherwise unspecified state. - any& operator=(any&& rhs) noexcept { - any(std::move(rhs)).swap(*this); - return *this; - } - - // Assigns an `absl::any` object with a "contained object" of the passed type. - template <typename T, typename VT = absl::decay_t<T>, - absl::enable_if_t<absl::conjunction< - absl::negation<std::is_same<VT, any>>, - std::is_copy_constructible<VT>>::value>* = nullptr> - any& operator=(T&& rhs) { - any tmp(in_place_type_t<VT>(), std::forward<T>(rhs)); - tmp.swap(*this); - return *this; - } - - // Modifiers - - // any::emplace() - // - // Emplaces a value within an `absl::any` object by calling `any::reset()`, - // initializing the contained value as if direct-non-list-initializing an - // object of type `VT` with the arguments `std::forward<Args>(args)...`, and - // returning a reference to the new contained value. - // - // Note: If an exception is thrown during the call to `VT`'s constructor, - // `*this` does not contain a value, and any previously contained value has - // been destroyed. - template < - typename T, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<std::is_copy_constructible<VT>::value && - std::is_constructible<VT, Args...>::value>* = nullptr> - VT& emplace(Args&&... args) { - reset(); // NOTE: reset() is required here even in the world of exceptions. - Obj<VT>* const object_ptr = - new Obj<VT>(in_place, std::forward<Args>(args)...); - obj_ = std::unique_ptr<ObjInterface>(object_ptr); - return object_ptr->value; - } - - // Overload of `any::emplace()` to emplace a value within an `absl::any` - // object by calling `any::reset()`, initializing the contained value as if - // direct-non-list-initializing an object of type `VT` with the arguments - // `initializer_list, std::forward<Args>(args)...`, and returning a reference - // to the new contained value. - // - // Note: If an exception is thrown during the call to `VT`'s constructor, - // `*this` does not contain a value, and any previously contained value has - // been destroyed. The function shall not participate in overload resolution - // unless `is_copy_constructible_v<VT>` is `true` and - // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`. - template < - typename T, typename U, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<std::is_copy_constructible<VT>::value && - std::is_constructible<VT, std::initializer_list<U>&, - Args...>::value>* = nullptr> - VT& emplace(std::initializer_list<U> ilist, Args&&... args) { - reset(); // NOTE: reset() is required here even in the world of exceptions. - Obj<VT>* const object_ptr = - new Obj<VT>(in_place, ilist, std::forward<Args>(args)...); - obj_ = std::unique_ptr<ObjInterface>(object_ptr); - return object_ptr->value; - } - - // any::reset() - // - // Resets the state of the `absl::any` object, destroying the contained object - // if present. - void reset() noexcept { obj_ = nullptr; } - - // any::swap() - // - // Swaps the passed value and the value of this `absl::any` object. - void swap(any& other) noexcept { obj_.swap(other.obj_); } - - // Observers - - // any::has_value() - // - // Returns `true` if the `any` object has a contained value, otherwise - // returns `false`. - bool has_value() const noexcept { return obj_ != nullptr; } - -#if ABSL_ANY_DETAIL_HAS_RTTI - // Returns: typeid(T) if *this has a contained object of type T, otherwise - // typeid(void). - const std::type_info& type() const noexcept { - if (has_value()) { - return obj_->Type(); - } - - return typeid(void); - } -#endif // ABSL_ANY_DETAIL_HAS_RTTI - - private: - // Tagged type-erased abstraction for holding a cloneable object. - class ObjInterface { - public: - virtual ~ObjInterface() = default; - virtual std::unique_ptr<ObjInterface> Clone() const = 0; - virtual const void* ObjTypeId() const noexcept = 0; -#if ABSL_ANY_DETAIL_HAS_RTTI - virtual const std::type_info& Type() const noexcept = 0; -#endif // ABSL_ANY_DETAIL_HAS_RTTI - }; - - // Hold a value of some queryable type, with an ability to Clone it. - template <typename T> - class Obj : public ObjInterface { - public: - template <typename... Args> - explicit Obj(in_place_t /*tag*/, Args&&... args) - : value(std::forward<Args>(args)...) {} - - std::unique_ptr<ObjInterface> Clone() const final { - return std::unique_ptr<ObjInterface>(new Obj(in_place, value)); - } - - const void* ObjTypeId() const noexcept final { return IdForType<T>(); } - -#if ABSL_ANY_DETAIL_HAS_RTTI - const std::type_info& Type() const noexcept final { return typeid(T); } -#endif // ABSL_ANY_DETAIL_HAS_RTTI - - T value; - }; - - std::unique_ptr<ObjInterface> CloneObj() const { - if (!obj_) return nullptr; - return obj_->Clone(); - } - - template <typename T> - constexpr static const void* IdForType() { - // Note: This type dance is to make the behavior consistent with typeid. - using NormalizedType = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - - return base_internal::FastTypeId<NormalizedType>(); - } - - const void* GetObjTypeId() const { - return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>(); - } - - // `absl::any` nonmember functions // - - // Description at the declaration site (top of file). - template <typename ValueType> - friend ValueType any_cast(const any& operand); - - // Description at the declaration site (top of file). - template <typename ValueType> - friend ValueType any_cast(any& operand); // NOLINT(runtime/references) - - // Description at the declaration site (top of file). - template <typename T> - friend const T* any_cast(const any* operand) noexcept; - - // Description at the declaration site (top of file). - template <typename T> - friend T* any_cast(any* operand) noexcept; - - std::unique_ptr<ObjInterface> obj_; -}; - -// ----------------------------------------------------------------------------- -// Implementation Details -// ----------------------------------------------------------------------------- - -constexpr any::any() noexcept = default; - -template <typename T> -struct any::IsInPlaceType : std::false_type {}; - -template <typename T> -struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {}; - -inline void swap(any& x, any& y) noexcept { x.swap(y); } - -// Description at the declaration site (top of file). -template <typename T, typename... Args> -any make_any(Args&&... args) { - return any(in_place_type_t<T>(), std::forward<Args>(args)...); -} - -// Description at the declaration site (top of file). -template <typename T, typename U, typename... Args> -any make_any(std::initializer_list<U> il, Args&&... args) { - return any(in_place_type_t<T>(), il, std::forward<Args>(args)...); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(const any& operand) { - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, const U&>::value, - "Invalid ValueType"); - auto* const result = (any_cast<U>)(&operand); - if (result == nullptr) { - any_internal::ThrowBadAnyCast(); - } - return static_cast<ValueType>(*result); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(any& operand) { // NOLINT(runtime/references) - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, U&>::value, - "Invalid ValueType"); - auto* result = (any_cast<U>)(&operand); - if (result == nullptr) { - any_internal::ThrowBadAnyCast(); - } - return static_cast<ValueType>(*result); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(any&& operand) { - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, U>::value, - "Invalid ValueType"); - return static_cast<ValueType>(std::move((any_cast<U&>)(operand))); -} - -// Description at the declaration site (top of file). -template <typename T> -const T* any_cast(const any* operand) noexcept { - using U = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - return operand && operand->GetObjTypeId() == any::IdForType<U>() - ? std::addressof( - static_cast<const any::Obj<U>*>(operand->obj_.get())->value) - : nullptr; -} - -// Description at the declaration site (top of file). -template <typename T> -T* any_cast(any* operand) noexcept { - using U = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - return operand && operand->GetObjTypeId() == any::IdForType<U>() - ? std::addressof( - static_cast<any::Obj<U>*>(operand->obj_.get())->value) - : nullptr; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_ANY_DETAIL_HAS_RTTI - -#endif // ABSL_USES_STD_ANY - -#endif // ABSL_TYPES_ANY_H_ diff --git a/third_party/abseil_cpp/absl/types/any_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/any_exception_safety_test.cc deleted file mode 100644 index 31c1140135f0..000000000000 --- a/third_party/abseil_cpp/absl/types/any_exception_safety_test.cc +++ /dev/null @@ -1,173 +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/types/any.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::any is an alias for std::any and when -// exceptions are not enabled. -#if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS) - -#include <typeinfo> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -using Thrower = testing::ThrowingValue<>; -using NoThrowMoveThrower = - testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using ThrowerList = std::initializer_list<Thrower>; -using ThrowerVec = std::vector<Thrower>; -using ThrowingAlloc = testing::ThrowingAllocator<Thrower>; -using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>; - -namespace { - -testing::AssertionResult AnyInvariants(absl::any* a) { - using testing::AssertionFailure; - using testing::AssertionSuccess; - - if (a->has_value()) { - if (a->type() == typeid(void)) { - return AssertionFailure() - << "A non-empty any should not have type `void`"; - } - } else { - if (a->type() != typeid(void)) { - return AssertionFailure() - << "An empty any should have type void, but has type " - << a->type().name(); - } - } - - // Make sure that reset() changes any to a valid state. - a->reset(); - if (a->has_value()) { - return AssertionFailure() << "A reset `any` should be valueless"; - } - if (a->type() != typeid(void)) { - return AssertionFailure() << "A reset `any` should have type() of `void`, " - "but instead has type " - << a->type().name(); - } - try { - auto unused = absl::any_cast<Thrower>(*a); - static_cast<void>(unused); - return AssertionFailure() - << "A reset `any` should not be able to be any_cast"; - } catch (const absl::bad_any_cast&) { - } catch (...) { - return AssertionFailure() - << "Unexpected exception thrown from absl::any_cast"; - } - return AssertionSuccess(); -} - -testing::AssertionResult AnyIsEmpty(absl::any* a) { - if (!a->has_value()) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "a should be empty, but instead has value " - << absl::any_cast<Thrower>(*a).Get(); -} - -TEST(AnyExceptionSafety, Ctors) { - Thrower val(1); - testing::TestThrowingCtor<absl::any>(val); - - Thrower copy(val); - testing::TestThrowingCtor<absl::any>(copy); - - testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1); - - testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(), - ThrowerList{val}); - - testing::TestThrowingCtor<absl::any, - absl::in_place_type_t<ThrowingThrowerVec>, - ThrowerList, ThrowingAlloc>( - absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc()); -} - -TEST(AnyExceptionSafety, Assignment) { - auto original = - absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor); - auto any_is_strong = [original](absl::any* ap) { - return testing::AssertionResult(ap->has_value() && - absl::any_cast<Thrower>(original) == - absl::any_cast<Thrower>(*ap)); - }; - auto any_strong_tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(original) - .WithContracts(AnyInvariants, any_is_strong); - - Thrower val(2); - absl::any any_val(val); - NoThrowMoveThrower mv_val(2); - - auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; }; - auto assign_val = [&val](absl::any* ap) { *ap = val; }; - auto move = [&val](absl::any* ap) { *ap = std::move(val); }; - auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); }; - - EXPECT_TRUE(any_strong_tester.Test(assign_any)); - EXPECT_TRUE(any_strong_tester.Test(assign_val)); - EXPECT_TRUE(any_strong_tester.Test(move)); - EXPECT_TRUE(any_strong_tester.Test(move_movable)); - - auto empty_any_is_strong = [](absl::any* ap) { - return testing::AssertionResult{!ap->has_value()}; - }; - auto strong_empty_any_tester = - testing::MakeExceptionSafetyTester() - .WithInitialValue(absl::any{}) - .WithContracts(AnyInvariants, empty_any_is_strong); - - EXPECT_TRUE(strong_empty_any_tester.Test(assign_any)); - EXPECT_TRUE(strong_empty_any_tester.Test(assign_val)); - EXPECT_TRUE(strong_empty_any_tester.Test(move)); -} - -TEST(AnyExceptionSafety, Emplace) { - auto initial_val = - absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor}; - auto one_tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(initial_val) - .WithContracts(AnyInvariants, AnyIsEmpty); - - auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); }; - auto emp_throwervec = [](absl::any* ap) { - std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)}; - ap->emplace<ThrowerVec>(il); - }; - auto emp_movethrower = [](absl::any* ap) { - ap->emplace<NoThrowMoveThrower>(2); - }; - - EXPECT_TRUE(one_tester.Test(emp_thrower)); - EXPECT_TRUE(one_tester.Test(emp_throwervec)); - EXPECT_TRUE(one_tester.Test(emp_movethrower)); - - auto empty_tester = one_tester.WithInitialValue(absl::any{}); - - EXPECT_TRUE(empty_tester.Test(emp_thrower)); - EXPECT_TRUE(empty_tester.Test(emp_throwervec)); -} - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/types/any_test.cc b/third_party/abseil_cpp/absl/types/any_test.cc deleted file mode 100644 index 70e4ba22b12b..000000000000 --- a/third_party/abseil_cpp/absl/types/any_test.cc +++ /dev/null @@ -1,781 +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/types/any.h" - -// This test is a no-op when absl::any is an alias for std::any. -#if !defined(ABSL_USES_STD_ANY) - -#include <initializer_list> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/exception_testing.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/container/internal/test_instance_tracker.h" - -namespace { -using absl::test_internal::CopyableOnlyInstance; -using absl::test_internal::InstanceTracker; - -template <typename T> -const T& AsConst(const T& t) { - return t; -} - -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int value) : value(value) {} - MoveOnly(MoveOnly&&) = default; - MoveOnly& operator=(MoveOnly&&) = default; - - int value = 0; -}; - -struct CopyOnly { - CopyOnly() = default; - explicit CopyOnly(int value) : value(value) {} - CopyOnly(CopyOnly&&) = delete; - CopyOnly& operator=(CopyOnly&&) = delete; - CopyOnly(const CopyOnly&) = default; - CopyOnly& operator=(const CopyOnly&) = default; - - int value = 0; -}; - -struct MoveOnlyWithListConstructor { - MoveOnlyWithListConstructor() = default; - explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/, - int value) - : value(value) {} - MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default; - MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) = - default; - - int value = 0; -}; - -struct IntMoveOnlyCopyOnly { - IntMoveOnlyCopyOnly(int value, MoveOnly /*move_only*/, CopyOnly /*copy_only*/) - : value(value) {} - - int value; -}; - -struct ListMoveOnlyCopyOnly { - ListMoveOnlyCopyOnly(std::initializer_list<int> ilist, MoveOnly /*move_only*/, - CopyOnly /*copy_only*/) - : values(ilist) {} - - std::vector<int> values; -}; - -using FunctionType = void(); -void FunctionToEmplace() {} - -using ArrayType = int[2]; -using DecayedArray = absl::decay_t<ArrayType>; - -TEST(AnyTest, Noexcept) { - static_assert(std::is_nothrow_default_constructible<absl::any>(), ""); - static_assert(std::is_nothrow_move_constructible<absl::any>(), ""); - static_assert(std::is_nothrow_move_assignable<absl::any>(), ""); - static_assert(noexcept(std::declval<absl::any&>().has_value()), ""); - static_assert(noexcept(std::declval<absl::any&>().type()), ""); - static_assert(noexcept(absl::any_cast<int>(std::declval<absl::any*>())), ""); - static_assert( - noexcept(std::declval<absl::any&>().swap(std::declval<absl::any&>())), - ""); - - using std::swap; - static_assert( - noexcept(swap(std::declval<absl::any&>(), std::declval<absl::any&>())), - ""); -} - -TEST(AnyTest, HasValue) { - absl::any o; - EXPECT_FALSE(o.has_value()); - o.emplace<int>(); - EXPECT_TRUE(o.has_value()); - o.reset(); - EXPECT_FALSE(o.has_value()); -} - -TEST(AnyTest, Type) { - absl::any o; - EXPECT_EQ(typeid(void), o.type()); - o.emplace<int>(5); - EXPECT_EQ(typeid(int), o.type()); - o.emplace<float>(5.f); - EXPECT_EQ(typeid(float), o.type()); - o.reset(); - EXPECT_EQ(typeid(void), o.type()); -} - -TEST(AnyTest, EmptyPointerCast) { - // pointer-to-unqualified overload - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<int>(&o)); - o.emplace<int>(); - EXPECT_NE(nullptr, absl::any_cast<int>(&o)); - o.reset(); - EXPECT_EQ(nullptr, absl::any_cast<int>(&o)); - } - - // pointer-to-const overload - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o))); - o.emplace<int>(); - EXPECT_NE(nullptr, absl::any_cast<int>(&AsConst(o))); - o.reset(); - EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o))); - } -} - -TEST(AnyTest, InPlaceConstruction) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<IntMoveOnlyCopyOnly>(), 5, MoveOnly(), - copy_only); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<IntMoveOnlyCopyOnly>, 5, MoveOnly(), - copy_only); - auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithCV) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<const volatile IntMoveOnlyCopyOnly>(), 5, - MoveOnly(), copy_only); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<const volatile IntMoveOnlyCopyOnly>, 5, - MoveOnly(), copy_only); - auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithFunction) { - absl::any o(absl::in_place_type_t<FunctionType>(), FunctionToEmplace); - FunctionType*& construction_result = absl::any_cast<FunctionType*&>(o); - EXPECT_EQ(&FunctionToEmplace, construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) { - absl::any o(absl::in_place_type<FunctionType>, FunctionToEmplace); - auto& construction_result = absl::any_cast<FunctionType*&>(o); - EXPECT_EQ(&FunctionToEmplace, construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithArray) { - ArrayType ar = {5, 42}; - absl::any o(absl::in_place_type_t<ArrayType>(), ar); - DecayedArray& construction_result = absl::any_cast<DecayedArray&>(o); - EXPECT_EQ(&ar[0], construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) { - ArrayType ar = {5, 42}; - absl::any o(absl::in_place_type<ArrayType>, ar); - auto& construction_result = absl::any_cast<DecayedArray&>(o); - EXPECT_EQ(&ar[0], construction_result); -} - -TEST(AnyTest, InPlaceConstructionIlist) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<ListMoveOnlyCopyOnly>(), {1, 2, 3, 4}, - MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<ListMoveOnlyCopyOnly>, {1, 2, 3, 4}, - MoveOnly(), copy_only); - auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistWithCV) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<const volatile ListMoveOnlyCopyOnly>(), - {1, 2, 3, 4}, MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<const volatile ListMoveOnlyCopyOnly>, - {1, 2, 3, 4}, MoveOnly(), copy_only); - auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceNoArgs) { - absl::any o(absl::in_place_type_t<int>{}); - EXPECT_EQ(0, absl::any_cast<int&>(o)); -} - -TEST(AnyTest, InPlaceNoArgsVariableTemplate) { - absl::any o(absl::in_place_type<int>); - EXPECT_EQ(0, absl::any_cast<int&>(o)); -} - -template <typename Enabler, typename T, typename... Args> -struct CanEmplaceAnyImpl : std::false_type {}; - -template <typename T, typename... Args> -struct CanEmplaceAnyImpl< - absl::void_t<decltype( - std::declval<absl::any&>().emplace<T>(std::declval<Args>()...))>, - T, Args...> : std::true_type {}; - -template <typename T, typename... Args> -using CanEmplaceAny = CanEmplaceAnyImpl<void, T, Args...>; - -TEST(AnyTest, Emplace) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE((std::is_same<decltype(o.emplace<IntMoveOnlyCopyOnly>( - 5, MoveOnly(), copy_only)), - IntMoveOnlyCopyOnly&>::value)); - IntMoveOnlyCopyOnly& emplace_result = - o.emplace<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - EXPECT_EQ(5, emplace_result.value); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); - EXPECT_EQ(&emplace_result, &v); - - static_assert(!CanEmplaceAny<int, int, int>::value, ""); - static_assert(!CanEmplaceAny<MoveOnly, MoveOnly>::value, ""); -} - -TEST(AnyTest, EmplaceWithCV) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<const volatile IntMoveOnlyCopyOnly>( - 5, MoveOnly(), copy_only)), - IntMoveOnlyCopyOnly&>::value)); - IntMoveOnlyCopyOnly& emplace_result = - o.emplace<const volatile IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - EXPECT_EQ(5, emplace_result.value); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); - EXPECT_EQ(&emplace_result, &v); -} - -TEST(AnyTest, EmplaceWithFunction) { - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<FunctionType>(FunctionToEmplace)), - FunctionType*&>::value)); - FunctionType*& emplace_result = o.emplace<FunctionType>(FunctionToEmplace); - EXPECT_EQ(&FunctionToEmplace, emplace_result); -} - -TEST(AnyTest, EmplaceWithArray) { - absl::any o; - ArrayType ar = {5, 42}; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<ArrayType>(ar)), DecayedArray&>::value)); - DecayedArray& emplace_result = o.emplace<ArrayType>(ar); - EXPECT_EQ(&ar[0], emplace_result); -} - -TEST(AnyTest, EmplaceIlist) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE((std::is_same<decltype(o.emplace<ListMoveOnlyCopyOnly>( - {1, 2, 3, 4}, MoveOnly(), copy_only)), - ListMoveOnlyCopyOnly&>::value)); - ListMoveOnlyCopyOnly& emplace_result = - o.emplace<ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - EXPECT_EQ(&v, &emplace_result); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); - - static_assert(!CanEmplaceAny<int, std::initializer_list<int>>::value, ""); - static_assert(!CanEmplaceAny<MoveOnlyWithListConstructor, - std::initializer_list<int>, int>::value, - ""); -} - -TEST(AnyTest, EmplaceIlistWithCV) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<const volatile ListMoveOnlyCopyOnly>( - {1, 2, 3, 4}, MoveOnly(), copy_only)), - ListMoveOnlyCopyOnly&>::value)); - ListMoveOnlyCopyOnly& emplace_result = - o.emplace<const volatile ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(), - copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - EXPECT_EQ(&v, &emplace_result); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, EmplaceNoArgs) { - absl::any o; - o.emplace<int>(); - EXPECT_EQ(0, absl::any_cast<int>(o)); -} - -TEST(AnyTest, ConversionConstruction) { - { - absl::any o = 5; - EXPECT_EQ(5, absl::any_cast<int>(o)); - } - - { - const CopyOnly copy_only(5); - absl::any o = copy_only; - EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value); - } - - static_assert(!std::is_convertible<MoveOnly, absl::any>::value, ""); -} - -TEST(AnyTest, ConversionAssignment) { - { - absl::any o; - o = 5; - EXPECT_EQ(5, absl::any_cast<int>(o)); - } - - { - const CopyOnly copy_only(5); - absl::any o; - o = copy_only; - EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value); - } - - static_assert(!std::is_assignable<MoveOnly, absl::any>::value, ""); -} - -// Suppress MSVC warnings. -// 4521: multiple copy constructors specified -// We wrote multiple of them to test that the correct overloads are selected. -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4521) -#endif - -// Weird type for testing, only used to make sure we "properly" perfect-forward -// when being placed into an absl::any (use the l-value constructor if given an -// l-value rather than use the copy constructor). -struct WeirdConstructor42 { - explicit WeirdConstructor42(int value) : value(value) {} - - // Copy-constructor - WeirdConstructor42(const WeirdConstructor42& other) : value(other.value) {} - - // L-value "weird" constructor (used when given an l-value) - WeirdConstructor42( - WeirdConstructor42& /*other*/) // NOLINT(runtime/references) - : value(42) {} - - int value; -}; -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -TEST(AnyTest, WeirdConversionConstruction) { - { - const WeirdConstructor42 source(5); - absl::any o = source; // Actual copy - EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value); - } - - { - WeirdConstructor42 source(5); - absl::any o = source; // Weird "conversion" - EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value); - } -} - -TEST(AnyTest, WeirdConversionAssignment) { - { - const WeirdConstructor42 source(5); - absl::any o; - o = source; // Actual copy - EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value); - } - - { - WeirdConstructor42 source(5); - absl::any o; - o = source; // Weird "conversion" - EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value); - } -} - -struct Value {}; - -TEST(AnyTest, AnyCastValue) { - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int>(o)); - EXPECT_EQ(5, absl::any_cast<int>(AsConst(o))); - static_assert( - std::is_same<decltype(absl::any_cast<Value>(o)), Value>::value, ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(o)); - EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o))); - static_assert(std::is_same<decltype(absl::any_cast<const Value>(o)), - const Value>::value, - ""); - } -} - -TEST(AnyTest, AnyCastReference) { - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int&>(o)); - EXPECT_EQ(5, absl::any_cast<const int&>(AsConst(o))); - static_assert( - std::is_same<decltype(absl::any_cast<Value&>(o)), Value&>::value, ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(o)); - EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o))); - static_assert(std::is_same<decltype(absl::any_cast<const Value&>(o)), - const Value&>::value, - ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int&&>(std::move(o))); - static_assert(std::is_same<decltype(absl::any_cast<Value&&>(std::move(o))), - Value&&>::value, - ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(std::move(o))); - static_assert( - std::is_same<decltype(absl::any_cast<const Value&&>(std::move(o))), - const Value&&>::value, - ""); - } -} - -TEST(AnyTest, AnyCastPointer) { - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<char>(&o)); - o.emplace<int>(5); - EXPECT_EQ(nullptr, absl::any_cast<char>(&o)); - o.emplace<char>('a'); - EXPECT_EQ('a', *absl::any_cast<char>(&o)); - static_assert( - std::is_same<decltype(absl::any_cast<Value>(&o)), Value*>::value, ""); - } - - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<const char>(&o)); - o.emplace<int>(5); - EXPECT_EQ(nullptr, absl::any_cast<const char>(&o)); - o.emplace<char>('a'); - EXPECT_EQ('a', *absl::any_cast<const char>(&o)); - static_assert(std::is_same<decltype(absl::any_cast<const Value>(&o)), - const Value*>::value, - ""); - } -} - -TEST(AnyTest, MakeAny) { - const CopyOnly copy_only{}; - auto o = absl::make_any<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - static_assert(std::is_same<decltype(o), absl::any>::value, ""); - EXPECT_EQ(5, absl::any_cast<IntMoveOnlyCopyOnly&>(o).value); -} - -TEST(AnyTest, MakeAnyIList) { - const CopyOnly copy_only{}; - auto o = - absl::make_any<ListMoveOnlyCopyOnly>({1, 2, 3}, MoveOnly(), copy_only); - static_assert(std::is_same<decltype(o), absl::any>::value, ""); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3}; - EXPECT_EQ(expected_values, v.values); -} - -// Test the use of copy constructor and operator= -TEST(AnyTest, Copy) { - InstanceTracker tracker_raii; - - { - absl::any o(absl::in_place_type<CopyableOnlyInstance>, 123); - CopyableOnlyInstance* f1 = absl::any_cast<CopyableOnlyInstance>(&o); - - absl::any o2(o); - const CopyableOnlyInstance* f2 = absl::any_cast<CopyableOnlyInstance>(&o2); - EXPECT_EQ(123, f2->value()); - EXPECT_NE(f1, f2); - - absl::any o3; - o3 = o2; - const CopyableOnlyInstance* f3 = absl::any_cast<CopyableOnlyInstance>(&o3); - EXPECT_EQ(123, f3->value()); - EXPECT_NE(f2, f3); - - const absl::any o4(4); - // copy construct from const lvalue ref. - absl::any o5 = o4; - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_EQ(4, absl::any_cast<int>(o5)); - - // Copy construct from const rvalue ref. - absl::any o6 = std::move(o4); // NOLINT - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_EQ(4, absl::any_cast<int>(o6)); - } -} - -TEST(AnyTest, Move) { - InstanceTracker tracker_raii; - - absl::any any1; - any1.emplace<CopyableOnlyInstance>(5); - - // This is a copy, so copy count increases to 1. - absl::any any2 = any1; - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any1).value()); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any2).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - // This isn't a copy, so copy count doesn't increase. - absl::any any3 = std::move(any2); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any3).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - absl::any any4; - any4 = std::move(any3); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any4).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - absl::any tmp4(4); - absl::any o4(std::move(tmp4)); // move construct - EXPECT_EQ(4, absl::any_cast<int>(o4)); - o4 = *&o4; // self assign - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_TRUE(o4.has_value()); - - absl::any o5; - absl::any tmp5(5); - o5 = std::move(tmp5); // move assign - EXPECT_EQ(5, absl::any_cast<int>(o5)); -} - -// Reset the ObjectOwner with an object of a different type -TEST(AnyTest, Reset) { - absl::any o; - o.emplace<int>(); - - o.reset(); - EXPECT_FALSE(o.has_value()); - - o.emplace<char>(); - EXPECT_TRUE(o.has_value()); -} - -TEST(AnyTest, ConversionConstructionCausesOneCopy) { - InstanceTracker tracker_raii; - CopyableOnlyInstance counter(5); - absl::any o(counter); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(o).value()); - EXPECT_EQ(1, tracker_raii.copies()); -} - -////////////////////////////////// -// Tests for Exception Behavior // -////////////////////////////////// - -#if defined(ABSL_USES_STD_ANY) - -// If using a std `any` implementation, we can't check for a specific message. -#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \ - "") - -#else - -// If using the absl `any` implementation, we can rely on a specific message. -#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \ - "Bad any cast") - -#endif // defined(ABSL_USES_STD_ANY) - -TEST(AnyTest, ThrowBadAlloc) { - { - absl::any a; - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(absl::any{})); - - // const absl::any operand - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(AsConst(a))); - } - - { - absl::any a(absl::in_place_type<int>); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST( - absl::any_cast<const float&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(absl::any{})); - - // const absl::any operand - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(AsConst(a))); - } -} - -class BadCopy {}; - -struct BadCopyable { - BadCopyable() = default; - BadCopyable(BadCopyable&&) = default; - BadCopyable(const BadCopyable&) { -#ifdef ABSL_HAVE_EXCEPTIONS - throw BadCopy(); -#else - ABSL_RAW_LOG(FATAL, "Bad copy"); -#endif - } -}; - -#define ABSL_ANY_TEST_EXPECT_BAD_COPY(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), BadCopy, "Bad copy") - -// Test the guarantees regarding exceptions in copy/assign. -TEST(AnyTest, FailedCopy) { - { - const BadCopyable bad{}; - ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{bad}); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src}); - } - - { - BadCopyable bad; - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad); - } - - { - BadCopyable bad; - absl::any target(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad); - EXPECT_TRUE(target.has_value()); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); - EXPECT_FALSE(target.has_value()); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - absl::any target(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); - EXPECT_TRUE(target.has_value()); - } -} - -// Test the guarantees regarding exceptions in emplace. -TEST(AnyTest, FailedEmplace) { - { - BadCopyable bad; - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad)); - } - - { - BadCopyable bad; - absl::any target(absl::in_place_type<int>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad)); -#if defined(ABSL_USES_STD_ANY) && defined(__GLIBCXX__) - // libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an - // exception is thrown, *this contains a value. -#define ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG 1 -#endif -#if defined(ABSL_HAVE_EXCEPTIONS) && \ - !defined(ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG) - EXPECT_FALSE(target.has_value()); -#endif - } -} - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_ANY) diff --git a/third_party/abseil_cpp/absl/types/bad_any_cast.cc b/third_party/abseil_cpp/absl/types/bad_any_cast.cc deleted file mode 100644 index b0592cc9bcc5..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_any_cast.cc +++ /dev/null @@ -1,46 +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/types/bad_any_cast.h" - -#ifndef ABSL_USES_STD_ANY - -#include <cstdlib> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -bad_any_cast::~bad_any_cast() = default; - -const char* bad_any_cast::what() const noexcept { return "Bad any cast"; } - -namespace any_internal { - -void ThrowBadAnyCast() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_any_cast(); -#else - ABSL_RAW_LOG(FATAL, "Bad any cast"); - std::abort(); -#endif -} - -} // namespace any_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_ANY diff --git a/third_party/abseil_cpp/absl/types/bad_any_cast.h b/third_party/abseil_cpp/absl/types/bad_any_cast.h deleted file mode 100644 index 114cef80cdde..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_any_cast.h +++ /dev/null @@ -1,75 +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. -// -// ----------------------------------------------------------------------------- -// bad_any_cast.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::bad_any_cast` type. - -#ifndef ABSL_TYPES_BAD_ANY_CAST_H_ -#define ABSL_TYPES_BAD_ANY_CAST_H_ - -#include <typeinfo> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_ANY - -#include <any> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_any_cast; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_ANY - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// bad_any_cast -// ----------------------------------------------------------------------------- -// -// An `absl::bad_any_cast` type is an exception type that is thrown when -// failing to successfully cast the return value of an `absl::any` object. -// -// Example: -// -// auto a = absl::any(65); -// absl::any_cast<int>(a); // 65 -// try { -// absl::any_cast<char>(a); -// } catch(const absl::bad_any_cast& e) { -// std::cout << "Bad any cast: " << e.what() << '\n'; -// } -class bad_any_cast : public std::bad_cast { - public: - ~bad_any_cast() override; - const char* what() const noexcept override; -}; - -namespace any_internal { - -[[noreturn]] void ThrowBadAnyCast(); - -} // namespace any_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_ANY - -#endif // ABSL_TYPES_BAD_ANY_CAST_H_ diff --git a/third_party/abseil_cpp/absl/types/bad_optional_access.cc b/third_party/abseil_cpp/absl/types/bad_optional_access.cc deleted file mode 100644 index 26aca70d9cff..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_optional_access.cc +++ /dev/null @@ -1,48 +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/types/bad_optional_access.h" - -#ifndef ABSL_USES_STD_OPTIONAL - -#include <cstdlib> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -bad_optional_access::~bad_optional_access() = default; - -const char* bad_optional_access::what() const noexcept { - return "optional has no value"; -} - -namespace optional_internal { - -void throw_bad_optional_access() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_optional_access(); -#else - ABSL_RAW_LOG(FATAL, "Bad optional access"); - abort(); -#endif -} - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_OPTIONAL diff --git a/third_party/abseil_cpp/absl/types/bad_optional_access.h b/third_party/abseil_cpp/absl/types/bad_optional_access.h deleted file mode 100644 index a500286adc42..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_optional_access.h +++ /dev/null @@ -1,78 +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. -// -// ----------------------------------------------------------------------------- -// bad_optional_access.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::bad_optional_access` type. - -#ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ -#define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ - -#include <stdexcept> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_OPTIONAL - -#include <optional> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_optional_access; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_OPTIONAL - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// bad_optional_access -// ----------------------------------------------------------------------------- -// -// An `absl::bad_optional_access` type is an exception type that is thrown when -// attempting to access an `absl::optional` object that does not contain a -// value. -// -// Example: -// -// absl::optional<int> o; -// -// try { -// int n = o.value(); -// } catch(const absl::bad_optional_access& e) { -// std::cout << "Bad optional access: " << e.what() << '\n'; -// } -class bad_optional_access : public std::exception { - public: - bad_optional_access() = default; - ~bad_optional_access() override; - const char* what() const noexcept override; -}; - -namespace optional_internal { - -// throw delegator -[[noreturn]] void throw_bad_optional_access(); - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_OPTIONAL - -#endif // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ diff --git a/third_party/abseil_cpp/absl/types/bad_variant_access.cc b/third_party/abseil_cpp/absl/types/bad_variant_access.cc deleted file mode 100644 index 3dc88cc09f23..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_variant_access.cc +++ /dev/null @@ -1,64 +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/types/bad_variant_access.h" - -#ifndef ABSL_USES_STD_VARIANT - -#include <cstdlib> -#include <stdexcept> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -////////////////////////// -// [variant.bad.access] // -////////////////////////// - -bad_variant_access::~bad_variant_access() = default; - -const char* bad_variant_access::what() const noexcept { - return "Bad variant access"; -} - -namespace variant_internal { - -void ThrowBadVariantAccess() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_variant_access(); -#else - ABSL_RAW_LOG(FATAL, "Bad variant access"); - abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn. -#endif -} - -void Rethrow() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw; -#else - ABSL_RAW_LOG(FATAL, - "Internal error in absl::variant implementation. Attempted to " - "rethrow an exception when building with exceptions disabled."); - abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn. -#endif -} - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_VARIANT diff --git a/third_party/abseil_cpp/absl/types/bad_variant_access.h b/third_party/abseil_cpp/absl/types/bad_variant_access.h deleted file mode 100644 index 095969f91eee..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_variant_access.h +++ /dev/null @@ -1,82 +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. -// -// ----------------------------------------------------------------------------- -// bad_variant_access.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::bad_variant_access` type. - -#ifndef ABSL_TYPES_BAD_VARIANT_ACCESS_H_ -#define ABSL_TYPES_BAD_VARIANT_ACCESS_H_ - -#include <stdexcept> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_VARIANT - -#include <variant> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_variant_access; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_VARIANT - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// bad_variant_access -// ----------------------------------------------------------------------------- -// -// An `absl::bad_variant_access` type is an exception type that is thrown in -// the following cases: -// -// * Calling `absl::get(absl::variant) with an index or type that does not -// match the currently selected alternative type -// * Calling `absl::visit on an `absl::variant` that is in the -// `variant::valueless_by_exception` state. -// -// Example: -// -// absl::variant<int, std::string> v; -// v = 1; -// try { -// absl::get<std::string>(v); -// } catch(const absl::bad_variant_access& e) { -// std::cout << "Bad variant access: " << e.what() << '\n'; -// } -class bad_variant_access : public std::exception { - public: - bad_variant_access() noexcept = default; - ~bad_variant_access() override; - const char* what() const noexcept override; -}; - -namespace variant_internal { - -[[noreturn]] void ThrowBadVariantAccess(); -[[noreturn]] void Rethrow(); - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_VARIANT - -#endif // ABSL_TYPES_BAD_VARIANT_ACCESS_H_ diff --git a/third_party/abseil_cpp/absl/types/compare.h b/third_party/abseil_cpp/absl/types/compare.h deleted file mode 100644 index 19b076e7f19c..000000000000 --- a/third_party/abseil_cpp/absl/types/compare.h +++ /dev/null @@ -1,600 +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. -// -// ----------------------------------------------------------------------------- -// compare.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::weak_equality`, `absl::strong_equality`, -// `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering` -// types for storing the results of three way comparisons. -// -// Example: -// absl::weak_ordering compare(const std::string& a, const std::string& b); -// -// These are C++11 compatible versions of the C++20 corresponding types -// (`std::weak_equality`, etc.) and are designed to be drop-in replacements -// for code compliant with C++20. - -#ifndef ABSL_TYPES_COMPARE_H_ -#define ABSL_TYPES_COMPARE_H_ - -#include <cstddef> -#include <cstdint> -#include <cstdlib> -#include <type_traits> - -#include "absl/base/attributes.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace compare_internal { - -using value_type = int8_t; - -template <typename T> -struct Fail { - static_assert(sizeof(T) < 0, "Only literal `0` is allowed."); -}; - -// We need the NullPtrT template to avoid triggering the modernize-use-nullptr -// ClangTidy warning in user code. -template <typename NullPtrT = std::nullptr_t> -struct OnlyLiteralZero { - constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT - - // Fails compilation when `nullptr` or integral type arguments other than - // `int` are passed. This constructor doesn't accept `int` because literal `0` - // has type `int`. Literal `0` arguments will be implicitly converted to - // `std::nullptr_t` and accepted by the above constructor, while other `int` - // arguments will fail to be converted and cause compilation failure. - template < - typename T, - typename = typename std::enable_if< - std::is_same<T, std::nullptr_t>::value || - (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type, - typename = typename Fail<T>::type> - OnlyLiteralZero(T); // NOLINT -}; - -enum class eq : value_type { - equal = 0, - equivalent = equal, - nonequal = 1, - nonequivalent = nonequal, -}; - -enum class ord : value_type { less = -1, greater = 1 }; - -enum class ncmp : value_type { unordered = -127 }; - -// Define macros to allow for creation or emulation of C++17 inline variables -// based on whether the feature is supported. Note: we can't use -// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of -// incomplete types so they need to be defined after the types are complete. -#ifdef __cpp_inline_variables - -// A no-op expansion that can be followed by a semicolon at class level. -#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "") - -#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ - static const type name - -#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ - inline constexpr type type::name(init) - -#else // __cpp_inline_variables - -#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \ - ABSL_CONST_INIT static const T name - -// A no-op expansion that can be followed by a semicolon at class level. -#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "") - -#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ - template <typename T> \ - const T compare_internal::type##_base<T>::name(init) - -#endif // __cpp_inline_variables - -// These template base classes allow for defining the values of the constants -// in the header file (for performance) without using inline variables (which -// aren't available in C++11). -template <typename T> -struct weak_equality_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); -}; - -template <typename T> -struct strong_equality_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); -}; - -template <typename T> -struct partial_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); - ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered); -}; - -template <typename T> -struct weak_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); -}; - -template <typename T> -struct strong_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); -}; - -} // namespace compare_internal - -class weak_equality - : public compare_internal::weak_equality_base<weak_equality> { - explicit constexpr weak_equality(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::weak_equality_base<weak_equality>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent); - - // Comparisons - friend constexpr bool operator==( - weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - weak_equality v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - weak_equality v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator==(weak_equality v1, - weak_equality v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(weak_equality v1, - weak_equality v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent, - compare_internal::eq::nonequivalent); - -class strong_equality - : public compare_internal::strong_equality_base<strong_equality> { - explicit constexpr strong_equality(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::strong_equality_base<strong_equality>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent); - - // Conversion - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - // Comparisons - friend constexpr bool operator==( - strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - strong_equality v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - strong_equality v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator==(strong_equality v1, - strong_equality v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(strong_equality v1, - strong_equality v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal); -ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal, - compare_internal::eq::nonequal); -ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent, - compare_internal::eq::nonequivalent); - -class partial_ordering - : public compare_internal::partial_ordering_base<partial_ordering> { - explicit constexpr partial_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr partial_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::partial_ordering_base<partial_ordering>; - - constexpr bool is_ordered() const noexcept { - return value_ != - compare_internal::value_type(compare_internal::ncmp::unordered); - } - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); - - // Conversion - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - // Comparisons - friend constexpr bool operator==( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ == 0; - } - friend constexpr bool operator!=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return !v.is_ordered() || v.value_ != 0; - } - friend constexpr bool operator<( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ < 0; - } - friend constexpr bool operator<=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ <= 0; - } - friend constexpr bool operator>( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ > 0; - } - friend constexpr bool operator>=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return !v.is_ordered() || 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 >= v.value_; - } - friend constexpr bool operator==(partial_ordering v1, - partial_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(partial_ordering v1, - partial_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(partial_ordering, greater, - compare_internal::ord::greater); -ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered, - compare_internal::ncmp::unordered); - -class weak_ordering - : public compare_internal::weak_ordering_base<weak_ordering> { - explicit constexpr weak_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr weak_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::weak_ordering_base<weak_ordering>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater); - - // Conversions - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - constexpr operator partial_ordering() const noexcept { // NOLINT - return value_ == 0 ? partial_ordering::equivalent - : (value_ < 0 ? partial_ordering::less - : partial_ordering::greater); - } - // Comparisons - friend constexpr bool operator==( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator<( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ < 0; - } - friend constexpr bool operator<=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ <= 0; - } - friend constexpr bool operator>( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ > 0; - } - friend constexpr bool operator>=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 >= v.value_; - } - friend constexpr bool operator==(weak_ordering v1, - weak_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(weak_ordering v1, - weak_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(weak_ordering, greater, - compare_internal::ord::greater); - -class strong_ordering - : public compare_internal::strong_ordering_base<strong_ordering> { - explicit constexpr strong_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr strong_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::strong_ordering_base<strong_ordering>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater); - - // Conversions - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - constexpr operator strong_equality() const noexcept { // NOLINT - return value_ == 0 ? strong_equality::equal : strong_equality::nonequal; - } - constexpr operator partial_ordering() const noexcept { // NOLINT - return value_ == 0 ? partial_ordering::equivalent - : (value_ < 0 ? partial_ordering::less - : partial_ordering::greater); - } - constexpr operator weak_ordering() const noexcept { // NOLINT - return value_ == 0 - ? weak_ordering::equivalent - : (value_ < 0 ? weak_ordering::less : weak_ordering::greater); - } - // Comparisons - friend constexpr bool operator==( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator<( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ < 0; - } - friend constexpr bool operator<=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ <= 0; - } - friend constexpr bool operator>( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ > 0; - } - friend constexpr bool operator>=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 >= v.value_; - } - friend constexpr bool operator==(strong_ordering v1, - strong_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(strong_ordering v1, - strong_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal); -ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(strong_ordering, greater, - compare_internal::ord::greater); - -#undef ABSL_COMPARE_INLINE_BASECLASS_DECL -#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL -#undef ABSL_COMPARE_INLINE_INIT - -namespace compare_internal { -// We also provide these comparator adapter functions for internal absl use. - -// Helper functions to do a boolean comparison of two keys given a boolean -// or three-way comparator. -// SFINAE prevents implicit conversions to bool (such as from int). -template <typename Bool, - absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0> -constexpr bool compare_result_as_less_than(const Bool r) { return r; } -constexpr bool compare_result_as_less_than(const absl::weak_ordering r) { - return r < 0; -} - -template <typename Compare, typename K, typename LK> -constexpr bool do_less_than_comparison(const Compare &compare, const K &x, - const LK &y) { - return compare_result_as_less_than(compare(x, y)); -} - -// Helper functions to do a three-way comparison of two keys given a boolean or -// three-way comparator. -// SFINAE prevents implicit conversions to int (such as from bool). -template <typename Int, - absl::enable_if_t<std::is_same<int, Int>::value, int> = 0> -constexpr absl::weak_ordering compare_result_as_ordering(const Int c) { - return c < 0 ? absl::weak_ordering::less - : c == 0 ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; -} -constexpr absl::weak_ordering compare_result_as_ordering( - const absl::weak_ordering c) { - return c; -} - -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { - return compare_result_as_ordering(compare(x, y)); -} -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { - return compare(x, y) ? absl::weak_ordering::less - : compare(y, x) ? absl::weak_ordering::greater - : absl::weak_ordering::equivalent; -} - -} // namespace compare_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_COMPARE_H_ diff --git a/third_party/abseil_cpp/absl/types/compare_test.cc b/third_party/abseil_cpp/absl/types/compare_test.cc deleted file mode 100644 index 8095baf9569f..000000000000 --- a/third_party/abseil_cpp/absl/types/compare_test.cc +++ /dev/null @@ -1,389 +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/types/compare.h" - -#include "gtest/gtest.h" -#include "absl/base/casts.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -// This is necessary to avoid a bunch of lint warnings suggesting that we use -// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0` -// to an int, which can't be converted to the unspecified zero type. -bool Identity(bool b) { return b; } - -TEST(Compare, WeakEquality) { - EXPECT_TRUE(Identity(weak_equality::equivalent == 0)); - EXPECT_TRUE(Identity(0 == weak_equality::equivalent)); - EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0)); - EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent)); - const weak_equality values[] = {weak_equality::equivalent, - weak_equality::nonequivalent}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, StrongEquality) { - EXPECT_TRUE(Identity(strong_equality::equal == 0)); - EXPECT_TRUE(Identity(0 == strong_equality::equal)); - EXPECT_TRUE(Identity(strong_equality::nonequal != 0)); - EXPECT_TRUE(Identity(0 != strong_equality::nonequal)); - EXPECT_TRUE(Identity(strong_equality::equivalent == 0)); - EXPECT_TRUE(Identity(0 == strong_equality::equivalent)); - EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0)); - EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent)); - const strong_equality values[] = {strong_equality::equal, - strong_equality::nonequal}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } - EXPECT_TRUE(Identity(strong_equality::equivalent == strong_equality::equal)); - EXPECT_TRUE( - Identity(strong_equality::nonequivalent == strong_equality::nonequal)); -} - -TEST(Compare, PartialOrdering) { - EXPECT_TRUE(Identity(partial_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > partial_ordering::less)); - EXPECT_TRUE(Identity(partial_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= partial_ordering::less)); - EXPECT_TRUE(Identity(partial_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == partial_ordering::equivalent)); - EXPECT_TRUE(Identity(partial_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < partial_ordering::greater)); - EXPECT_TRUE(Identity(partial_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= partial_ordering::greater)); - EXPECT_TRUE(Identity(partial_ordering::unordered != 0)); - EXPECT_TRUE(Identity(0 != partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered < 0)); - EXPECT_FALSE(Identity(0 < partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered <= 0)); - EXPECT_FALSE(Identity(0 <= partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered > 0)); - EXPECT_FALSE(Identity(0 > partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered >= 0)); - EXPECT_FALSE(Identity(0 >= partial_ordering::unordered)); - const partial_ordering values[] = { - partial_ordering::less, partial_ordering::equivalent, - partial_ordering::greater, partial_ordering::unordered}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, WeakOrdering) { - EXPECT_TRUE(Identity(weak_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > weak_ordering::less)); - EXPECT_TRUE(Identity(weak_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= weak_ordering::less)); - EXPECT_TRUE(Identity(weak_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == weak_ordering::equivalent)); - EXPECT_TRUE(Identity(weak_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < weak_ordering::greater)); - EXPECT_TRUE(Identity(weak_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= weak_ordering::greater)); - const weak_ordering values[] = { - weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, StrongOrdering) { - EXPECT_TRUE(Identity(strong_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > strong_ordering::less)); - EXPECT_TRUE(Identity(strong_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= strong_ordering::less)); - EXPECT_TRUE(Identity(strong_ordering::equal == 0)); - EXPECT_TRUE(Identity(0 == strong_ordering::equal)); - EXPECT_TRUE(Identity(strong_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == strong_ordering::equivalent)); - EXPECT_TRUE(Identity(strong_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < strong_ordering::greater)); - EXPECT_TRUE(Identity(strong_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= strong_ordering::greater)); - const strong_ordering values[] = { - strong_ordering::less, strong_ordering::equal, strong_ordering::greater}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } - EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal)); -} - -TEST(Compare, Conversions) { - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::nonequal) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::equivalent) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<weak_equality>(strong_equality::nonequivalent) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::less) != 0)); - EXPECT_TRUE(Identity( - implicit_cast<weak_equality>(partial_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::unordered) != 0)); - - EXPECT_TRUE(implicit_cast<weak_equality>(weak_ordering::less) != 0); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(weak_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(weak_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0)); - EXPECT_TRUE(Identity( - implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::equal) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<strong_equality>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0)); -} - -struct WeakOrderingLess { - template <typename T> - absl::weak_ordering operator()(const T& a, const T& b) const { - return a < b ? absl::weak_ordering::less - : a == b ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; - } -}; - -TEST(CompareResultAsLessThan, SanityTest) { - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false)); - EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true)); - - EXPECT_TRUE( - absl::compare_internal::compare_result_as_less_than(weak_ordering::less)); - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than( - weak_ordering::equivalent)); - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than( - weak_ordering::greater)); -} - -TEST(DoLessThanComparison, SanityTest) { - std::less<int> less; - WeakOrderingLess weak; - - EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0)); - EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0)); - - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10)); - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10)); - - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5)); - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5)); -} - -TEST(CompareResultAsOrdering, SanityTest) { - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) < 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) == 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) > 0)); - - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(0) < 0)); - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(0) == 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(0) > 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) < 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) == 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) > 0)); - - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(1) < 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(1) == 0)); - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(1) > 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) < 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) == 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) > 0)); -} - -TEST(DoThreeWayComparison, SanityTest) { - std::less<int> less; - WeakOrderingLess weak; - - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0)); - - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0)); - - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0)); -} - -#ifdef __cpp_inline_variables -TEST(Compare, StaticAsserts) { - static_assert(weak_equality::equivalent == 0, ""); - static_assert(weak_equality::nonequivalent != 0, ""); - - static_assert(strong_equality::equal == 0, ""); - static_assert(strong_equality::nonequal != 0, ""); - static_assert(strong_equality::equivalent == 0, ""); - static_assert(strong_equality::nonequivalent != 0, ""); - - static_assert(partial_ordering::less < 0, ""); - static_assert(partial_ordering::equivalent == 0, ""); - static_assert(partial_ordering::greater > 0, ""); - static_assert(partial_ordering::unordered != 0, ""); - - static_assert(weak_ordering::less < 0, ""); - static_assert(weak_ordering::equivalent == 0, ""); - static_assert(weak_ordering::greater > 0, ""); - - static_assert(strong_ordering::less < 0, ""); - static_assert(strong_ordering::equal == 0, ""); - static_assert(strong_ordering::equivalent == 0, ""); - static_assert(strong_ordering::greater > 0, ""); -} -#endif // __cpp_inline_variables - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h b/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h deleted file mode 100644 index 0cc6884e309e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h +++ /dev/null @@ -1,447 +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. -// -// ----------------------------------------------------------------------------- -// regularity_aliases.h -// ----------------------------------------------------------------------------- -// -// This file contains type aliases of common ConformanceProfiles and Archetypes -// so that they can be directly used by name without creating them from scratch. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ - -#include "absl/types/internal/conformance_archetype.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Creates both a Profile and a corresponding Archetype with root name "name". -#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...) \ - struct name##Profile : __VA_ARGS__ {}; \ - \ - using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \ - \ - template <class AbslInternalProfileTag> \ - using name##Archetype##_ = ::absl::types_internal::Archetype< \ - ::absl::types_internal::StrongProfileTypedef<name##Profile, \ - AbslInternalProfileTag>> - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDefaultConstructor, - ConformanceProfile<default_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDefaultConstructor, - ConformanceProfile<default_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDefaultConstructor, ConformanceProfile<default_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, - inequality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasStdHashSpecialization, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::maybe, hashable::yes>); - -//////////////////////////////////////////////////////////////////////////////// -//// The remaining aliases are combinations of the previous aliases. //// -//////////////////////////////////////////////////////////////////////////////// - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Comparable, - CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile, - HasGreaterEqualProfile, HasGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowEquatable, - CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowComparable, - CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile, - HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile, - HasNothrowGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Value, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowMoveAssignProfile, HasCopyAssignProfile, - HasNothrowDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleValue, - CombineProfiles<HasDefaultConstructorProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMoveConstructible, - CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMoveConstructible, - CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMoveConstructible, - CombineProfiles<HasDefaultConstructorProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - CopyConstructible, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableCopyConstructible, - CombineProfiles<EquatableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableCopyConstructible, - CombineProfiles<ComparableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleCopyConstructible, - CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMovable, - CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowMoveAssignProfile, HasNothrowDestructorProfile, - HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMovable, - CombineProfiles<EquatableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMovable, - CombineProfiles<ComparableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMovable, - CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TrivialSpecialMemberFunctions, - CombineProfiles<HasTrivialDefaultConstructorProfile, - HasTrivialMoveConstructorProfile, - HasTrivialCopyConstructorProfile, - HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile, - HasTrivialDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TriviallyComplete, - CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile, - HasStdHashSpecializationProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMoveConstructible, - CombineProfiles<HasStdHashSpecializationProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableCopyConstructible, - CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMovable, - CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableValue, - CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableHashableValue, - CombineProfiles<HashableValueProfile, ComparableProfile>); - -// The "preferred" profiles that we support in Abseil. -template <template <class...> class Receiver> -using ExpandBasicProfiles = - Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile>; - -// The basic profiles except that they are also all Equatable. -template <template <class...> class Receiver> -using ExpandBasicEquatableProfiles = - Receiver<EquatableNothrowMoveConstructibleProfile, - EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile, - EquatableValueProfile>; - -// The basic profiles except that they are also all Comparable. -template <template <class...> class Receiver> -using ExpandBasicComparableProfiles = - Receiver<ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, - ComparableNothrowMovableProfile, ComparableValueProfile>; - -// The basic profiles except that they are also all Hashable. -template <template <class...> class Receiver> -using ExpandBasicHashableProfiles = - Receiver<HashableNothrowMoveConstructibleProfile, - HashableCopyConstructibleProfile, HashableNothrowMovableProfile, - HashableValueProfile>; - -// The basic profiles except that they are also all DefaultConstructible. -template <template <class...> class Receiver> -using ExpandBasicDefaultConstructibleProfiles = - Receiver<DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, - DefaultConstructibleValueProfile>; - -// The type profiles that we support in Abseil (all of the previous lists). -template <template <class...> class Receiver> -using ExpandSupportedProfiles = Receiver< - NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile, - EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile, - EquatableNothrowMovableProfile, EquatableValueProfile, - ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile, - ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile, - HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile, - HashableNothrowMovableProfile, HashableValueProfile>; - -// TODO(calabrese) Include types that have throwing move constructors, since in -// practice we still need to support them because of standard library types with -// (potentially) non-noexcept moves. - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h b/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h deleted file mode 100644 index 2349e0f72635..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h +++ /dev/null @@ -1,978 +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_archetype.h -// ----------------------------------------------------------------------------- -// -// This file contains a facility for generating "archetypes" of out of -// "Conformance Profiles" (see "conformance_profiles.h" for more information -// about Conformance Profiles). An archetype is a type that aims to support the -// bare minimum requirements of a given Conformance Profile. For instance, an -// archetype that corresponds to an ImmutableProfile has exactly a nothrow -// move-constructor, a potentially-throwing copy constructor, a nothrow -// destructor, with all other special-member-functions deleted. These archetypes -// are useful for testing to make sure that templates are able to work with the -// kinds of types that they claim to support (i.e. that they do not accidentally -// under-constrain), -// -// The main type template in this file is the Archetype template, which takes -// a Conformance Profile as a template argument and its instantiations are a -// minimum-conforming model of that profile. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ - -#include <cstddef> -#include <functional> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// A minimum-conforming implementation of a type with properties specified in -// `Prof`, where `Prof` is a valid Conformance Profile. -template <class Prof, class /*Enabler*/ = void> -class Archetype; - -// Given an Archetype, obtain the properties of the profile associated with that -// archetype. -template <class Archetype> -struct PropertiesOfArchetype; - -template <class Prof> -struct PropertiesOfArchetype<Archetype<Prof>> { - using type = PropertiesOfT<Prof>; -}; - -template <class Archetype> -using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type; - -// A metafunction to determine if a type is an `Archetype`. -template <class T> -struct IsArchetype : std::false_type {}; - -template <class Prof> -struct IsArchetype<Archetype<Prof>> : std::true_type {}; - -// A constructor tag type used when creating an Archetype with internal state. -struct MakeArchetypeState {}; - -// Data stored within an archetype that is copied/compared/hashed when the -// corresponding operations are used. -using ArchetypeState = std::size_t; - -//////////////////////////////////////////////////////////////////////////////// -// This section of the file defines a chain of base classes for Archetype, // -// where each base defines a specific special member function with the // -// appropriate properties (deleted, noexcept(false), noexcept, or trivial). // -//////////////////////////////////////////////////////////////////////////////// - -// The bottom-most base, which contains the state and the default constructor. -template <default_constructible DefaultConstructibleValue> -struct ArchetypeStateBase { - static_assert(DefaultConstructibleValue == default_constructible::yes || - DefaultConstructibleValue == default_constructible::nothrow, - ""); - - ArchetypeStateBase() noexcept( - DefaultConstructibleValue == - default_constructible:: - nothrow) /*Vacuous archetype_state initialization*/ {} - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::maybe> { - explicit ArchetypeStateBase() = delete; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::trivial> { - ArchetypeStateBase() = default; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -// The move-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeMoveConstructor - : ArchetypeStateBase<DefaultConstructibleValue> { - static_assert(MoveConstructibleValue == move_constructible::yes || - MoveConstructibleValue == move_constructible::nothrow, - ""); - - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; - ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept( - MoveConstructibleValue == move_constructible::nothrow) - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - other.archetype_state) {} - ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default; - ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default; - ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue> -struct ArchetypeMoveConstructor<DefaultConstructibleValue, - move_constructible::trivial> - : ArchetypeStateBase<DefaultConstructibleValue> { - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; -}; - -// The copy-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeCopyConstructor - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - static_assert(CopyConstructibleValue == copy_constructible::yes || - CopyConstructibleValue == copy_constructible::nothrow, - ""); - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept( - CopyConstructibleValue == copy_constructible::nothrow) - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>( - MakeArchetypeState(), other.archetype_state) {} - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::maybe> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete; - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::trivial> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; -}; - -// The move-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeMoveAssign - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - static_assert(MoveAssignableValue == move_assignable::yes || - MoveAssignableValue == move_assignable::nothrow, - ""); - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; - ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default; - ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default; - ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept( - MoveAssignableValue == move_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } - - ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, move_assignable::trivial> - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; -}; - -// The copy-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeCopyAssign - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - static_assert(CopyAssignableValue == copy_assignable::yes || - CopyAssignableValue == copy_assignable::nothrow, - ""); - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept( - CopyAssignableValue == copy_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::maybe> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::trivial> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; -}; - -// The destructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -struct ArchetypeDestructor - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - static_assert(DestructibleValue == destructible::yes || - DestructibleValue == destructible::nothrow, - ""); - - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; - ArchetypeDestructor(ArchetypeDestructor&&) = default; - ArchetypeDestructor(const ArchetypeDestructor&) = default; - ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default; - ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default; - ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {} -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue, destructible::trivial> - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; -}; - -// An alias to the top of the chain of bases for special-member functions. -// NOTE: move_constructible::maybe, move_assignable::maybe, and -// destructible::maybe are handled in the top-level type by way of SFINAE. -// Because of this, we never instantiate the base classes with -// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so -// that we minimize the number of different possible type-template -// instantiations. -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -using ArchetypeSpecialMembersBase = ArchetypeDestructor< - DefaultConstructibleValue, - MoveConstructibleValue != move_constructible::maybe - ? MoveConstructibleValue - : move_constructible::nothrow, - CopyConstructibleValue, - MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue - : move_assignable::nothrow, - CopyAssignableValue, - DestructibleValue != destructible::maybe ? DestructibleValue - : destructible::nothrow>; - -// A function that is used to create an archetype with some associated state. -template <class Arch> -Arch MakeArchetype(ArchetypeState state) noexcept { - static_assert(IsArchetype<Arch>::value, - "The explicit template argument to MakeArchetype is required " - "to be an Archetype."); - return Arch(MakeArchetypeState(), state); -} - -// This is used to conditionally delete "copy" and "move" constructors in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteConstructor() { - return !((PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_constructible_support != - copy_constructible::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// This is used to conditionally delete "copy" and "move" assigns in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteAssign() { - return !( - (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// TODO(calabrese) Inherit from a chain of secondary bases to pull in the -// associated functions of other concepts. -template <class Prof, class Enabler> -class Archetype : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - static_assert(std::is_same<Enabler, void>::value, - "An explicit type must not be passed as the second template " - "argument to 'Archetype`."); - - // The cases mentioned in these static_asserts are expected to be handled in - // the partial template specializations of Archetype that follow this - // definition. - static_assert(PropertiesOfT<Prof>::destructible_support != - destructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe || - PropertiesOfT<Prof>::copy_constructible_support == - copy_constructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe || - PropertiesOfT<Prof>::copy_assignable_support == - copy_assignable::maybe, - ""); - - public: - Archetype() = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -// Explicitly deleted swap for Archetype if the profile does not require swap. -// It is important to delete it rather than simply leave it out so that the -// "using std::swap;" idiom will result in this deleted overload being picked. -template <class Prof, - absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>&, Archetype<Prof>&) = delete; // NOLINT - -// A conditionally-noexcept swap implementation for Archetype when the profile -// supports swap. -template <class Prof, - absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs) // NOLINT - noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) { - std::swap(lhs.archetype_state, rhs.archetype_state); -} - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -struct NothrowBool { - explicit NothrowBool() = delete; - ~NothrowBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // NothrowBool(NothrowBool const&) = delete; - - NothrowBool& operator=(NothrowBool const&) = delete; - - explicit operator bool() const noexcept { return value; } - - static NothrowBool make(bool const value) noexcept { - return NothrowBool(value); - } - - private: - explicit NothrowBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -// Note: ExceptionalBool has a conversion operator that is not noexcept, so -// that even when a comparison operator is noexcept, that operation may still -// potentially throw when converted to bool. -struct ExceptionalBool { - explicit ExceptionalBool() = delete; - ~ExceptionalBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // ExceptionalBool(ExceptionalBool const&) = delete; - - ExceptionalBool& operator=(ExceptionalBool const&) = delete; - - explicit operator bool() const { return value; } // NOLINT - - static ExceptionalBool make(bool const value) noexcept { - return ExceptionalBool(value); - } - - private: - explicit ExceptionalBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// The following macro is only used as a helper in this file to stamp out -// comparison operator definitions. It is undefined after usage. -// -// NOTE: Non-nothrow operators throw via their result's conversion to bool even -// though the operation itself is noexcept. -#define ABSL_TYPES_INTERNAL_OP(enum_name, op) \ - template <class Prof> \ - absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \ - const Archetype<Prof>&, const Archetype<Prof>&) = delete; \ - \ - template <class Prof> \ - typename absl::enable_if_t< \ - PropertiesOfT<Prof>::is_##enum_name, \ - std::conditional<PropertiesOfT<Prof>::enum_name##_support == \ - enum_name::nothrow, \ - NothrowBool, ExceptionalBool>>::type \ - operator op(const Archetype<Prof>& lhs, \ - const Archetype<Prof>& rhs) noexcept { \ - return absl::conditional_t< \ - PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow, \ - NothrowBool, ExceptionalBool>::make(lhs.archetype_state op \ - rhs.archetype_state); \ - } - -ABSL_TYPES_INTERNAL_OP(equality_comparable, ==); -ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=); -ABSL_TYPES_INTERNAL_OP(less_than_comparable, <); -ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=); -ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=); -ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >); - -#undef ABSL_TYPES_INTERNAL_OP - -// Base class for std::hash specializations when an Archetype doesn't support -// hashing. -struct PoisonedHash { - PoisonedHash() = delete; - PoisonedHash(const PoisonedHash&) = delete; - PoisonedHash& operator=(const PoisonedHash&) = delete; -}; - -// Base class for std::hash specializations when an Archetype supports hashing. -template <class Prof> -struct EnabledHash { - using argument_type = Archetype<Prof>; - using result_type = std::size_t; - result_type operator()(const argument_type& arg) const { - return std::hash<ArchetypeState>()(arg.archetype_state); - } -}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -template <class Prof> // NOLINT -struct hash<::absl::types_internal::Archetype<Prof>> - : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable, - ::absl::types_internal::EnabledHash<Prof>, - ::absl::types_internal::PoisonedHash>::type {}; - -} // namespace std - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h b/third_party/abseil_cpp/absl/types/internal/conformance_profile.h deleted file mode 100644 index cf64ff4fcd1e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h +++ /dev/null @@ -1,931 +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_profiles.h -// ----------------------------------------------------------------------------- -// -// This file contains templates for representing "Regularity Profiles" and -// concisely-named versions of commonly used Regularity Profiles. -// -// A Regularity Profile is a compile-time description of the types of operations -// that a given type supports, along with properties of those operations when -// they do exist. For instance, a Regularity Profile may describe a type that -// has a move-constructor that is noexcept and a copy constructor that is not -// noexcept. This description can then be examined and passed around to other -// templates for the purposes of asserting expectations on user-defined types -// via a series trait checks, or for determining what kinds of run-time tests -// are able to be performed. -// -// Regularity Profiles are also used when creating "archetypes," which are -// minimum-conforming types that meet all of the requirements of a given -// Regularity Profile. For more information regarding archetypes, see -// "conformance_archetypes.h". - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ - -#include <set> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/algorithm/container.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/internal/conformance_testing_helpers.h" -#include "absl/utility/utility.h" - -// TODO(calabrese) Add support for extending profiles. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Converts an enum to its underlying integral value. -template <typename Enum> -constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) { - return static_cast<absl::underlying_type_t<Enum>>(value); -} - -// A tag type used in place of a matcher when checking that an assertion result -// does not actually contain any errors. -struct NoError {}; - -// ----------------------------------------------------------------------------- -// ConformanceErrors -// ----------------------------------------------------------------------------- -class ConformanceErrors { - public: - // Setup the error reporting mechanism by seeding it with the name of the type - // that is being tested. - explicit ConformanceErrors(std::string type_name) - : assertion_result_(false), type_name_(std::move(type_name)) { - assertion_result_ << "\n\n" - "Assuming the following type alias:\n" - "\n" - " using _T = " - << type_name_ << ";\n\n"; - outputDivider(); - } - - // Adds the test name to the list of successfully run tests iff it was not - // previously reported as failing. This behavior is useful for tests that - // have multiple parts, where failures and successes are reported individually - // with the same test name. - void addTestSuccess(absl::string_view test_name) { - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If the test is already reported as failing, do not add it to the list of - // successes. - if (test_failures_.find(normalized_test_name) == test_failures_.end()) { - test_successes_.insert(std::move(normalized_test_name)); - } - } - - // Streams a single error description into the internal buffer (a visual - // divider is automatically inserted after the error so that multiple errors - // are visibly distinct). - // - // This function increases the error count by 1. - // - // TODO(calabrese) Determine desired behavior when if this function throws. - template <class... P> - void addTestFailure(absl::string_view test_name, const P&... args) { - // Output a message related to the test failure. - assertion_result_ << "\n\n" - "Failed test: " - << test_name << "\n\n"; - addTestFailureImpl(args...); - assertion_result_ << "\n\n"; - outputDivider(); - - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If previous parts of this test succeeded, remove it from that set. - test_successes_.erase(normalized_test_name); - - // Add the test name to the list of failed tests. - test_failures_.insert(std::move(normalized_test_name)); - - has_error_ = true; - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. - ::testing::AssertionResult assertionResult() const { - return has_error_ ? assertion_result_ : ::testing::AssertionSuccess(); - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. This overload expects errors, using the specified - // matcher. - ::testing::AssertionResult expectFailedTests( - const std::set<std::string>& test_names) const { - // Since we are expecting nonconformance, output an error message when the - // type actually conformed to the specified profile. - if (!has_error_) { - return ::testing::AssertionFailure() - << "Unexpected conformance of type:\n" - " " - << type_name_ << "\n\n"; - } - - // Get a list of all expected failures that did not actually fail - // (or that were not run). - std::vector<std::string> nonfailing_tests; - absl::c_set_difference(test_names, test_failures_, - std::back_inserter(nonfailing_tests)); - - // Get a list of all "expected failures" that were never actually run. - std::vector<std::string> unrun_tests; - absl::c_set_difference(nonfailing_tests, test_successes_, - std::back_inserter(unrun_tests)); - - // Report when the user specified tests that were not run. - if (!unrun_tests.empty()) { - const bool tests_were_run = - !(test_failures_.empty() && test_successes_.empty()); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult result = ::testing::AssertionFailure(); - result << "When testing type:\n " << type_name_ - << "\n\nThe following tests were expected to fail but were not " - "run"; - - if (tests_were_run) result << " (was the test name spelled correctly?)"; - - result << ":\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : unrun_tests) { - result << " " << test_name << "\n"; - } - - if (!tests_were_run) result << "\nNo tests were run."; - - if (!test_failures_.empty()) { - // List test failures - result << "\nThe tests that were run and failed are:\n\n"; - for (const auto& test_name : test_failures_) { - result << " " << test_name << "\n"; - } - } - - if (!test_successes_.empty()) { - // List test successes - result << "\nThe tests that were run and succeeded are:\n\n"; - for (const auto& test_name : test_successes_) { - result << " " << test_name << "\n"; - } - } - - return result; - } - - // If some tests passed when they were expected to fail, alert the caller. - if (nonfailing_tests.empty()) return ::testing::AssertionSuccess(); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult unexpected_successes = - ::testing::AssertionFailure(); - unexpected_successes << "When testing type:\n " << type_name_ - << "\n\nThe following tests passed when they were " - "expected to fail:\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : nonfailing_tests) { - unexpected_successes << " " << test_name << "\n"; - } - - return unexpected_successes; - } - - private: - void outputDivider() { - assertion_result_ << "========================================"; - } - - void addTestFailureImpl() {} - - template <class H, class... T> - void addTestFailureImpl(const H& head, const T&... tail) { - assertion_result_ << head; - addTestFailureImpl(tail...); - } - - ::testing::AssertionResult assertion_result_; - std::set<std::string> test_failures_; - std::set<std::string> test_successes_; - std::string type_name_; - bool has_error_ = false; -}; - -template <class T, class /*Enabler*/ = void> -struct PropertiesOfImpl {}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> { - using type = typename T::properties; -}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> { - using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type; -}; - -template <class T> -struct PropertiesOf : PropertiesOfImpl<T> {}; - -template <class T> -using PropertiesOfT = typename PropertiesOf<T>::type; - -// NOTE: These enums use this naming convention to be consistent with the -// standard trait names, which is useful since it allows us to match up each -// enum name with a corresponding trait name in macro definitions. - -// An enum that describes the various expectations on an operations existence. -enum class function_support { maybe, yes, nothrow, trivial }; - -constexpr const char* PessimisticPropertyDescription(function_support v) { - return v == function_support::maybe - ? "no" - : v == function_support::yes - ? "yes, potentially throwing" - : v == function_support::nothrow ? "yes, nothrow" - : "yes, trivial"; -} - -// Return a string that describes the kind of property support that was -// expected. -inline std::string ExpectedFunctionKindList(function_support min, - function_support max) { - if (min == max) { - std::string result = - absl::StrCat("Expected:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(UnderlyingValue(min))), - "\n"); - return result; - } - - std::string result = "Expected one of:\n"; - for (auto curr_support = UnderlyingValue(min); - curr_support <= UnderlyingValue(max); ++curr_support) { - absl::StrAppend(&result, " ", - PessimisticPropertyDescription( - static_cast<function_support>(curr_support)), - "\n"); - } - - return result; -} - -template <class Enum> -void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support, - Enum max_support, Enum kind) { - const auto kind_value = UnderlyingValue(kind); - const auto min_support_value = UnderlyingValue(min_support); - const auto max_support_value = UnderlyingValue(max_support); - - if (!(kind_value >= min_support_value && kind_value <= max_support_value)) { - errors->addTestFailure( - PropertyName(kind), "**Failed property expectation**\n\n", - ExpectedFunctionKindList( - static_cast<function_support>(min_support_value), - static_cast<function_support>(max_support_value)), - '\n', "Actual:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(kind_value))); - } else { - errors->addTestSuccess(PropertyName(kind)); - } -} - -#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow, trivial }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction", - default_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction", - move_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction", - copy_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment", - move_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment", - copy_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction", - destructible); - -#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM - -#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=", - greater_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable); - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable); - -#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM - -enum class hashable { maybe, yes }; - -constexpr const char* PropertyName(hashable v) { - return "support for std::hash"; -} - -template <class T> -using AlwaysFalse = std::false_type; - -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property) \ - template <class T> \ - constexpr property property##_support_of() { \ - return std::is_##property<T>::value \ - ? std::is_nothrow_##property<T>::value \ - ? absl::is_trivially_##property<T>::value \ - ? property::trivial \ - : property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible, - default_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible, - move_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible, - copy_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable, - move_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable, - copy_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER - -void BoolFunction(bool) noexcept; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists through SFINAE. -// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {}; - -template <template <class...> class Op> -struct IsOpable { - template <class T> - using apply = typename IsOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists and is also noexcept -// through SFINAE and the noexcept operator. -/// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsNothrowOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>> - : std::true_type {}; - -template <template <class...> class Op> -struct IsNothrowOpable { - template <class T> - using apply = typename IsNothrowOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A macro that produces the necessary function for reporting what kind of -// support a specific comparison operation has and a function for reporting an -// error if a given type's support for that operation does not meet the expected -// requirements. -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op) \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept((BoolFunction)(std::declval<const T&>() op \ - std::declval<const T&>()))>> \ - using name = Result; \ - \ - template <class T> \ - constexpr property property##_support_of() { \ - return IsOpable<name>::apply<T>::value \ - ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// Generate the necessary support-checking and error reporting functions for -// each of the comparison operators. -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable, - equality_comparable, ==); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable, - inequality_comparable, !=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable, - less_than_comparable, <); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable, - less_equal_comparable, <=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable, - greater_equal_comparable, >=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable, - greater_than_comparable, >); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for swap. -template <class T> -constexpr swappable swappable_support_of() { - return type_traits_internal::IsSwappable<T>::value - ? type_traits_internal::IsNothrowSwappable<T>::value - ? swappable::nothrow - : swappable::yes - : swappable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfSwappable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support, - PropertiesOfT<MaxProf>::swappable_support, - swappable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for std::hash. -template <class T> -constexpr hashable hashable_support_of() { - return type_traits_internal::IsHashable<T>::value ? hashable::yes - : hashable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfHashable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support, - PropertiesOfT<MaxProf>::hashable_support, - hashable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -template < - default_constructible DefaultConstructibleValue = - default_constructible::maybe, - move_constructible MoveConstructibleValue = move_constructible::maybe, - copy_constructible CopyConstructibleValue = copy_constructible::maybe, - move_assignable MoveAssignableValue = move_assignable::maybe, - copy_assignable CopyAssignableValue = copy_assignable::maybe, - destructible DestructibleValue = destructible::maybe, - equality_comparable EqualityComparableValue = equality_comparable::maybe, - inequality_comparable InequalityComparableValue = - inequality_comparable::maybe, - less_than_comparable LessThanComparableValue = less_than_comparable::maybe, - less_equal_comparable LessEqualComparableValue = - less_equal_comparable::maybe, - greater_equal_comparable GreaterEqualComparableValue = - greater_equal_comparable::maybe, - greater_than_comparable GreaterThanComparableValue = - greater_than_comparable::maybe, - swappable SwappableValue = swappable::maybe, - hashable HashableValue = hashable::maybe> -struct ConformanceProfile { - using properties = ConformanceProfile; - - static constexpr default_constructible - default_constructible_support = // NOLINT - DefaultConstructibleValue; - - static constexpr move_constructible move_constructible_support = // NOLINT - MoveConstructibleValue; - - static constexpr copy_constructible copy_constructible_support = // NOLINT - CopyConstructibleValue; - - static constexpr move_assignable move_assignable_support = // NOLINT - MoveAssignableValue; - - static constexpr copy_assignable copy_assignable_support = // NOLINT - CopyAssignableValue; - - static constexpr destructible destructible_support = // NOLINT - DestructibleValue; - - static constexpr equality_comparable equality_comparable_support = // NOLINT - EqualityComparableValue; - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - InequalityComparableValue; - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - LessThanComparableValue; - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - LessEqualComparableValue; - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - GreaterEqualComparableValue; - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - GreaterThanComparableValue; - - static constexpr swappable swappable_support = SwappableValue; // NOLINT - - static constexpr hashable hashable_support = HashableValue; // NOLINT - - static constexpr bool is_default_constructible = // NOLINT - DefaultConstructibleValue != default_constructible::maybe; - - static constexpr bool is_move_constructible = // NOLINT - MoveConstructibleValue != move_constructible::maybe; - - static constexpr bool is_copy_constructible = // NOLINT - CopyConstructibleValue != copy_constructible::maybe; - - static constexpr bool is_move_assignable = // NOLINT - MoveAssignableValue != move_assignable::maybe; - - static constexpr bool is_copy_assignable = // NOLINT - CopyAssignableValue != copy_assignable::maybe; - - static constexpr bool is_destructible = // NOLINT - DestructibleValue != destructible::maybe; - - static constexpr bool is_equality_comparable = // NOLINT - EqualityComparableValue != equality_comparable::maybe; - - static constexpr bool is_inequality_comparable = // NOLINT - InequalityComparableValue != inequality_comparable::maybe; - - static constexpr bool is_less_than_comparable = // NOLINT - LessThanComparableValue != less_than_comparable::maybe; - - static constexpr bool is_less_equal_comparable = // NOLINT - LessEqualComparableValue != less_equal_comparable::maybe; - - static constexpr bool is_greater_equal_comparable = // NOLINT - GreaterEqualComparableValue != greater_equal_comparable::maybe; - - static constexpr bool is_greater_than_comparable = // NOLINT - GreaterThanComparableValue != greater_than_comparable::maybe; - - static constexpr bool is_swappable = // NOLINT - SwappableValue != swappable::maybe; - - static constexpr bool is_hashable = // NOLINT - HashableValue != hashable::maybe; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// Compliant SFINAE-friendliness is not always present on the standard library -// implementations that we support. This helper-struct (and associated enum) is -// used as a means to conditionally check the hashability support of a type. -enum class CheckHashability { no, yes }; - -template <class T, CheckHashability ShouldCheckHashability> -struct conservative_hashable_support_of; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::no> { - static constexpr hashable Invoke() { return hashable::maybe; } -}; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::yes> { - static constexpr hashable Invoke() { return hashable_support_of<T>(); } -}; -// -//////////////////////////////////////////////////////////////////////////////// - -// The ConformanceProfile that is expected based on introspection into the type -// by way of trait checks. -template <class T, CheckHashability ShouldCheckHashability> -struct SyntacticConformanceProfileOf { - using properties = ConformanceProfile< - default_constructible_support_of<T>(), move_constructible_support_of<T>(), - copy_constructible_support_of<T>(), move_assignable_support_of<T>(), - copy_assignable_support_of<T>(), destructible_support_of<T>(), - equality_comparable_support_of<T>(), - inequality_comparable_support_of<T>(), - less_than_comparable_support_of<T>(), - less_equal_comparable_support_of<T>(), - greater_equal_comparable_support_of<T>(), - greater_than_comparable_support_of<T>(), swappable_support_of<T>(), - conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>; -}; - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name) \ - template <default_constructible DefaultConstructibleValue, \ - move_constructible MoveConstructibleValue, \ - copy_constructible CopyConstructibleValue, \ - move_assignable MoveAssignableValue, \ - copy_assignable CopyAssignableValue, \ - destructible DestructibleValue, \ - equality_comparable EqualityComparableValue, \ - inequality_comparable InequalityComparableValue, \ - less_than_comparable LessThanComparableValue, \ - less_equal_comparable LessEqualComparableValue, \ - greater_equal_comparable GreaterEqualComparableValue, \ - greater_than_comparable GreaterThanComparableValue, \ - swappable SwappableValue, hashable HashableValue> \ - constexpr type ConformanceProfile< \ - DefaultConstructibleValue, MoveConstructibleValue, \ - CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue, \ - DestructibleValue, EqualityComparableValue, InequalityComparableValue, \ - LessThanComparableValue, LessEqualComparableValue, \ - GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \ - HashableValue>::name - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type) \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, \ - type##_support); \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type) - -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable); - -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL - -// Retrieve the enum with the minimum underlying value. -// Note: std::min is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MinEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MinEnum(H head, N next, T... tail) { - return (UnderlyingValue)(head) < (UnderlyingValue)(next) - ? (MinEnum)(head, tail...) - : (MinEnum)(next, tail...); -} - -template <class... Profs> -struct MinimalProfiles { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// Retrieve the enum with the greatest underlying value. -// Note: std::max is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MaxEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MaxEnum(H head, N next, T... tail) { - return (UnderlyingValue)(next) < (UnderlyingValue)(head) - ? (MaxEnum)(head, tail...) - : (MaxEnum)(next, tail...); -} - -template <class... Profs> -struct CombineProfilesImpl { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that -// when named aliases of CombineProfiles are created (such as in -// conformance_aliases.h), we only pay for the combination algorithm on the -// profiles that are actually used. -template <class... Profs> -struct CombineProfiles { - using profile_alias_of = CombineProfilesImpl<Profs...>; -}; - -template <> -struct CombineProfiles<> { - using properties = ConformanceProfile<>; -}; - -template <class Profile, class Tag> -struct StrongProfileTypedef { - using properties = PropertiesOfT<Profile>; -}; - -template <class T, class /*Enabler*/ = void> -struct IsProfileImpl : std::false_type {}; - -template <class T> -struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {}; - -template <class T> -struct IsProfile : IsProfileImpl<T>::type {}; - -// A tag that describes which set of properties we will check when the user -// requires a strict match in conformance (as opposed to a loose match which -// allows more-refined support of any given operation). -// -// Currently only the RegularityDomain exists and it includes all operations -// that the conformance testing suite knows about. The intent is that if the -// suite is expanded to support extension, such as for checking conformance of -// concepts like Iterators or Containers, additional corresponding domains can -// be created. -struct RegularityDomain {}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ diff --git a/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 487b0f786b48..000000000000 --- 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 00775f960c36..000000000000 --- 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 deleted file mode 100644 index cf262fa6c222..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc +++ /dev/null @@ -1,1556 +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/types/internal/conformance_testing.h" - -#include <new> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_aliases.h" -#include "absl/types/internal/conformance_profile.h" - -namespace { - -namespace ti = absl::types_internal; - -template <class T> -using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T); - -template <class T> -using DefaultConstructibleWithNew = - absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>; - -template <class T> -using MoveConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<T>())); - -template <class T> -using MoveConstructibleWithNew = - absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>; - -template <class T> -using CopyConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<const T&>())); - -template <class T> -using CopyConstructibleWithNew = - absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>; - -template <class T, - class Result = - std::integral_constant<bool, noexcept(::new (std::nothrow) T)>> -using NothrowDefaultConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowDefaultConstructibleWithNew = - absl::type_traits_internal::is_detected< - NothrowDefaultConstructibleWithNewImpl, T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>> -using NothrowMoveConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowMoveConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl, - T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>> -using NothrowCopyConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowCopyConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl, - T>; - -// NOTE: ?: is used to verify contextually-convertible to bool and not simply -// implicit or explicit convertibility. -#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \ - ((std::declval<const T&>() op std::declval<const T&>()) ? true : true) - -#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op) \ - template <class T> \ - using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op)); \ - \ - template <class T> \ - using name = absl::type_traits_internal::is_detected<name##Impl, T>; \ - \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>> \ - using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \ - \ - template <class T> \ - using Nothrow##name = \ - absl::type_traits_internal::is_detected<Nothrow##name##Impl, T> - -ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >); - -#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT - -template <class T> -class ProfileTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ProfileTest); - -TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(arch_props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(arch_props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(arch_props::destructible_support, - expected_props::destructible_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Default constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - switch (expected_props::default_constructible_support) { - case ti::default_constructible::maybe: - EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::yes: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::nothrow: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - } - } - break; - case ti::default_constructible::trivial: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Move constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - switch (expected_props::move_constructible_support) { - case ti::move_constructible::maybe: - EXPECT_FALSE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::yes: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::nothrow: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - } - } - break; - case ti::move_constructible::trivial: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - switch (expected_props::copy_constructible_support) { - case ti::copy_constructible::maybe: - EXPECT_FALSE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::yes: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::nothrow: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - } - } - break; - case ti::copy_constructible::trivial: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Destructible checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - switch (expected_props::destructible_support) { - case ti::destructible::maybe: - EXPECT_FALSE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::yes: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::nothrow: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::trivial: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_TRUE(absl::is_trivially_destructible<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(arch_props::copy_assignable_support, - expected_props::copy_assignable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Move assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - switch (expected_props::move_assignable_support) { - case ti::move_assignable::maybe: - EXPECT_FALSE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::yes: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::nothrow: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::trivial: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - switch (expected_props::copy_assignable_support) { - case ti::copy_assignable::maybe: - EXPECT_FALSE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::yes: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::nothrow: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::trivial: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(arch_props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(arch_props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(arch_props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Equality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::equality_comparable_support) { - case ti::equality_comparable::maybe: - EXPECT_FALSE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::yes: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::nothrow: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_TRUE(NothrowEqualityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Inequality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::inequality_comparable_support) { - case ti::inequality_comparable::maybe: - EXPECT_FALSE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::yes: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::nothrow: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_TRUE(NothrowInequalityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_than_comparable_support) { - case ti::less_than_comparable::maybe: - EXPECT_FALSE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::yes: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::nothrow: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_TRUE(NothrowLessThanComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_equal_comparable_support) { - case ti::less_equal_comparable::maybe: - EXPECT_FALSE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::yes: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::nothrow: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_TRUE(NothrowLessEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_equal_comparable_support) { - case ti::greater_equal_comparable::maybe: - EXPECT_FALSE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::yes: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::nothrow: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_than_comparable_support) { - case ti::greater_than_comparable::maybe: - EXPECT_FALSE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::yes: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::nothrow: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(props::hashable_support, expected_props::hashable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Swappable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::swappable_support) { - case ti::swappable::maybe: - EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::nothrow: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Hashable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::hashable_support) { - case ti::hashable::maybe: -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value); -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - break; - case ti::hashable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value); - break; - } -} - -REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties, - HasAppropriateAssignmentProperties, - HasAppropriateComparisonProperties, - HasAppropriateAuxilliaryProperties); - -template <class Profile, class Arch, class ExpectedProfile> -struct ProfileAndExpectation { - using profile = Profile; - using arch = Arch; - using expected_profile = ExpectedProfile; -}; - -using CoreProfilesToTest = ::testing::Types< - // The terminating case of combine (all properties are "maybe"). - ProfileAndExpectation<ti::CombineProfiles<>, - ti::Archetype<ti::CombineProfiles<>>, - ti::ConformanceProfile<>>, - - // Core default constructor profiles - ProfileAndExpectation< - ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDefaultConstructorProfile, - ti::HasNothrowDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDefaultConstructorProfile, - ti::HasTrivialDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::trivial>>, - - // Core move constructor profiles - ProfileAndExpectation< - ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveConstructorProfile, - ti::HasNothrowMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveConstructorProfile, - ti::HasTrivialMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::trivial>>, - - // Core copy constructor profiles - ProfileAndExpectation< - ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyConstructorProfile, - ti::HasNothrowCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyConstructorProfile, - ti::HasTrivialCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::trivial>>, - - // Core move assignment profiles - ProfileAndExpectation< - ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::trivial>>, - - // Core copy assignment profiles - ProfileAndExpectation< - ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::trivial>>, - - // Core destructor profiles - ProfileAndExpectation< - ti::HasDestructorProfile, ti::HasDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::trivial>>, - - // Core equality comparable profiles - ProfileAndExpectation< - ti::HasEqualityProfile, ti::HasEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow>>, - - // Core inequality comparable profiles - ProfileAndExpectation< - ti::HasInequalityProfile, ti::HasInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, - ti::inequality_comparable::nothrow>>, - - // Core less than comparable profiles - ProfileAndExpectation< - ti::HasLessThanProfile, ti::HasLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::nothrow>>, - - // Core less equal comparable profiles - ProfileAndExpectation< - ti::HasLessEqualProfile, ti::HasLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, - ti::less_equal_comparable::nothrow>>, - - // Core greater equal comparable profiles - ProfileAndExpectation< - ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::nothrow>>, - - // Core greater than comparable profiles - ProfileAndExpectation< - ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::nothrow>>, - - // Core swappable profiles - ProfileAndExpectation< - ti::HasSwapProfile, ti::HasSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::yes>>, - ProfileAndExpectation< - ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Core hashable profiles - ProfileAndExpectation< - ti::HasStdHashSpecializationProfile, - ti::HasStdHashSpecializationArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::maybe, - ti::hashable::yes>>>; - -using CommonProfilesToTest = ::testing::Types< - // NothrowMoveConstructible - ProfileAndExpectation< - ti::NothrowMoveConstructibleProfile, - ti::NothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // CopyConstructible - ProfileAndExpectation< - ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // NothrowMovable - ProfileAndExpectation< - ti::NothrowMovableProfile, ti::NothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Value - ProfileAndExpectation< - ti::ValueProfile, ti::ValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - //////////////////////////////////////////////////////////////////////////// - // Common but also DefaultConstructible // - //////////////////////////////////////////////////////////////////////////// - - // DefaultConstructibleNothrowMoveConstructible - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMoveConstructibleProfile, - ti::DefaultConstructibleNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleCopyConstructible - ProfileAndExpectation< - ti::DefaultConstructibleCopyConstructibleProfile, - ti::DefaultConstructibleCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleNothrowMovable - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMovableProfile, - ti::DefaultConstructibleNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // DefaultConstructibleValue - ProfileAndExpectation< - ti::DefaultConstructibleValueProfile, - ti::DefaultConstructibleValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>; - -using ComparableHelpersProfilesToTest = ::testing::Types< - // Equatable - ProfileAndExpectation< - ti::EquatableProfile, ti::EquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes>>, - - // Comparable - ProfileAndExpectation< - ti::ComparableProfile, ti::ComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // NothrowEquatable - ProfileAndExpectation< - ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow>>, - - // NothrowComparable - ProfileAndExpectation< - ti::NothrowComparableProfile, ti::NothrowComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow, - ti::less_than_comparable::nothrow, - ti::less_equal_comparable::nothrow, - ti::greater_equal_comparable::nothrow, - ti::greater_than_comparable::nothrow>>>; - -using CommonComparableProfilesToTest = ::testing::Types< - // ComparableNothrowMoveConstructible - ProfileAndExpectation< - ti::ComparableNothrowMoveConstructibleProfile, - ti::ComparableNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableCopyConstructible - ProfileAndExpectation< - ti::ComparableCopyConstructibleProfile, - ti::ComparableCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableNothrowMovable - ProfileAndExpectation< - ti::ComparableNothrowMovableProfile, - ti::ComparableNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>, - - // ComparableValue - ProfileAndExpectation< - ti::ComparableValueProfile, ti::ComparableValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>>; - -using TrivialProfilesToTest = ::testing::Types< - ProfileAndExpectation< - ti::TrivialSpecialMemberFunctionsProfile, - ti::TrivialSpecialMemberFunctionsArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - ProfileAndExpectation< - ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow, ti::hashable::yes>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest, - ComparableHelpersProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest, - CommonComparableProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest); - -TEST(ConformanceTestingTest, Basic) { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - using lim = std::numeric_limits<float>; - - ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float) - .INITIALIZER(-lim::infinity()) - .INITIALIZER(lim::lowest()) - .INITIALIZER(-1.f) - .INITIALIZER(-lim::min()) - .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f)) - .INITIALIZER(lim::min()) - .INITIALIZER(1.f) - .INITIALIZER(lim::max()) - .INITIALIZER(lim::infinity()) - .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile); -} - -struct BadMoveConstruct { - BadMoveConstruct() = default; - BadMoveConstruct(BadMoveConstruct&& other) noexcept - : value(other.value + 1) {} - BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default; - int value = 0; - - friend bool operator==(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value != rhs.value; - } -}; - -struct BadMoveAssign { - BadMoveAssign() = default; - BadMoveAssign(BadMoveAssign&& other) noexcept = default; - BadMoveAssign& operator=(BadMoveAssign&& other) noexcept { - int new_value = other.value + 1; - value = new_value; - return *this; - } - int value = 0; - - friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value != rhs.value; - } -}; - -enum class WhichCompIsBad { eq, ne, lt, le, ge, gt }; - -template <WhichCompIsBad Which> -struct BadCompare { - int value; - - friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::eq ? lhs.value != rhs.value - : lhs.value == rhs.value; - } - - friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ne ? lhs.value == rhs.value - : lhs.value != rhs.value; - } - - friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value - : lhs.value < rhs.value; - } - - friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::le ? lhs.value > rhs.value - : lhs.value <= rhs.value; - } - - friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ge ? lhs.value < rhs.value - : lhs.value >= rhs.value; - } - - friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value - : lhs.value > rhs.value; - } -}; - -TEST(ConformanceTestingDeathTest, Failures) { - { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - // Note: The initializers are intentionally in the wrong order. - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float) - .INITIALIZER(1.f) - .INITIALIZER(0.f) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct) - .DUE_TO("Move construction") - .INITIALIZER(BadMoveConstruct()) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign) - .DUE_TO("Move assignment") - .INITIALIZER(BadMoveAssign()) - .WITH_LOOSE_PROFILE(profile); - } -} - -TEST(ConformanceTestingDeathTest, CompFailures) { - using profile = ti::ComparableProfile; - - { - using BadComp = BadCompare<WhichCompIsBad::eq>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ne>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::lt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::le>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ge>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::gt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfMove { - BadSelfMove() = default; - BadSelfMove(BadSelfMove&&) = default; - BadSelfMove& operator=(BadSelfMove&& other) noexcept { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfMoveFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove) - .DUE_TO("Move assignment") - .INITIALIZER(BadSelfMove()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfCopy { - BadSelfCopy() = default; - BadSelfCopy(BadSelfCopy&&) = default; - BadSelfCopy(const BadSelfCopy&) = default; - BadSelfCopy& operator=(BadSelfCopy&&) = default; - BadSelfCopy& operator=(BadSelfCopy const& other) { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfCopyFailure) { - using profile = ti::EquatableValueProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy) - .DUE_TO("Copy assignment") - .INITIALIZER(BadSelfCopy()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfSwap { - friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept { - if (&lhs == &rhs) lhs.broken_state = true; - } - - friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfSwapFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap) - .DUE_TO("Swap") - .INITIALIZER(BadSelfSwap()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedMoveAssign { - BadDefaultInitializedMoveAssign() : default_initialized(true) {} - explicit BadDefaultInitializedMoveAssign(int v) : value(v) {} - BadDefaultInitializedMoveAssign( - BadDefaultInitializedMoveAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedMoveAssign& operator=( - BadDefaultInitializedMoveAssign&& other) noexcept { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) { - using profile = - ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign) - .DUE_TO("move assignment") - .INITIALIZER(BadDefaultInitializedMoveAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedCopyAssign { - BadDefaultInitializedCopyAssign() : default_initialized(true) {} - explicit BadDefaultInitializedCopyAssign(int v) : value(v) {} - BadDefaultInitializedCopyAssign( - BadDefaultInitializedCopyAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other) - : value(other.value) {} - - BadDefaultInitializedCopyAssign& operator=( - BadDefaultInitializedCopyAssign&& other) noexcept { - value = other.value; - return *this; - } - - BadDefaultInitializedCopyAssign& operator=( - const BadDefaultInitializedCopyAssign& other) { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) { - using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign) - .DUE_TO("copy assignment") - .INITIALIZER(BadDefaultInitializedCopyAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/internal/optional.h b/third_party/abseil_cpp/absl/types/internal/optional.h deleted file mode 100644 index 92932b6001b3..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/optional.h +++ /dev/null @@ -1,396 +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. -// -#ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_ -#define ABSL_TYPES_INTERNAL_OPTIONAL_H_ - -#include <functional> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/inline_variable.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/utility/utility.h" - -// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS -// -// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015. -// __cpp_inheriting_constructors is a predefined macro and a recommended way to -// check for this language feature, but GCC doesn't support it until 5.0 and -// Clang doesn't support it until 3.6. -// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template -// constructor. For example, the following code won't work on MSVC 2015 Update3: -// struct Base { -// int t; -// template <typename T> -// constexpr Base(T t_) : t(t_) {} -// }; -// struct Foo : Base { -// using Base::Base; -// } -// constexpr Foo foo(0); // doesn't work on MSVC 2015 -#if defined(__clang__) -#if __has_feature(cxx_inheriting_constructors) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif -#elif (defined(__GNUC__) && \ - (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \ - (__cpp_inheriting_constructors >= 200802) || \ - (defined(_MSC_VER) && _MSC_VER >= 1910) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Forward declaration -template <typename T> -class optional; - -namespace optional_internal { - -// This tag type is used as a constructor parameter type for `nullopt_t`. -struct init_t { - explicit init_t() = default; -}; - -struct empty_struct {}; - -// This class stores the data in optional<T>. -// It is specialized based on whether T is trivially destructible. -// This is the specialization for non trivially destructible type. -template <typename T, bool unused = std::is_trivially_destructible<T>::value> -class optional_data_dtor_base { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use an array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - - void destruct() noexcept { - if (engaged_) { - data_.~T(); - engaged_ = false; - } - } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} - - ~optional_data_dtor_base() { destruct(); } -}; - -// Specialization for trivially destructible type. -template <typename T> -class optional_data_dtor_base<T, true> { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - void destruct() noexcept { engaged_ = false; } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} -}; - -template <typename T> -class optional_data_base : public optional_data_dtor_base<T> { - protected: - using base = optional_data_dtor_base<T>; -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using base::base; -#else - optional_data_base() = default; - - template <typename... Args> - constexpr explicit optional_data_base(in_place_t t, Args&&... args) - : base(t, absl::forward<Args>(args)...) {} -#endif - - template <typename... Args> - void construct(Args&&... args) { - // Use dummy_'s address to work around casting cv-qualified T* to void*. - ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...); - this->engaged_ = true; - } - - template <typename U> - void assign(U&& u) { - if (this->engaged_) { - this->data_ = std::forward<U>(u); - } else { - construct(std::forward<U>(u)); - } - } -}; - -// TODO(absl-team): Add another class using -// std::is_trivially_move_constructible trait when available to match -// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that -// have trivial move but nontrivial copy. -// Also, we should be checking is_trivially_copyable here, which is not -// supported now, so we use is_trivially_* traits instead. -template <typename T, - bool unused = absl::is_trivially_copy_constructible<T>::value&& - absl::is_trivially_copy_assignable<typename std::remove_cv< - T>::type>::value&& std::is_trivially_destructible<T>::value> -class optional_data; - -// Trivially copyable types -template <typename T> -class optional_data<T, true> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - optional_data() = default; - - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif -}; - -template <typename T> -class optional_data<T, false> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif - - optional_data() = default; - - optional_data(const optional_data& rhs) : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(rhs.data_); - } - } - - optional_data(optional_data&& rhs) noexcept( - absl::default_allocator_is_nothrow::value || - std::is_nothrow_move_constructible<T>::value) - : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(std::move(rhs.data_)); - } - } - - optional_data& operator=(const optional_data& rhs) { - if (rhs.engaged_) { - this->assign(rhs.data_); - } else { - this->destruct(); - } - return *this; - } - - optional_data& operator=(optional_data&& rhs) noexcept( - std::is_nothrow_move_assignable<T>::value&& - std::is_nothrow_move_constructible<T>::value) { - if (rhs.engaged_) { - this->assign(std::move(rhs.data_)); - } else { - this->destruct(); - } - return *this; - } -}; - -// Ordered by level of restriction, from low to high. -// Copyable implies movable. -enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 }; - -// Base class for enabling/disabling copy/move constructor. -template <copy_traits> -class optional_ctor_base; - -template <> -class optional_ctor_base<copy_traits::copyable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = default; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::non_movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = delete; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -// Base class for enabling/disabling copy/move assignment. -template <copy_traits> -class optional_assign_base; - -template <> -class optional_assign_base<copy_traits::copyable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = default; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::non_movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = delete; -}; - -template <typename T> -struct ctor_copy_traits { - static constexpr copy_traits traits = - std::is_copy_constructible<T>::value - ? copy_traits::copyable - : std::is_move_constructible<T>::value ? copy_traits::movable - : copy_traits::non_movable; -}; - -template <typename T> -struct assign_copy_traits { - static constexpr copy_traits traits = - absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value - ? copy_traits::copyable - : absl::is_move_assignable<T>::value && - std::is_move_constructible<T>::value - ? copy_traits::movable - : copy_traits::non_movable; -}; - -// Whether T is constructible or convertible from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_from_optional - : std::integral_constant< - bool, std::is_constructible<T, optional<U>&>::value || - std::is_constructible<T, optional<U>&&>::value || - std::is_constructible<T, const optional<U>&>::value || - std::is_constructible<T, const optional<U>&&>::value || - std::is_convertible<optional<U>&, T>::value || - std::is_convertible<optional<U>&&, T>::value || - std::is_convertible<const optional<U>&, T>::value || - std::is_convertible<const optional<U>&&, T>::value> {}; - -// Whether T is constructible or convertible or assignable from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_assignable_from_optional - : std::integral_constant< - bool, is_constructible_convertible_from_optional<T, U>::value || - std::is_assignable<T&, optional<U>&>::value || - std::is_assignable<T&, optional<U>&&>::value || - std::is_assignable<T&, const optional<U>&>::value || - std::is_assignable<T&, const optional<U>&&>::value> {}; - -// Helper function used by [optional.relops], [optional.comp_with_t], -// for checking whether an expression is convertible to bool. -bool convertible_to_bool(bool); - -// Base class for std::hash<absl::optional<T>>: -// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to -// compute the hash; Otherwise, it is disabled. -// Reference N4659 23.14.15 [unord.hash]. -template <typename T, typename = size_t> -struct optional_hash_base { - optional_hash_base() = delete; - optional_hash_base(const optional_hash_base&) = delete; - optional_hash_base(optional_hash_base&&) = delete; - optional_hash_base& operator=(const optional_hash_base&) = delete; - optional_hash_base& operator=(optional_hash_base&&) = delete; -}; - -template <typename T> -struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()( - std::declval<absl::remove_const_t<T> >()))> { - using argument_type = absl::optional<T>; - using result_type = size_t; - size_t operator()(const absl::optional<T>& opt) const { - absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>(); - if (opt) { - return std::hash<absl::remove_const_t<T> >()(*opt); - } else { - return static_cast<size_t>(0x297814aaad196e6dULL); - } - } -}; - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - -#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/parentheses.h b/third_party/abseil_cpp/absl/types/internal/parentheses.h deleted file mode 100644 index 5aebee8fdeb9..000000000000 --- 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/span.h b/third_party/abseil_cpp/absl/types/internal/span.h deleted file mode 100644 index 112612f4bdae..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/span.h +++ /dev/null @@ -1,128 +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_SPAN_H_ -#define ABSL_TYPES_INTERNAL_SPAN_H_ - -#include <algorithm> -#include <cstddef> -#include <string> -#include <type_traits> - -#include "absl/algorithm/algorithm.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace span_internal { -// A constexpr min function -constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; } - -// Wrappers for access to container data pointers. -template <typename C> -constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) - -> decltype(c.data()) { - return c.data(); -} - -// Before C++17, std::string::data returns a const char* in all cases. -inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) - int) noexcept { - return &s[0]; -} - -template <typename C> -constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references) - -> decltype(GetDataImpl(c, 0)) { - return GetDataImpl(c, 0); -} - -// Detection idioms for size() and data(). -template <typename C> -using HasSize = - std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>; - -// We want to enable conversion from vector<T*> to Span<const T* const> but -// disable conversion from vector<Derived> to Span<Base>. Here we use -// the fact that U** is convertible to Q* const* if and only if Q is the same -// type or a more cv-qualified version of U. We also decay the result type of -// data() to avoid problems with classes which have a member function data() -// which returns a reference. -template <typename T, typename C> -using HasData = - std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*, - T* const*>; - -// Extracts value type from a Container -template <typename C> -struct ElementType { - using type = typename absl::remove_reference_t<C>::value_type; -}; - -template <typename T, size_t N> -struct ElementType<T (&)[N]> { - using type = T; -}; - -template <typename C> -using ElementT = typename ElementType<C>::type; - -template <typename T> -using EnableIfMutable = - typename std::enable_if<!std::is_const<T>::value, int>::type; - -template <template <typename> class SpanT, typename T> -bool EqualImpl(SpanT<T> a, SpanT<T> b) { - static_assert(std::is_const<T>::value, ""); - return absl::equal(a.begin(), a.end(), b.begin(), b.end()); -} - -template <template <typename> class SpanT, typename T> -bool LessThanImpl(SpanT<T> a, SpanT<T> b) { - // We can't use value_type since that is remove_cv_t<T>, so we go the long way - // around. - static_assert(std::is_const<T>::value, ""); - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); -} - -// The `IsConvertible` classes here are needed because of the -// `std::is_convertible` bug in libcxx when compiled with GCC. This build -// configuration is used by Android NDK toolchain. Reference link: -// https://bugs.llvm.org/show_bug.cgi?id=27538. -template <typename From, typename To> -struct IsConvertibleHelper { - private: - static std::true_type testval(To); - static std::false_type testval(...); - - public: - using type = decltype(testval(std::declval<From>())); -}; - -template <typename From, typename To> -struct IsConvertible : IsConvertibleHelper<From, To>::type {}; - -// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the -// older version of libcxx is not supported. -template <typename From, typename To> -using EnableIfConvertibleTo = - typename std::enable_if<IsConvertible<From, To>::value>::type; -} // namespace span_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_SPAN_H_ diff --git a/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 4a0ab42ac49f..000000000000 --- 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 deleted file mode 100644 index 772008c74e6d..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/variant.h +++ /dev/null @@ -1,1646 +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. -// -// Implementation details of absl/types/variant.h, pulled into a -// separate file to avoid cluttering the top of the API header with -// implementation details. - -#ifndef ABSL_TYPES_variant_internal_H_ -#define ABSL_TYPES_variant_internal_H_ - -#include <cassert> -#include <cstddef> -#include <cstdlib> -#include <memory> -#include <stdexcept> -#include <tuple> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/base/internal/identity.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/base/internal/invoke.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_variant_access.h" -#include "absl/utility/utility.h" - -#if !defined(ABSL_USES_STD_VARIANT) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -template <class... Types> -class variant; - -ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1)); - -template <class T> -struct variant_size; - -template <std::size_t I, class T> -struct variant_alternative; - -namespace variant_internal { - -// NOTE: See specializations below for details. -template <std::size_t I, class T> -struct VariantAlternativeSfinae {}; - -// Requires: I < variant_size_v<T>. -// -// Value: The Ith type of Types... -template <std::size_t I, class T0, class... Tn> -struct VariantAlternativeSfinae<I, variant<T0, Tn...>> - : VariantAlternativeSfinae<I - 1, variant<Tn...>> {}; - -// Value: T0 -template <class T0, class... Ts> -struct VariantAlternativeSfinae<0, variant<T0, Ts...>> { - using type = T0; -}; - -template <std::size_t I, class T> -using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type; - -// NOTE: Requires T to be a reference type. -template <class T, class U> -struct GiveQualsTo; - -template <class T, class U> -struct GiveQualsTo<T&, U> { - using type = U&; -}; - -template <class T, class U> -struct GiveQualsTo<T&&, U> { - using type = U&&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&, U> { - using type = const U&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&&, U> { - using type = const U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&, U> { - using type = volatile U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&&, U> { - using type = volatile U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&, U> { - using type = volatile const U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&&, U> { - using type = volatile const U&&; -}; - -template <class T, class U> -using GiveQualsToT = typename GiveQualsTo<T, U>::type; - -// Convenience alias, since size_t integral_constant is used a lot in this file. -template <std::size_t I> -using SizeT = std::integral_constant<std::size_t, I>; - -using NPos = SizeT<variant_npos>; - -template <class Variant, class T, class = void> -struct IndexOfConstructedType {}; - -template <std::size_t I, class Variant> -struct VariantAccessResultImpl; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, class Variant> -using VariantAccessResult = - typename VariantAccessResultImpl<I, Variant&&>::type; - -// NOTE: This is used instead of std::array to reduce instantiation overhead. -template <class T, std::size_t Size> -struct SimpleArray { - static_assert(Size != 0, ""); - T value[Size]; -}; - -template <class T> -struct AccessedType { - using type = T; -}; - -template <class T> -using AccessedTypeT = typename AccessedType<T>::type; - -template <class T, std::size_t Size> -struct AccessedType<SimpleArray<T, Size>> { - using type = AccessedTypeT<T>; -}; - -template <class T> -constexpr T AccessSimpleArray(const T& value) { - return value; -} - -template <class T, std::size_t Size, class... SizeT> -constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table, - std::size_t head_index, - SizeT... tail_indices) { - return AccessSimpleArray(table.value[head_index], tail_indices...); -} - -// Note: Intentionally is an alias. -template <class T> -using AlwaysZero = SizeT<0>; - -template <class Op, class... Vs> -struct VisitIndicesResultImpl { - using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>; -}; - -template <class Op, class... Vs> -using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type; - -template <class ReturnType, class FunctionObject, class EndIndices, - class BoundIndices> -struct MakeVisitationMatrix; - -template <class ReturnType, class FunctionObject, std::size_t... Indices> -constexpr ReturnType call_with_indices(FunctionObject&& function) { - static_assert( - std::is_same<ReturnType, decltype(std::declval<FunctionObject>()( - SizeT<Indices>()...))>::value, - "Not all visitation overloads have the same return type."); - return absl::forward<FunctionObject>(function)(SizeT<Indices>()...); -} - -template <class ReturnType, class FunctionObject, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>, - index_sequence<BoundIndices...>> { - using ResultType = ReturnType (*)(FunctionObject&&); - static constexpr ResultType Run() { - return &call_with_indices<ReturnType, FunctionObject, - (BoundIndices - 1)...>; - } -}; - -template <typename Is, std::size_t J> -struct AppendToIndexSequence; - -template <typename Is, std::size_t J> -using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type; - -template <std::size_t... Is, std::size_t J> -struct AppendToIndexSequence<index_sequence<Is...>, J> { - using type = index_sequence<Is..., J>; -}; - -template <class ReturnType, class FunctionObject, class EndIndices, - class CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl; - -template <class ReturnType, class FunctionObject, class EndIndices, - std::size_t... CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices, - index_sequence<CurrIndices...>, BoundIndices> { - using ResultType = SimpleArray< - typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices, - index_sequence<>>::ResultType, - sizeof...(CurrIndices)>; - - static constexpr ResultType Run() { - return {{MakeVisitationMatrix< - ReturnType, FunctionObject, EndIndices, - AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}}; - } -}; - -template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex, - std::size_t... TailEndIndices, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, - index_sequence<HeadEndIndex, TailEndIndices...>, - index_sequence<BoundIndices...>> - : MakeVisitationMatrixImpl<ReturnType, FunctionObject, - index_sequence<TailEndIndices...>, - absl::make_index_sequence<HeadEndIndex>, - index_sequence<BoundIndices...>> {}; - -struct UnreachableSwitchCase { - template <class Op> - [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run( - Op&& /*ignored*/) { -#if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \ - (defined(__GNUC__) && !defined(__clang__)) - __builtin_unreachable(); -#elif defined(_MSC_VER) - __assume(false); -#else - // Try to use assert of false being identified as an unreachable intrinsic. - // NOTE: We use assert directly to increase chances of exploiting an assume - // intrinsic. - assert(false); // NOLINT - - // Hack to silence potential no return warning -- cause an infinite loop. - return Run(absl::forward<Op>(op)); -#endif // Checks for __builtin_unreachable - } -}; - -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>()); - } -}; - -// The number 33 is just a guess at a reasonable maximum to our switch. It is -// not based on any analysis. The reason it is a power of 2 plus 1 instead of a -// power of 2 is because the number was picked to correspond to a power of 2 -// amount of "normal" alternatives, plus one for the possibility of the user -// providing "monostate" in addition to the more natural alternatives. -ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33); - -// Note: The default-definition is for unreachable cases. -template <bool IsReachable> -struct PickCaseImpl { - template <class Op, std::size_t I> - using Apply = UnreachableSwitchCase; -}; - -template <> -struct PickCaseImpl</*IsReachable =*/true> { - template <class Op, std::size_t I> - using Apply = ReachableSwitchCase<Op, I>; -}; - -// Note: This form of dance with template aliases is to make sure that we -// instantiate a number of templates proportional to the number of variant -// alternatives rather than a number of templates proportional to our -// maximum unrolled amount of visitation cases (aliases are effectively -// "free" whereas other template instantiations are costly). -template <class Op, std::size_t I, std::size_t EndIndex> -using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>; - -template <class ReturnType> -[[noreturn]] ReturnType TypedThrowBadVariantAccess() { - absl::variant_internal::ThrowBadVariantAccess(); -} - -// Given N variant sizes, determine the number of cases there would need to be -// in a single switch-statement that would cover every possibility in the -// corresponding N-ary visit operation. -template <std::size_t... NumAlternatives> -struct NumCasesOfSwitch; - -template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives> -struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> { - static constexpr std::size_t value = - (HeadNumAlternatives + 1) * - NumCasesOfSwitch<TailNumAlternatives...>::value; -}; - -template <> -struct NumCasesOfSwitch<> { - static constexpr std::size_t value = 1; -}; - -// A switch statement optimizes better than the table of function pointers. -template <std::size_t EndIndex> -struct VisitIndicesSwitch { - static_assert(EndIndex <= MaxUnrolledVisitCases, - "Maximum unrolled switch size exceeded."); - - template <class Op> - static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) { - switch (i) { - case 0: - return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op)); - case 1: - return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op)); - case 2: - return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op)); - case 3: - return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op)); - case 4: - return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op)); - case 5: - return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op)); - case 6: - return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op)); - case 7: - return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op)); - case 8: - return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op)); - case 9: - return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op)); - case 10: - return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op)); - case 11: - return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op)); - case 12: - return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op)); - case 13: - return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op)); - case 14: - return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op)); - case 15: - return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op)); - case 16: - return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op)); - case 17: - return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op)); - case 18: - return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op)); - case 19: - return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op)); - case 20: - return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op)); - case 21: - return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op)); - case 22: - return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op)); - case 23: - return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op)); - case 24: - return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op)); - case 25: - return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op)); - case 26: - return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op)); - case 27: - return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op)); - case 28: - return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op)); - case 29: - return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op)); - case 30: - return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op)); - case 31: - return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op)); - case 32: - 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()); - } - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesFallback { - template <class Op, class... SizeT> - static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) { - return AccessSimpleArray( - MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op, - index_sequence<(EndIndices + 1)...>, - index_sequence<>>::Run(), - (indices + 1)...)(absl::forward<Op>(op)); - } -}; - -// Take an N-dimensional series of indices and convert them into a single index -// without loss of information. The purpose of this is to be able to convert an -// N-ary visit operation into a single switch statement. -template <std::size_t...> -struct FlattenIndices; - -template <std::size_t HeadSize, std::size_t... TailSize> -struct FlattenIndices<HeadSize, TailSize...> { - template<class... SizeType> - static constexpr std::size_t Run(std::size_t head, SizeType... tail) { - return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...); - } -}; - -template <> -struct FlattenIndices<> { - static constexpr std::size_t Run() { return 0; } -}; - -// Take a single "flattened" index (flattened by FlattenIndices) and determine -// the value of the index of one of the logically represented dimensions. -template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize, - std::size_t... TailSize> -struct UnflattenIndex { - static constexpr std::size_t value = - UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value; -}; - -template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize> -struct UnflattenIndex<I, 0, HeadSize, TailSize...> { - static constexpr std::size_t value = (I % HeadSize); -}; - -// The backend for converting an N-ary visit operation into a unary visit. -template <class IndexSequence, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl; - -template <std::size_t... N, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> { - // A type that can take an N-ary function object and converts it to a unary - // function object that takes a single, flattened index, and "unflattens" it - // into its individual dimensions when forwarding to the wrapped object. - template <class Op> - struct FlattenedOp { - template <std::size_t I> - VisitIndicesResultT<Op, decltype(EndIndices)...> operator()( - SizeT<I> /*index*/) && { - return base_internal::invoke( - absl::forward<Op>(op), - SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value - - std::size_t{1}>()...); - } - - Op&& op; - }; - - template <class Op, class... SizeType> - static VisitIndicesResultT<Op, decltype(EndIndices)...> Run( - Op&& op, SizeType... i) { - return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run( - FlattenedOp<Op>{absl::forward<Op>(op)}, - FlattenIndices<(EndIndices + std::size_t{1})...>::Run( - (i + std::size_t{1})...)); - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesVariadic - : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>, - EndIndices...> {}; - -// This implementation will flatten N-ary visit operations into a single switch -// statement when the number of cases would be less than our maximum specified -// switch-statement size. -// TODO(calabrese) -// Based on benchmarks, determine whether the function table approach actually -// does optimize better than a chain of switch statements and possibly update -// the implementation accordingly. Also consider increasing the maximum switch -// size. -template <std::size_t... EndIndices> -struct VisitIndices - : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <= - MaxUnrolledVisitCases), - VisitIndicesVariadic<EndIndices...>, - VisitIndicesFallback<EndIndices...>> {}; - -template <std::size_t EndIndex> -struct VisitIndices<EndIndex> - : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases), - VisitIndicesSwitch<EndIndex>, - VisitIndicesFallback<EndIndex>> {}; - -// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast` -// below is returning the address of a temporary or local object. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4172) -#endif // _MSC_VER - -// TODO(calabrese) std::launder -// TODO(calabrese) constexpr -// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a -// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details. -template <class Self, std::size_t I> -inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) { - return reinterpret_cast<VariantAccessResult<I, Self>>(self); -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -template <class T> -void DeducedDestroy(T& self) { // NOLINT - self.~T(); -} - -// NOTE: This type exists as a single entity for variant and its bases to -// befriend. It contains helper functionality that manipulates the state of the -// variant, such as the implementation of things like assignment and emplace -// operations. -struct VariantCoreAccess { - template <class VariantType> - static typename VariantType::Variant& Derived(VariantType& self) { // NOLINT - return static_cast<typename VariantType::Variant&>(self); - } - - template <class VariantType> - static const typename VariantType::Variant& Derived( - const VariantType& self) { // NOLINT - return static_cast<const typename VariantType::Variant&>(self); - } - - template <class VariantType> - static void Destroy(VariantType& self) { // NOLINT - Derived(self).destroy(); - self.index_ = absl::variant_npos; - } - - template <class Variant> - static void SetIndex(Variant& self, std::size_t i) { // NOLINT - self.index_ = i; - } - - template <class Variant> - static void InitFrom(Variant& self, Variant&& other) { // NOLINT - VisitIndices<absl::variant_size<Variant>::value>::Run( - InitFromVisitor<Variant, Variant&&>{&self, - std::forward<Variant>(other)}, - other.index()); - self.index_ = other.index(); - } - - // Access a variant alternative, assuming the index is correct. - template <std::size_t I, class Variant> - static VariantAccessResult<I, Variant> Access(Variant&& self) { - // This cast instead of invocation of AccessUnion with an rvalue is a - // workaround for msvc. Without this there is a runtime failure when dealing - // with rvalues. - // TODO(calabrese) Reduce test case and find a simpler workaround. - return static_cast<VariantAccessResult<I, Variant>>( - variant_internal::AccessUnion(self.state_, SizeT<I>())); - } - - // Access a variant alternative, throwing if the index is incorrect. - template <std::size_t I, class Variant> - static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) { - if (ABSL_PREDICT_FALSE(self.index_ != I)) { - TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>(); - } - - return Access<I>(absl::forward<Variant>(self)); - } - - // The implementation of the move-assignment operation for a variant. - template <class VType> - struct MoveAssignVisitor { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right)); - } else { - Derived(*left).template emplace<NewIndex>( - std::move(Access<NewIndex>(*right))); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - VType* right; - }; - - template <class VType> - static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left, - VType* other) { - return {left, other}; - } - - // The implementation of the assignment operation for a variant. - template <class VType> - struct CopyAssignVisitor { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using New = - typename absl::variant_alternative<NewIndex, DerivedType>::type; - - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = Access<NewIndex>(*right); - } else if (std::is_nothrow_copy_constructible<New>::value || - !std::is_nothrow_move_constructible<New>::value) { - Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right)); - } else { - Derived(*left) = DerivedType(Derived(*right)); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - const VType* right; - }; - - template <class VType> - static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left, - const VType& other) { - return {left, &other}; - } - - // The implementation of conversion-assignment operations for variant. - template <class Left, class QualifiedNew> - struct ConversionAssignVisitor { - using NewIndex = - variant_internal::IndexOfConstructedType<Left, QualifiedNew>; - - void operator()(SizeT<NewIndex::value> /*old_i*/ - ) const { - Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other); - } - - template <std::size_t OldIndex> - void operator()(SizeT<OldIndex> /*old_i*/ - ) const { - using New = - typename absl::variant_alternative<NewIndex::value, Left>::type; - if (std::is_nothrow_constructible<New, QualifiedNew>::value || - !std::is_nothrow_move_constructible<New>::value) { - left->template emplace<NewIndex::value>( - absl::forward<QualifiedNew>(other)); - } else { - // the standard says "equivalent to - // operator=(variant(std::forward<T>(t)))", but we use `emplace` here - // because the variant's move assignment operator could be deleted. - left->template emplace<NewIndex::value>( - New(absl::forward<QualifiedNew>(other))); - } - } - - Left* left; - QualifiedNew&& other; - }; - - template <class Left, class QualifiedNew> - static ConversionAssignVisitor<Left, QualifiedNew> - MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) { - return {left, absl::forward<QualifiedNew>(qual)}; - } - - // Backend for operations for `emplace()` which destructs `*self` then - // construct a new alternative with `Args...`. - template <std::size_t NewIndex, class Self, class... Args> - static typename absl::variant_alternative<NewIndex, Self>::type& Replace( - Self* self, Args&&... args) { - Destroy(*self); - using New = typename absl::variant_alternative<NewIndex, Self>::type; - New* const result = ::new (static_cast<void*>(&self->state_)) - New(absl::forward<Args>(args)...); - self->index_ = NewIndex; - return *result; - } - - template <class LeftVariant, class QualifiedRightVariant> - struct InitFromVisitor { - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using Alternative = - typename variant_alternative<NewIndex, LeftVariant>::type; - ::new (static_cast<void*>(&left->state_)) Alternative( - Access<NewIndex>(std::forward<QualifiedRightVariant>(right))); - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - // This space intentionally left blank. - } - LeftVariant* left; - QualifiedRightVariant&& right; - }; -}; - -template <class Expected, class... T> -struct IndexOfImpl; - -template <class Expected> -struct IndexOfImpl<Expected> { - using IndexFromEnd = SizeT<0>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::false_type; -}; - -template <class Expected, class Head, class... Tail> -struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; -}; - -template <class Expected, class... Tail> -struct IndexOfImpl<Expected, Expected, Tail...> - : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::integral_constant< - bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>; -}; - -template <class Expected, class... Types> -struct IndexOfMeta { - using Results = IndexOfImpl<Expected, Types...>; - static_assert(!Results::MultipleMatches::value, - "Attempted to access a variant by specifying a type that " - "matches more than one alternative."); - static_assert(Results::MatchedIndexFromEnd::value != 0, - "Attempted to access a variant by specifying a type that does " - "not match any alternative."); - using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>; -}; - -template <class Expected, class... Types> -using IndexOf = typename IndexOfMeta<Expected, Types...>::type; - -template <class Variant, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl; - -// Terminating case encountered once we've checked all of the alternatives -template <class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {}; - -// Case where T is not Head -template <class Head, class... Tail, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex> - : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {}; - -// Case where T is Head -template <class Head, class... Tail, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex> - : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value == - sizeof...(Tail) - ? CurrIndex - : CurrIndex + sizeof...(Tail) + 1> {}; - -template <class Variant, class T> -struct UnambiguousIndexOf; - -struct NoMatch { - struct type {}; -}; - -template <class... Alts, class T> -struct UnambiguousIndexOf<variant<Alts...>, T> - : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value != - sizeof...(Alts), - UnambiguousIndexOfImpl<variant<Alts...>, T, 0>, - NoMatch>::type::type {}; - -template <class T, std::size_t /*Dummy*/> -using UnambiguousTypeOfImpl = T; - -template <class Variant, class T> -using UnambiguousTypeOfT = - UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>; - -template <class H, class... T> -class VariantStateBase; - -// This is an implementation of the "imaginary function" that is described in -// [variant.ctor] -// It is used in order to determine which alternative to construct during -// initialization from some type T. -template <class Variant, std::size_t I = 0> -struct ImaginaryFun; - -template <std::size_t I> -struct ImaginaryFun<variant<>, I> { - static void Run() = delete; -}; - -template <class H, class... T, std::size_t I> -struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> { - using ImaginaryFun<variant<T...>, I + 1>::Run; - - // NOTE: const& and && are used instead of by-value due to lack of guaranteed - // move elision of C++17. This may have other minor differences, but tests - // pass. - static SizeT<I> Run(const H&, SizeT<I>); - static SizeT<I> Run(H&&, SizeT<I>); -}; - -// The following metafunctions are used in constructor and assignment -// constraints. -template <class Self, class T> -struct IsNeitherSelfNorInPlace : std::true_type {}; - -template <class Self> -struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {}; - -template <class Self, class T> -struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {}; - -template <class Self, std::size_t I> -struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {}; - -template <class Variant, class T, class = void> -struct ConversionIsPossibleImpl : std::false_type {}; - -template <class Variant, class T> -struct ConversionIsPossibleImpl< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : std::true_type {}; - -template <class Variant, class T> -struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {}; - -template <class Variant, class T> -struct IndexOfConstructedType< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {}; - -template <std::size_t... Is> -struct ContainsVariantNPos - : absl::negation<std::is_same< // NOLINT - absl::integer_sequence<bool, 0 <= Is...>, - absl::integer_sequence<bool, Is != absl::variant_npos...>>> {}; - -template <class Op, class... QualifiedVariants> -using RawVisitResult = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; - -// NOTE: The spec requires that all return-paths yield the same type and is not -// SFINAE-friendly, so we can deduce the return type by examining the first -// result. If it's not callable, then we get an error, but are compliant and -// fast to compile. -// TODO(calabrese) Possibly rewrite in a way that yields better compile errors -// at the cost of longer compile-times. -template <class Op, class... QualifiedVariants> -struct VisitResultImpl { - using type = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; -}; - -// Done in two steps intentionally so that we don't cause substitution to fail. -template <class Op, class... QualifiedVariants> -using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type; - -template <class Op, class... QualifiedVariants> -struct PerformVisitation { - using ReturnType = VisitResult<Op, QualifiedVariants...>; - - template <std::size_t... Is> - constexpr ReturnType operator()(SizeT<Is>... indices) const { - return Run(typename ContainsVariantNPos<Is...>::type{}, - absl::index_sequence_for<QualifiedVariants...>(), indices...); - } - - template <std::size_t... TupIs, std::size_t... Is> - constexpr ReturnType Run(std::false_type /*has_valueless*/, - index_sequence<TupIs...>, SizeT<Is>...) const { - static_assert( - std::is_same<ReturnType, - absl::result_of_t<Op(VariantAccessResult< - Is, QualifiedVariants>...)>>::value, - "All visitation overloads must have the same return type."); - return absl::base_internal::invoke( - absl::forward<Op>(op), - VariantCoreAccess::Access<Is>( - absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...); - } - - template <std::size_t... TupIs, std::size_t... Is> - [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/, - index_sequence<TupIs...>, SizeT<Is>...) const { - absl::variant_internal::ThrowBadVariantAccess(); - } - - // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations - // Attempts using lambda variadic captures fail on current GCC. - std::tuple<QualifiedVariants&&...> variant_tup; - Op&& op; -}; - -template <class... T> -union Union; - -// We want to allow for variant<> to be trivial. For that, we need the default -// constructor to be trivial, which means we can't define it ourselves. -// Instead, we use a non-default constructor that takes NoopConstructorTag -// that doesn't affect the triviality of the types. -struct NoopConstructorTag {}; - -template <std::size_t I> -struct EmplaceTag {}; - -template <> -union Union<> { - constexpr explicit Union(NoopConstructorTag) noexcept {} -}; - -// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined -// deleted destructor from the `std::is_destructible` check below. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4624) -#endif // _MSC_VER - -template <class Head, class... Tail> -union Union<Head, Tail...> { - using TailUnion = Union<Tail...>; - - explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr Union(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr Union(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - Head head; - TailUnion tail; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -// TODO(calabrese) Just contain a Union in this union (certain configs fail). -template <class... T> -union DestructibleUnionImpl; - -template <> -union DestructibleUnionImpl<> { - constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {} -}; - -template <class Head, class... Tail> -union DestructibleUnionImpl<Head, Tail...> { - using TailUnion = DestructibleUnionImpl<Tail...>; - - explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - ~DestructibleUnionImpl() {} - - Head head; - TailUnion tail; -}; - -// This union type is destructible even if one or more T are not trivially -// destructible. In the case that all T are trivially destructible, then so is -// this resultant type. -template <class... T> -using DestructibleUnion = - absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>, - DestructibleUnionImpl<T...>>; - -// Deepest base, containing the actual union and the discriminator -template <class H, class... T> -class VariantStateBase { - protected: - using Variant = variant<H, T...>; - - template <class LazyH = H, - class ConstructibleH = absl::enable_if_t< - std::is_default_constructible<LazyH>::value, LazyH>> - constexpr VariantStateBase() noexcept( - std::is_nothrow_default_constructible<ConstructibleH>::value) - : state_(EmplaceTag<0>()), index_(0) {} - - template <std::size_t I, class... P> - explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args) - : state_(tag, absl::forward<P>(args)...), index_(I) {} - - explicit constexpr VariantStateBase(NoopConstructorTag) - : state_(NoopConstructorTag()), index_(variant_npos) {} - - void destroy() {} // Does nothing (shadowed in child if non-trivial) - - DestructibleUnion<H, T...> state_; - std::size_t index_; -}; - -using absl::internal::identity; - -// OverloadSet::Overload() is a unary function which is overloaded to -// take any of the element types of the variant, by reference-to-const. -// The return type of the overload on T is identity<T>, so that you -// can statically determine which overload was called. -// -// Overload() is not defined, so it can only be called in unevaluated -// contexts. -template <typename... Ts> -struct OverloadSet; - -template <typename T, typename... Ts> -struct OverloadSet<T, Ts...> : OverloadSet<Ts...> { - using Base = OverloadSet<Ts...>; - static identity<T> Overload(const T&); - using Base::Overload; -}; - -template <> -struct OverloadSet<> { - // For any case not handled above. - static void Overload(...); -}; - -template <class T> -using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); - -template <class T> -using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>()); - -template <class T> -using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>()); - -template <class T> -using GreaterThanOrEqualResult = - decltype(std::declval<T>() >= std::declval<T>()); - -template <class T> -using EqualResult = decltype(std::declval<T>() == std::declval<T>()); - -template <class T> -using NotEqualResult = decltype(std::declval<T>() != std::declval<T>()); - -using type_traits_internal::is_detected_convertible; - -template <class... T> -using RequireAllHaveEqualT = absl::enable_if_t< - absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveNotEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, NotEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanResult, T>...>::value, - bool>; - -// Helper template containing implementations details of variant that can't go -// in the private section. For convenience, this takes the variant type as a -// single template parameter. -template <typename T> -struct VariantHelper; - -template <typename... Ts> -struct VariantHelper<variant<Ts...>> { - // Type metafunction which returns the element type selected if - // OverloadSet::Overload() is well-formed when called with argument type U. - template <typename U> - using BestMatch = decltype( - variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>())); - - // Type metafunction which returns true if OverloadSet::Overload() is - // well-formed when called with argument type U. - // CanAccept can't be just an alias because there is a MSVC bug on parameter - // pack expansion involving decltype. - template <typename U> - struct CanAccept : - std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {}; - - // Type metafunction which returns true if Other is an instantiation of - // variant, and variants's converting constructor from Other will be - // well-formed. We will use this to remove constructors that would be - // ill-formed from the overload set. - template <typename Other> - struct CanConvertFrom; - - template <typename... Us> - struct CanConvertFrom<variant<Us...>> - : public absl::conjunction<CanAccept<Us>...> {}; -}; - -// A type with nontrivial copy ctor and trivial move ctor. -struct TrivialMoveOnly { - TrivialMoveOnly(TrivialMoveOnly&&) = default; -}; - -// Trait class to detect whether a type is trivially move constructible. -// A union's defaulted copy/move constructor is deleted if any variant member's -// copy/move constructor is nontrivial. -template <typename T> -struct IsTriviallyMoveConstructible: - std::is_move_constructible<Union<T, TrivialMoveOnly>> {}; - -// To guarantee triviality of all special-member functions that can be trivial, -// we use a chain of conditional bases for each one. -// The order of inheritance of bases from child to base are logically: -// -// variant -// VariantCopyAssignBase -// VariantMoveAssignBase -// VariantCopyBase -// VariantMoveBase -// VariantStateBaseDestructor -// VariantStateBase -// -// Note that there is a separate branch at each base that is dependent on -// whether or not that corresponding special-member-function can be trivial in -// the resultant variant type. - -template <class... T> -class VariantStateBaseDestructorNontrivial; - -template <class... T> -class VariantMoveBaseNontrivial; - -template <class... T> -class VariantCopyBaseNontrivial; - -template <class... T> -class VariantMoveAssignBaseNontrivial; - -template <class... T> -class VariantCopyAssignBaseNontrivial; - -// Base that is dependent on whether or not the destructor can be trivial. -template <class... T> -using VariantStateBaseDestructor = - absl::conditional_t<std::is_destructible<Union<T...>>::value, - VariantStateBase<T...>, - VariantStateBaseDestructorNontrivial<T...>>; - -// Base that is dependent on whether or not the move-constructor can be -// implicitly generated by the compiler (trivial or deleted). -// Previously we were using `std::is_move_constructible<Union<T...>>` to check -// whether all Ts have trivial move constructor, but it ran into a GCC bug: -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866 -// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to -// work around the bug. -template <class... T> -using VariantMoveBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_move_constructible<T>...>>, - absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value, - VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the copy-constructor can be trivial. -template <class... T> -using VariantCopyBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>, - std::is_copy_constructible<Union<T...>>>::value, - VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the move-assign can be trivial. -template <class... T> -using VariantMoveAssignBase = absl::conditional_t< - absl::disjunction< - absl::conjunction<absl::is_move_assignable<Union<T...>>, - std::is_move_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction<std::is_move_constructible<T>..., - // Note: We're not qualifying this with - // absl:: because it doesn't compile - // under MSVC. - is_move_assignable<T>...>>>::value, - VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the copy-assign can be trivial. -template <class... T> -using VariantCopyAssignBase = absl::conditional_t< - absl::disjunction< - absl::conjunction<absl::is_copy_assignable<Union<T...>>, - std::is_copy_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction<std::is_copy_constructible<T>..., - // Note: We're not qualifying this with - // absl:: because it doesn't compile - // under MSVC. - is_copy_assignable<T>...>>>::value, - VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>; - -template <class... T> -using VariantBase = VariantCopyAssignBase<T...>; - -template <class... T> -class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> { - private: - using Base = VariantStateBase<T...>; - - protected: - using Base::Base; - - VariantStateBaseDestructorNontrivial() = default; - VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) = - default; - VariantStateBaseDestructorNontrivial( - const VariantStateBaseDestructorNontrivial&) = default; - VariantStateBaseDestructorNontrivial& operator=( - VariantStateBaseDestructorNontrivial&&) = default; - VariantStateBaseDestructorNontrivial& operator=( - const VariantStateBaseDestructorNontrivial&) = default; - - struct Destroyer { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - variant_internal::AccessUnion(self->state_, i).~Alternative(); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const { - // This space intentionally left blank - } - - VariantStateBaseDestructorNontrivial* self; - }; - - void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); } - - ~VariantStateBaseDestructorNontrivial() { destroy(); } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> { - private: - using Base = VariantStateBaseDestructor<T...>; - - protected: - using Base::Base; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) Alternative( - variant_internal::AccessUnion(absl::move(other->state_), i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantMoveBaseNontrivial* self; - VariantMoveBaseNontrivial* other; - }; - - VariantMoveBaseNontrivial() = default; - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>...>::value) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default; - - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default; - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> { - private: - using Base = VariantMoveBase<T...>; - - protected: - using Base::Base; - - VariantCopyBaseNontrivial() = default; - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) - Alternative(variant_internal::AccessUnion(other->state_, i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantCopyBaseNontrivial* self; - const VariantCopyBaseNontrivial* other; - }; - - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default; - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantCopyBase<T...>; - - protected: - using Base::Base; - - VariantMoveAssignBaseNontrivial() = default; - VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default; - VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) = - default; - VariantMoveAssignBaseNontrivial& operator=( - VariantMoveAssignBaseNontrivial const&) = default; - - VariantMoveAssignBaseNontrivial& - operator=(VariantMoveAssignBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>..., - std::is_nothrow_move_assignable<T>...>::value) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantMoveAssignBase<T...>; - - protected: - using Base::Base; - - VariantCopyAssignBaseNontrivial() = default; - VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default; - VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) = - default; - VariantCopyAssignBaseNontrivial& operator=( - VariantCopyAssignBaseNontrivial&&) = default; - - VariantCopyAssignBaseNontrivial& operator=( - const VariantCopyAssignBaseNontrivial& other) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -//////////////////////////////////////// -// Visitors for Comparison Operations // -//////////////////////////////////////// - -template <class... Types> -struct EqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct NotEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w); - } -}; - -// Precondition: v.index() == w.index(); -template <class... Types> -struct SwapSameIndex { - variant<Types...>* v; - variant<Types...>* w; - template <std::size_t I> - void operator()(SizeT<I>) const { - type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v), - VariantCoreAccess::Access<I>(*w)); - } - - void operator()(SizeT<variant_npos>) const {} -}; - -// TODO(calabrese) do this from a different namespace for proper adl usage -template <class... Types> -struct Swap { - variant<Types...>* v; - variant<Types...>* w; - - void generic_swap() const { - variant<Types...> tmp(std::move(*w)); - VariantCoreAccess::Destroy(*w); - VariantCoreAccess::InitFrom(*w, std::move(*v)); - VariantCoreAccess::Destroy(*v); - VariantCoreAccess::InitFrom(*v, std::move(tmp)); - } - - void operator()(SizeT<absl::variant_npos> /*w_i*/) const { - if (!v->valueless_by_exception()) { - generic_swap(); - } - } - - template <std::size_t Wi> - void operator()(SizeT<Wi> /*w_i*/) { - if (v->index() == Wi) { - VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi); - } else { - generic_swap(); - } - } -}; - -template <typename Variant, typename = void, typename... Ts> -struct VariantHashBase { - VariantHashBase() = delete; - VariantHashBase(const VariantHashBase&) = delete; - VariantHashBase(VariantHashBase&&) = delete; - VariantHashBase& operator=(const VariantHashBase&) = delete; - VariantHashBase& operator=(VariantHashBase&&) = delete; -}; - -struct VariantHashVisitor { - template <typename T> - size_t operator()(const T& t) { - return std::hash<T>{}(t); - } -}; - -template <typename Variant, typename... Ts> -struct VariantHashBase<Variant, - absl::enable_if_t<absl::conjunction< - type_traits_internal::IsHashable<Ts>...>::value>, - Ts...> { - using argument_type = Variant; - using result_type = size_t; - size_t operator()(const Variant& var) const { - type_traits_internal::AssertHashEnabled<Ts...>(); - if (var.valueless_by_exception()) { - return 239799884; - } - size_t result = VisitIndices<variant_size<Variant>::value>::Run( - PerformVisitation<VariantHashVisitor, const Variant&>{ - std::forward_as_tuple(var), VariantHashVisitor{}}, - var.index()); - // Combine the index and the hash result in order to distinguish - // std::variant<int, int> holding the same value as different alternative. - return result ^ var.index(); - } -}; - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // !defined(ABSL_USES_STD_VARIANT) -#endif // ABSL_TYPES_variant_internal_H_ diff --git a/third_party/abseil_cpp/absl/types/optional.h b/third_party/abseil_cpp/absl/types/optional.h deleted file mode 100644 index 61540cfdb26a..000000000000 --- a/third_party/abseil_cpp/absl/types/optional.h +++ /dev/null @@ -1,776 +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. -// -// ----------------------------------------------------------------------------- -// optional.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::optional` type for holding a value which -// may or may not be present. This type is useful for providing value semantics -// for operations that may either wish to return or hold "something-or-nothing". -// -// Example: -// -// // A common way to signal operation failure is to provide an output -// // parameter and a bool return type: -// bool AcquireResource(const Input&, Resource * out); -// -// // Providing an absl::optional return type provides a cleaner API: -// absl::optional<Resource> AcquireResource(const Input&); -// -// `absl::optional` is a C++11 compatible version of the C++17 `std::optional` -// abstraction and is designed to be a drop-in replacement for code compliant -// with C++17. -#ifndef ABSL_TYPES_OPTIONAL_H_ -#define ABSL_TYPES_OPTIONAL_H_ - -#include "absl/base/config.h" // TODO(calabrese) IWYU removal? -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_OPTIONAL - -#include <optional> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_optional_access; -using std::optional; -using std::make_optional; -using std::nullopt_t; -using std::nullopt; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_OPTIONAL - -#include <cassert> -#include <functional> -#include <initializer_list> -#include <type_traits> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_optional_access.h" -#include "absl/types/internal/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// nullopt_t -// -// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type -// that does not contain a value. -struct nullopt_t { - // It must not be default-constructible to avoid ambiguity for opt = {}. - explicit constexpr nullopt_t(optional_internal::init_t) noexcept {} -}; - -// nullopt -// -// A tag constant of type `absl::nullopt_t` used to indicate an empty -// `absl::optional` in certain functions, such as construction or assignment. -ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt, - nullopt_t(optional_internal::init_t())); - -// ----------------------------------------------------------------------------- -// absl::optional -// ----------------------------------------------------------------------------- -// -// A value of type `absl::optional<T>` holds either a value of `T` or an -// "empty" value. When it holds a value of `T`, it stores it as a direct -// sub-object, so `sizeof(optional<T>)` is approximately -// `sizeof(T) + sizeof(bool)`. -// -// This implementation is based on the specification in the latest draft of the -// C++17 `std::optional` specification as of May 2017, section 20.6. -// -// Differences between `absl::optional<T>` and `std::optional<T>` include: -// -// * `constexpr` is not used for non-const member functions. -// (dependency on some differences between C++11 and C++14.) -// * `absl::nullopt` and `absl::in_place` are not declared `constexpr`. We -// need the inline variable support in C++17 for external linkage. -// * Throws `absl::bad_optional_access` instead of -// `std::bad_optional_access`. -// * `make_optional()` cannot be declared `constexpr` due to the absence of -// guaranteed copy elision. -// * The move constructor's `noexcept` specification is stronger, i.e. if the -// default allocator is non-throwing (via setting -// `ABSL_ALLOCATOR_NOTHROW`), it evaluates to `noexcept(true)`, because -// we assume -// a) move constructors should only throw due to allocation failure and -// b) if T's move constructor allocates, it uses the same allocation -// function as the default allocator. -// -template <typename T> -class optional : private optional_internal::optional_data<T>, - private optional_internal::optional_ctor_base< - optional_internal::ctor_copy_traits<T>::traits>, - private optional_internal::optional_assign_base< - optional_internal::assign_copy_traits<T>::traits> { - using data_base = optional_internal::optional_data<T>; - - public: - typedef T value_type; - - // Constructors - - // Constructs an `optional` holding an empty value, NOT a default constructed - // `T`. - constexpr optional() noexcept {} - - // Constructs an `optional` initialized with `nullopt` to hold an empty value. - constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit) - - // Copy constructor, standard semantics - optional(const optional&) = default; - - // Move constructor, standard semantics - optional(optional&&) = default; - - // Constructs a non-empty `optional` direct-initialized value of type `T` from - // the arguments `std::forward<Args>(args)...` within the `optional`. - // (The `in_place_t` is a tag used to indicate that the contained object - // should be constructed in-place.) - template <typename InPlaceT, typename... Args, - absl::enable_if_t<absl::conjunction< - std::is_same<InPlaceT, in_place_t>, - std::is_constructible<T, Args&&...> >::value>* = nullptr> - constexpr explicit optional(InPlaceT, Args&&... args) - : data_base(in_place_t(), absl::forward<Args>(args)...) {} - - // Constructs a non-empty `optional` direct-initialized value of type `T` from - // the arguments of an initializer_list and `std::forward<Args>(args)...`. - // (The `in_place_t` is a tag used to indicate that the contained object - // should be constructed in-place.) - template <typename U, typename... Args, - typename = typename std::enable_if<std::is_constructible< - T, std::initializer_list<U>&, Args&&...>::value>::type> - constexpr explicit optional(in_place_t, std::initializer_list<U> il, - Args&&... args) - : data_base(in_place_t(), il, absl::forward<Args>(args)...) { - } - - // Value constructor (implicit) - template < - typename U = T, - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same< - in_place_t, typename std::decay<U>::type> >, - absl::negation<std::is_same< - optional<T>, typename std::decay<U>::type> >, - std::is_convertible<U&&, T>, - std::is_constructible<T, U&&> >::value, - bool>::type = false> - constexpr optional(U&& v) : data_base(in_place_t(), absl::forward<U>(v)) {} - - // Value constructor (explicit) - template < - typename U = T, - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same< - in_place_t, typename std::decay<U>::type>>, - absl::negation<std::is_same< - optional<T>, typename std::decay<U>::type>>, - absl::negation<std::is_convertible<U&&, T>>, - std::is_constructible<T, U&&>>::value, - bool>::type = false> - explicit constexpr optional(U&& v) - : data_base(in_place_t(), absl::forward<U>(v)) {} - - // Converting copy constructor (implicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U> >, - std::is_constructible<T, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U> >, - std::is_convertible<const U&, T> >::value, - bool>::type = false> - optional(const optional<U>& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting copy constructor (explicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U>>, - absl::negation<std::is_convertible<const U&, T>>>::value, - bool>::type = false> - explicit optional(const optional<U>& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting move constructor (implicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U> >, - std::is_constructible<T, U&&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U> >, - std::is_convertible<U&&, T> >::value, - bool>::type = false> - optional(optional<U>&& rhs) { - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Converting move constructor (explicit) - template < - typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - absl::negation< - optional_internal::is_constructible_convertible_from_optional< - T, U>>, - absl::negation<std::is_convertible<U&&, T>>>::value, - bool>::type = false> - explicit optional(optional<U>&& rhs) { - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Destructor. Trivial if `T` is trivially destructible. - ~optional() = default; - - // Assignment Operators - - // Assignment from `nullopt` - // - // Example: - // - // struct S { int value; }; - // optional<S> opt = absl::nullopt; // Could also use opt = { }; - optional& operator=(nullopt_t) noexcept { - this->destruct(); - return *this; - } - - // Copy assignment operator, standard semantics - optional& operator=(const optional& src) = default; - - // Move assignment operator, standard semantics - optional& operator=(optional&& src) = default; - - // Value assignment operators - template < - typename U = T, - typename = typename std::enable_if<absl::conjunction< - absl::negation< - std::is_same<optional<T>, typename std::decay<U>::type>>, - absl::negation< - absl::conjunction<std::is_scalar<T>, - std::is_same<T, typename std::decay<U>::type>>>, - std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type> - optional& operator=(U&& v) { - this->assign(std::forward<U>(v)); - return *this; - } - - template < - typename U, - typename = typename std::enable_if<absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_assignable_from_optional< - T, U>>>::value>::type> - optional& operator=(const optional<U>& rhs) { - if (rhs) { - this->assign(*rhs); - } else { - this->destruct(); - } - return *this; - } - - template <typename U, - typename = typename std::enable_if<absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U>, - std::is_assignable<T&, U>, - absl::negation< - optional_internal:: - is_constructible_convertible_assignable_from_optional< - T, U>>>::value>::type> - optional& operator=(optional<U>&& rhs) { - if (rhs) { - this->assign(std::move(*rhs)); - } else { - this->destruct(); - } - return *this; - } - - // Modifiers - - // optional::reset() - // - // Destroys the inner `T` value of an `absl::optional` if one is present. - ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); } - - // optional::emplace() - // - // (Re)constructs the underlying `T` in-place with the given forwarded - // arguments. - // - // Example: - // - // optional<Foo> opt; - // opt.emplace(arg1,arg2,arg3); // Constructs Foo(arg1,arg2,arg3) - // - // If the optional is non-empty, and the `args` refer to subobjects of the - // current object, then behaviour is undefined, because the current object - // will be destructed before the new object is constructed with `args`. - template <typename... Args, - typename = typename std::enable_if< - std::is_constructible<T, Args&&...>::value>::type> - T& emplace(Args&&... args) { - this->destruct(); - this->construct(std::forward<Args>(args)...); - return reference(); - } - - // Emplace reconstruction overload for an initializer list and the given - // forwarded arguments. - // - // Example: - // - // struct Foo { - // Foo(std::initializer_list<int>); - // }; - // - // optional<Foo> opt; - // opt.emplace({1,2,3}); // Constructs Foo({1,2,3}) - template <typename U, typename... Args, - typename = typename std::enable_if<std::is_constructible< - T, std::initializer_list<U>&, Args&&...>::value>::type> - T& emplace(std::initializer_list<U> il, Args&&... args) { - this->destruct(); - this->construct(il, std::forward<Args>(args)...); - return reference(); - } - - // Swaps - - // Swap, standard semantics - void swap(optional& rhs) noexcept( - std::is_nothrow_move_constructible<T>::value&& - type_traits_internal::IsNothrowSwappable<T>::value) { - if (*this) { - if (rhs) { - type_traits_internal::Swap(**this, *rhs); - } else { - rhs.construct(std::move(**this)); - this->destruct(); - } - } else { - if (rhs) { - this->construct(std::move(*rhs)); - rhs.destruct(); - } else { - // No effect (swap(disengaged, disengaged)). - } - } - } - - // Observers - - // optional::operator->() - // - // Accesses the underlying `T` value's member `m` of an `optional`. If the - // `optional` is empty, behavior is undefined. - // - // If you need myOpt->foo in constexpr, use (*myOpt).foo instead. - const T* operator->() const { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::addressof(this->data_); - } - T* operator->() { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::addressof(this->data_); - } - - // optional::operator*() - // - // 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(); - } - T& operator*() & { - ABSL_HARDENING_ASSERT(this->engaged_); - return reference(); - } - constexpr const T&& operator*() const && { - return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference()); - } - T&& operator*() && { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::move(reference()); - } - - // optional::operator bool() - // - // Returns false if and only if the `optional` is empty. - // - // if (opt) { - // // do something with *opt or opt->; - // } else { - // // opt is empty. - // } - // - constexpr explicit operator bool() const noexcept { return this->engaged_; } - - // optional::has_value() - // - // Determines whether the `optional` contains a value. Returns `false` if and - // only if `*this` is empty. - constexpr bool has_value() const noexcept { return this->engaged_; } - -// Suppress bogus warning on MSVC: MSVC complains call to reference() after -// throw_bad_optional_access() is unreachable. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4702) -#endif // _MSC_VER - // optional::value() - // - // Returns a reference to an `optional`s underlying value. The constness - // and lvalue/rvalue-ness of the `optional` is preserved to the view of - // the `T` sub-object. Throws `absl::bad_optional_access` when the `optional` - // is empty. - constexpr const T& value() const & { - return static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference()); - } - T& value() & { - return static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference()); - } - T&& value() && { // NOLINT(build/c++11) - return std::move( - static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference())); - } - constexpr const T&& value() const && { // NOLINT(build/c++11) - return absl::move( - static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference())); - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - - // optional::value_or() - // - // Returns either the value of `T` or a passed default `v` if the `optional` - // is empty. - template <typename U> - constexpr T value_or(U&& v) const& { - static_assert(std::is_copy_constructible<value_type>::value, - "optional<T>::value_or: T must be copy constructible"); - static_assert(std::is_convertible<U&&, value_type>::value, - "optional<T>::value_or: U must be convertible to T"); - return static_cast<bool>(*this) - ? **this - : static_cast<T>(absl::forward<U>(v)); - } - template <typename U> - T value_or(U&& v) && { // NOLINT(build/c++11) - static_assert(std::is_move_constructible<value_type>::value, - "optional<T>::value_or: T must be move constructible"); - static_assert(std::is_convertible<U&&, value_type>::value, - "optional<T>::value_or: U must be convertible to T"); - return static_cast<bool>(*this) ? std::move(**this) - : static_cast<T>(std::forward<U>(v)); - } - - private: - // Private accessors for internal storage viewed as reference to T. - constexpr const T& reference() const { return this->data_; } - T& reference() { return this->data_; } - - // T constraint checks. You can't have an optional of nullopt_t, in_place_t - // or a reference. - static_assert( - !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value, - "optional<nullopt_t> is not allowed."); - static_assert( - !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value, - "optional<in_place_t> is not allowed."); - static_assert(!std::is_reference<T>::value, - "optional<reference> is not allowed."); -}; - -// Non-member functions - -// swap() -// -// Performs a swap between two `absl::optional` objects, using standard -// semantics. -template <typename T, typename std::enable_if< - std::is_move_constructible<T>::value && - type_traits_internal::IsSwappable<T>::value, - bool>::type = false> -void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) { - a.swap(b); -} - -// make_optional() -// -// Creates a non-empty `optional<T>` where the type of `T` is deduced. An -// `absl::optional` can also be explicitly instantiated with -// `make_optional<T>(v)`. -// -// Note: `make_optional()` constructions may be declared `constexpr` for -// trivially copyable types `T`. Non-trivial types require copy elision -// support in C++17 for `make_optional` to support `constexpr` on such -// non-trivial types. -// -// Example: -// -// constexpr absl::optional<int> opt = absl::make_optional(1); -// static_assert(opt.value() == 1, ""); -template <typename T> -constexpr optional<typename std::decay<T>::type> make_optional(T&& v) { - return optional<typename std::decay<T>::type>(absl::forward<T>(v)); -} - -template <typename T, typename... Args> -constexpr optional<T> make_optional(Args&&... args) { - return optional<T>(in_place_t(), absl::forward<Args>(args)...); -} - -template <typename T, typename U, typename... Args> -constexpr optional<T> make_optional(std::initializer_list<U> il, - Args&&... args) { - return optional<T>(in_place_t(), il, - absl::forward<Args>(args)...); -} - -// Relational operators [optional.relops] - -// Empty optionals are considered equal to each other and less than non-empty -// optionals. Supports relations between optional<T> and optional<U>, between -// optional<T> and U, and between optional<T> and nullopt. -// -// Note: We're careful to support T having non-bool relationals. - -// Requires: The expression, e.g. "*x == *y" shall be well-formed and its result -// shall be convertible to bool. -// The C++17 (N4606) "Returns:" statements are translated into -// code in an obvious way here, and the original text retained as function docs. -// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; -// otherwise *x == *y. -template <typename T, typename U> -constexpr auto operator==(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x == *y)) { - return static_cast<bool>(x) != static_cast<bool>(y) - ? false - : static_cast<bool>(x) == false ? true - : static_cast<bool>(*x == *y); -} - -// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; -// otherwise *x != *y. -template <typename T, typename U> -constexpr auto operator!=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x != *y)) { - return static_cast<bool>(x) != static_cast<bool>(y) - ? true - : static_cast<bool>(x) == false ? false - : static_cast<bool>(*x != *y); -} -// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y. -template <typename T, typename U> -constexpr auto operator<(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x < *y)) { - return !y ? false : !x ? true : static_cast<bool>(*x < *y); -} -// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y. -template <typename T, typename U> -constexpr auto operator>(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x > *y)) { - return !x ? false : !y ? true : static_cast<bool>(*x > *y); -} -// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y. -template <typename T, typename U> -constexpr auto operator<=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x <= *y)) { - return !x ? true : !y ? false : static_cast<bool>(*x <= *y); -} -// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y. -template <typename T, typename U> -constexpr auto operator>=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x >= *y)) { - return !y ? true : !x ? false : static_cast<bool>(*x >= *y); -} - -// Comparison with nullopt [optional.nullops] -// The C++17 (N4606) "Returns:" statements are used directly here. -template <typename T> -constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept { - return !x; -} -template <typename T> -constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept { - return !x; -} -template <typename T> -constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { - return false; -} -template <typename T> -constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept { - return !x; -} -template <typename T> -constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { - return true; -} -template <typename T> -constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { - return false; -} -template <typename T> -constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { - return true; -} -template <typename T> -constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept { - return !x; -} - -// Comparison with T [optional.comp_with_t] - -// Requires: The expression, e.g. "*x == v" shall be well-formed and its result -// shall be convertible to bool. -// The C++17 (N4606) "Equivalent to:" statements are used directly here. -template <typename T, typename U> -constexpr auto operator==(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x == v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x == v) : false; -} -template <typename T, typename U> -constexpr auto operator==(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v == *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v == *x) : false; -} -template <typename T, typename U> -constexpr auto operator!=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x != v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x != v) : true; -} -template <typename T, typename U> -constexpr auto operator!=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v != *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v != *x) : true; -} -template <typename T, typename U> -constexpr auto operator<(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x < v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x < v) : true; -} -template <typename T, typename U> -constexpr auto operator<(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v < *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v < *x) : false; -} -template <typename T, typename U> -constexpr auto operator<=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x <= v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x <= v) : true; -} -template <typename T, typename U> -constexpr auto operator<=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v <= *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v <= *x) : false; -} -template <typename T, typename U> -constexpr auto operator>(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x > v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x > v) : false; -} -template <typename T, typename U> -constexpr auto operator>(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v > *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v > *x) : true; -} -template <typename T, typename U> -constexpr auto operator>=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x >= v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x >= v) : false; -} -template <typename T, typename U> -constexpr auto operator>=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v >= *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true; -} - -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -// std::hash specialization for absl::optional. -template <typename T> -struct hash<absl::optional<T> > - : absl::optional_internal::optional_hash_base<T> {}; - -} // namespace std - -#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS - -#endif // ABSL_USES_STD_OPTIONAL - -#endif // ABSL_TYPES_OPTIONAL_H_ diff --git a/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc deleted file mode 100644 index 8e5fe851dbb7..000000000000 --- a/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc +++ /dev/null @@ -1,292 +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/types/optional.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::optional is an alias for std::optional and -// when exceptions are not enabled. -#if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS) - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::MakeExceptionSafetyTester; - -using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; -using Optional = absl::optional<Thrower>; - -using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using MoveOptional = absl::optional<MoveThrower>; - -constexpr int kInitialInteger = 5; -constexpr int kUpdatedInteger = 10; - -template <typename OptionalT> -bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try { - return (static_cast<void>(optional.value()), false); -} catch (const absl::bad_optional_access&) { - return true; -} - -template <typename OptionalT> -AssertionResult OptionalInvariants(OptionalT* optional_ptr) { - // Check the current state post-throw for validity - auto& optional = *optional_ptr; - - if (optional.has_value() && ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() - << "Optional with value should not throw bad_optional_access when " - "accessing the value."; - } - if (!optional.has_value() && !ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() - << "Optional without a value should throw bad_optional_access when " - "accessing the value."; - } - - // Reset to a known state - optional.reset(); - - // Confirm that the known post-reset state is valid - if (optional.has_value()) { - return AssertionFailure() - << "Optional should not contain a value after being reset."; - } - if (!ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() << "Optional should throw bad_optional_access " - "when accessing the value after being reset."; - } - - return AssertionSuccess(); -} - -template <typename OptionalT> -AssertionResult CheckDisengaged(OptionalT* optional_ptr) { - auto& optional = *optional_ptr; - - if (optional.has_value()) { - return AssertionFailure() - << "Expected optional to not contain a value but a value was found."; - } - - return AssertionSuccess(); -} - -template <typename OptionalT> -AssertionResult CheckEngaged(OptionalT* optional_ptr) { - auto& optional = *optional_ptr; - - if (!optional.has_value()) { - return AssertionFailure() - << "Expected optional to contain a value but no value was found."; - } - - return AssertionSuccess(); -} - -TEST(OptionalExceptionSafety, ThrowingConstructors) { - auto thrower_nonempty = Optional(Thrower(kInitialInteger)); - testing::TestThrowingCtor<Optional>(thrower_nonempty); - - auto integer_nonempty = absl::optional<int>(kInitialInteger); - testing::TestThrowingCtor<Optional>(integer_nonempty); - testing::TestThrowingCtor<Optional>(std::move(integer_nonempty)); // NOLINT - - testing::TestThrowingCtor<Optional>(kInitialInteger); - using ThrowerVec = std::vector<Thrower, testing::ThrowingAllocator<Thrower>>; - testing::TestThrowingCtor<absl::optional<ThrowerVec>>( - absl::in_place, - std::initializer_list<Thrower>{Thrower(), Thrower(), Thrower()}, - testing::ThrowingAllocator<Thrower>()); -} - -TEST(OptionalExceptionSafety, NothrowConstructors) { - // This constructor is marked noexcept. If it throws, the program will - // terminate. - testing::TestThrowingCtor<MoveOptional>(MoveOptional(kUpdatedInteger)); -} - -TEST(OptionalExceptionSafety, Emplace) { - // Test the basic guarantee plus test the result of optional::has_value() - // is false in all cases - auto disengaged_test = MakeExceptionSafetyTester().WithContracts( - OptionalInvariants<Optional>, CheckDisengaged<Optional>); - auto disengaged_test_empty = disengaged_test.WithInitialValue(Optional()); - auto disengaged_test_nonempty = - disengaged_test.WithInitialValue(Optional(kInitialInteger)); - - auto emplace_thrower_directly = [](Optional* optional_ptr) { - optional_ptr->emplace(kUpdatedInteger); - }; - EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_directly)); - EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_directly)); - - auto emplace_thrower_copy = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - optional_ptr->emplace(thrower); - }; - EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_copy)); - EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_copy)); -} - -TEST(OptionalExceptionSafety, EverythingThrowsSwap) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto swap_empty = [](Optional* optional_ptr) { - auto empty = Optional(); - optional_ptr->swap(empty); - }; - EXPECT_TRUE(engaged_test_nonempty.Test(swap_empty)); - - auto swap_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - optional_ptr->swap(nonempty); - }; - EXPECT_TRUE(disengaged_test_empty.Test(swap_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(swap_nonempty)); -} - -TEST(OptionalExceptionSafety, NoThrowMoveSwap) { - // Tests the nothrow guarantee for optional of T with non-throwing move - { - auto empty = MoveOptional(); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty.swap(empty); })); - } - { - auto nonempty = MoveOptional(kUpdatedInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty.swap(nonempty); })); - } - { - auto nonempty_from = MoveOptional(kUpdatedInteger); - auto nonempty_to = MoveOptional(kInitialInteger); - EXPECT_TRUE( - testing::TestNothrowOp([&]() { nonempty_to.swap(nonempty_from); })); - } -} - -TEST(OptionalExceptionSafety, CopyAssign) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto copyassign_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = nonempty; - }; - EXPECT_TRUE(disengaged_test_empty.Test(copyassign_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_nonempty)); - - auto copyassign_thrower = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = thrower; - }; - EXPECT_TRUE(disengaged_test_empty.Test(copyassign_thrower)); - EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_thrower)); -} - -TEST(OptionalExceptionSafety, MoveAssign) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto moveassign_empty = [](Optional* optional_ptr) { - auto empty = Optional(); - *optional_ptr = std::move(empty); - }; - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_empty)); - - auto moveassign_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = std::move(nonempty); - }; - EXPECT_TRUE(disengaged_test_empty.Test(moveassign_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_nonempty)); - - auto moveassign_thrower = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = std::move(thrower); - }; - EXPECT_TRUE(disengaged_test_empty.Test(moveassign_thrower)); - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_thrower)); -} - -TEST(OptionalExceptionSafety, NothrowMoveAssign) { - // Tests the nothrow guarantee for optional of T with non-throwing move - { - auto empty = MoveOptional(); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty = std::move(empty); })); - } - { - auto nonempty = MoveOptional(kInitialInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(nonempty); })); - } - { - auto nonempty_from = MoveOptional(kUpdatedInteger); - auto nonempty_to = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp( - [&]() { nonempty_to = std::move(nonempty_from); })); - } - { - auto thrower = MoveThrower(kUpdatedInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(thrower); })); - } - { - auto thrower = MoveThrower(kUpdatedInteger); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE( - testing::TestNothrowOp([&]() { nonempty = std::move(thrower); })); - } -} - -} // namespace - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/types/optional_test.cc b/third_party/abseil_cpp/absl/types/optional_test.cc deleted file mode 100644 index 7ef142cb9937..000000000000 --- a/third_party/abseil_cpp/absl/types/optional_test.cc +++ /dev/null @@ -1,1659 +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/types/optional.h" - -// This test is a no-op when absl::optional is an alias for std::optional. -#if !defined(ABSL_USES_STD_OPTIONAL) - -#include <string> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -struct Hashable {}; - -namespace std { -template <> -struct hash<Hashable> { - size_t operator()(const Hashable&) { return 0; } -}; -} // namespace std - -struct NonHashable {}; - -namespace { - -std::string TypeQuals(std::string&) { return "&"; } -std::string TypeQuals(std::string&&) { return "&&"; } -std::string TypeQuals(const std::string&) { return "c&"; } -std::string TypeQuals(const std::string&&) { return "c&&"; } - -struct StructorListener { - int construct0 = 0; - int construct1 = 0; - int construct2 = 0; - int listinit = 0; - int copy = 0; - int move = 0; - int copy_assign = 0; - int move_assign = 0; - int destruct = 0; - int volatile_copy = 0; - int volatile_move = 0; - int volatile_copy_assign = 0; - int volatile_move_assign = 0; -}; - -// Suppress MSVC warnings. -// 4521: multiple copy constructors specified -// 4522: multiple assignment operators specified -// We wrote multiple of them to test that the correct overloads are selected. -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4521) -#pragma warning( disable : 4522) -#endif -struct Listenable { - static StructorListener* listener; - - Listenable() { ++listener->construct0; } - explicit Listenable(int /*unused*/) { ++listener->construct1; } - Listenable(int /*unused*/, int /*unused*/) { ++listener->construct2; } - Listenable(std::initializer_list<int> /*unused*/) { ++listener->listinit; } - Listenable(const Listenable& /*unused*/) { ++listener->copy; } - Listenable(const volatile Listenable& /*unused*/) { - ++listener->volatile_copy; - } - Listenable(volatile Listenable&& /*unused*/) { ++listener->volatile_move; } - Listenable(Listenable&& /*unused*/) { ++listener->move; } - Listenable& operator=(const Listenable& /*unused*/) { - ++listener->copy_assign; - return *this; - } - Listenable& operator=(Listenable&& /*unused*/) { - ++listener->move_assign; - return *this; - } - // use void return type instead of volatile T& to work around GCC warning - // when the assignment's returned reference is ignored. - void operator=(const volatile Listenable& /*unused*/) volatile { - ++listener->volatile_copy_assign; - } - void operator=(volatile Listenable&& /*unused*/) volatile { - ++listener->volatile_move_assign; - } - ~Listenable() { ++listener->destruct; } -}; -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -StructorListener* Listenable::listener = nullptr; - -// ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST is defined to 1 when the standard -// library implementation doesn't marked initializer_list's default constructor -// constexpr. The C++11 standard doesn't specify constexpr on it, but C++14 -// added it. However, libstdc++ 4.7 marked it constexpr. -#if defined(_LIBCPP_VERSION) && \ - (_LIBCPP_STD_VER <= 11 || defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)) -#define ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST 1 -#endif - -struct ConstexprType { - enum CtorTypes { - kCtorDefault, - kCtorInt, - kCtorInitializerList, - kCtorConstChar - }; - constexpr ConstexprType() : x(kCtorDefault) {} - constexpr explicit ConstexprType(int i) : x(kCtorInt) {} -#ifndef ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST - constexpr ConstexprType(std::initializer_list<int> il) - : x(kCtorInitializerList) {} -#endif - constexpr ConstexprType(const char*) // NOLINT(runtime/explicit) - : x(kCtorConstChar) {} - int x; -}; - -struct Copyable { - Copyable() {} - Copyable(const Copyable&) {} - Copyable& operator=(const Copyable&) { return *this; } -}; - -struct MoveableThrow { - MoveableThrow() {} - MoveableThrow(MoveableThrow&&) {} - MoveableThrow& operator=(MoveableThrow&&) { return *this; } -}; - -struct MoveableNoThrow { - MoveableNoThrow() {} - MoveableNoThrow(MoveableNoThrow&&) noexcept {} - MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept { return *this; } -}; - -struct NonMovable { - NonMovable() {} - NonMovable(const NonMovable&) = delete; - NonMovable& operator=(const NonMovable&) = delete; - NonMovable(NonMovable&&) = delete; - NonMovable& operator=(NonMovable&&) = delete; -}; - -struct NoDefault { - NoDefault() = delete; - NoDefault(const NoDefault&) {} - NoDefault& operator=(const NoDefault&) { return *this; } -}; - -struct ConvertsFromInPlaceT { - ConvertsFromInPlaceT(absl::in_place_t) {} // NOLINT -}; - -TEST(optionalTest, DefaultConstructor) { - absl::optional<int> empty; - EXPECT_FALSE(empty); - constexpr absl::optional<int> cempty; - static_assert(!cempty.has_value(), ""); - EXPECT_TRUE( - std::is_nothrow_default_constructible<absl::optional<int>>::value); -} - -TEST(optionalTest, nulloptConstructor) { - absl::optional<int> empty(absl::nullopt); - EXPECT_FALSE(empty); - constexpr absl::optional<int> cempty{absl::nullopt}; - static_assert(!cempty.has_value(), ""); - EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>, - absl::nullopt_t>::value)); -} - -TEST(optionalTest, CopyConstructor) { - { - absl::optional<int> empty, opt42 = 42; - absl::optional<int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - { - absl::optional<const int> empty, opt42 = 42; - absl::optional<const int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<const int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - { - absl::optional<volatile int> empty, opt42 = 42; - absl::optional<volatile int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<volatile int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - // test copyablility - EXPECT_TRUE(std::is_copy_constructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_copy_constructible<absl::optional<Copyable>>::value); - EXPECT_FALSE( - std::is_copy_constructible<absl::optional<MoveableThrow>>::value); - EXPECT_FALSE( - std::is_copy_constructible<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_copy_constructible<absl::optional<NonMovable>>::value); - - EXPECT_FALSE( - absl::is_trivially_copy_constructible<absl::optional<Copyable>>::value); -#if defined(ABSL_USES_STD_OPTIONAL) && defined(__GLIBCXX__) - // libstdc++ std::optional implementation (as of 7.2) has a bug: when T is - // trivially copyable, optional<T> is not trivially copyable (due to one of - // its base class is unconditionally nontrivial). -#define ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG 1 -#endif -#ifndef ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - EXPECT_TRUE( - absl::is_trivially_copy_constructible<absl::optional<int>>::value); - EXPECT_TRUE( - absl::is_trivially_copy_constructible<absl::optional<const int>>::value); -#ifndef _MSC_VER - // See defect report "Trivial copy/move constructor for class with volatile - // member" at - // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094 - // A class with non-static data member of volatile-qualified type should still - // have a trivial copy constructor if the data member is trivial. - // Also a cv-qualified scalar type should be trivially copyable. - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<volatile int>>::value); -#endif // _MSC_VER -#endif // ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - - // constexpr copy constructor for trivially copyable types - { - constexpr absl::optional<int> o1; - constexpr absl::optional<int> o2 = o1; - static_assert(!o2, ""); - } - { - constexpr absl::optional<int> o1 = 42; - constexpr absl::optional<int> o2 = o1; - static_assert(o2, ""); - static_assert(*o2 == 42, ""); - } - { - struct TrivialCopyable { - constexpr TrivialCopyable() : x(0) {} - constexpr explicit TrivialCopyable(int i) : x(i) {} - int x; - }; - constexpr absl::optional<TrivialCopyable> o1(42); - constexpr absl::optional<TrivialCopyable> o2 = o1; - static_assert(o2, ""); - static_assert((*o2).x == 42, ""); -#ifndef ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<TrivialCopyable>>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<const TrivialCopyable>>::value); -#endif - // When testing with VS 2017 15.3, there seems to be a bug in MSVC - // std::optional when T is volatile-qualified. So skipping this test. - // Bug report: - // https://connect.microsoft.com/VisualStudio/feedback/details/3142534 -#if defined(ABSL_USES_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911 -#define ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG 1 -#endif -#ifndef ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG - EXPECT_FALSE(std::is_copy_constructible< - absl::optional<volatile TrivialCopyable>>::value); -#endif - } -} - -TEST(optionalTest, MoveConstructor) { - absl::optional<int> empty, opt42 = 42; - absl::optional<int> empty_move(std::move(empty)); - EXPECT_FALSE(empty_move); - absl::optional<int> opt42_move(std::move(opt42)); - EXPECT_TRUE(opt42_move); - EXPECT_EQ(42, opt42_move); - // test movability - EXPECT_TRUE(std::is_move_constructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_move_constructible<absl::optional<Copyable>>::value); - EXPECT_TRUE(std::is_move_constructible<absl::optional<MoveableThrow>>::value); - EXPECT_TRUE( - std::is_move_constructible<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_move_constructible<absl::optional<NonMovable>>::value); - // test noexcept - EXPECT_TRUE(std::is_nothrow_move_constructible<absl::optional<int>>::value); -#ifndef ABSL_USES_STD_OPTIONAL - EXPECT_EQ( - absl::default_allocator_is_nothrow::value, - std::is_nothrow_move_constructible<absl::optional<MoveableThrow>>::value); -#endif - EXPECT_TRUE(std::is_nothrow_move_constructible< - absl::optional<MoveableNoThrow>>::value); -} - -TEST(optionalTest, Destructor) { - struct Trivial {}; - - struct NonTrivial { - NonTrivial(const NonTrivial&) {} - NonTrivial& operator=(const NonTrivial&) { return *this; } - ~NonTrivial() {} - }; - - EXPECT_TRUE(std::is_trivially_destructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_trivially_destructible<absl::optional<Trivial>>::value); - EXPECT_FALSE( - std::is_trivially_destructible<absl::optional<NonTrivial>>::value); -} - -TEST(optionalTest, InPlaceConstructor) { - constexpr absl::optional<ConstexprType> opt0{absl::in_place_t()}; - static_assert(opt0, ""); - static_assert((*opt0).x == ConstexprType::kCtorDefault, ""); - constexpr absl::optional<ConstexprType> opt1{absl::in_place_t(), 1}; - static_assert(opt1, ""); - static_assert((*opt1).x == ConstexprType::kCtorInt, ""); -#ifndef ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST - constexpr absl::optional<ConstexprType> opt2{absl::in_place_t(), {1, 2}}; - static_assert(opt2, ""); - static_assert((*opt2).x == ConstexprType::kCtorInitializerList, ""); -#endif - - EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - absl::in_place_t>::value)); - EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - const absl::in_place_t&>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - absl::in_place_t, absl::in_place_t>::value)); - - EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>, - absl::in_place_t>::value)); - EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>, - absl::in_place_t&&>::value)); -} - -// template<U=T> optional(U&&); -TEST(optionalTest, ValueConstructor) { - constexpr absl::optional<int> opt0(0); - static_assert(opt0, ""); - static_assert(*opt0 == 0, ""); - EXPECT_TRUE((std::is_convertible<int, absl::optional<int>>::value)); - // Copy initialization ( = "abc") won't work due to optional(optional&&) - // is not constexpr. Use list initialization instead. This invokes - // absl::optional<ConstexprType>::absl::optional<U>(U&&), with U = const char - // (&) [4], which direct-initializes the ConstexprType value held by the - // optional via ConstexprType::ConstexprType(const char*). - constexpr absl::optional<ConstexprType> opt1 = {"abc"}; - static_assert(opt1, ""); - static_assert(ConstexprType::kCtorConstChar == (*opt1).x, ""); - EXPECT_TRUE( - (std::is_convertible<const char*, absl::optional<ConstexprType>>::value)); - // direct initialization - constexpr absl::optional<ConstexprType> opt2{2}; - static_assert(opt2, ""); - static_assert(ConstexprType::kCtorInt == (*opt2).x, ""); - EXPECT_FALSE( - (std::is_convertible<int, absl::optional<ConstexprType>>::value)); - - // this invokes absl::optional<int>::optional(int&&) - // NOTE: this has different behavior than assignment, e.g. - // "opt3 = {};" clears the optional rather than setting the value to 0 - // According to C++17 standard N4659 [over.ics.list] 16.3.3.1.5, (9.2)- "if - // the initializer list has no elements, the implicit conversion is the - // identity conversion", so `optional(int&&)` should be a better match than - // `optional(optional&&)` which is a user-defined conversion. - // Note: GCC 7 has a bug with this overload selection when compiled with - // `-std=c++17`. -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 7 && \ - __cplusplus == 201703L -#define ABSL_GCC7_OVER_ICS_LIST_BUG 1 -#endif -#ifndef ABSL_GCC7_OVER_ICS_LIST_BUG - constexpr absl::optional<int> opt3({}); - static_assert(opt3, ""); - static_assert(*opt3 == 0, ""); -#endif - - // this invokes the move constructor with a default constructed optional - // because non-template function is a better match than template function. - absl::optional<ConstexprType> opt4({}); - EXPECT_FALSE(opt4); -} - -struct Implicit {}; - -struct Explicit {}; - -struct Convert { - Convert(const Implicit&) // NOLINT(runtime/explicit) - : implicit(true), move(false) {} - Convert(Implicit&&) // NOLINT(runtime/explicit) - : implicit(true), move(true) {} - explicit Convert(const Explicit&) : implicit(false), move(false) {} - explicit Convert(Explicit&&) : implicit(false), move(true) {} - - bool implicit; - bool move; -}; - -struct ConvertFromOptional { - ConvertFromOptional(const Implicit&) // NOLINT(runtime/explicit) - : implicit(true), move(false), from_optional(false) {} - ConvertFromOptional(Implicit&&) // NOLINT(runtime/explicit) - : implicit(true), move(true), from_optional(false) {} - ConvertFromOptional( - const absl::optional<Implicit>&) // NOLINT(runtime/explicit) - : implicit(true), move(false), from_optional(true) {} - ConvertFromOptional(absl::optional<Implicit>&&) // NOLINT(runtime/explicit) - : implicit(true), move(true), from_optional(true) {} - explicit ConvertFromOptional(const Explicit&) - : implicit(false), move(false), from_optional(false) {} - explicit ConvertFromOptional(Explicit&&) - : implicit(false), move(true), from_optional(false) {} - explicit ConvertFromOptional(const absl::optional<Explicit>&) - : implicit(false), move(false), from_optional(true) {} - explicit ConvertFromOptional(absl::optional<Explicit>&&) - : implicit(false), move(true), from_optional(true) {} - - bool implicit; - bool move; - bool from_optional; -}; - -TEST(optionalTest, ConvertingConstructor) { - absl::optional<Implicit> i_empty; - absl::optional<Implicit> i(absl::in_place); - absl::optional<Explicit> e_empty; - absl::optional<Explicit> e(absl::in_place); - { - // implicitly constructing absl::optional<Convert> from - // absl::optional<Implicit> - absl::optional<Convert> empty = i_empty; - EXPECT_FALSE(empty); - absl::optional<Convert> opt_copy = i; - EXPECT_TRUE(opt_copy); - EXPECT_TRUE(opt_copy->implicit); - EXPECT_FALSE(opt_copy->move); - absl::optional<Convert> opt_move = absl::optional<Implicit>(absl::in_place); - EXPECT_TRUE(opt_move); - EXPECT_TRUE(opt_move->implicit); - EXPECT_TRUE(opt_move->move); - } - { - // explicitly constructing absl::optional<Convert> from - // absl::optional<Explicit> - absl::optional<Convert> empty(e_empty); - EXPECT_FALSE(empty); - absl::optional<Convert> opt_copy(e); - EXPECT_TRUE(opt_copy); - EXPECT_FALSE(opt_copy->implicit); - EXPECT_FALSE(opt_copy->move); - EXPECT_FALSE((std::is_convertible<const absl::optional<Explicit>&, - absl::optional<Convert>>::value)); - absl::optional<Convert> opt_move{absl::optional<Explicit>(absl::in_place)}; - EXPECT_TRUE(opt_move); - EXPECT_FALSE(opt_move->implicit); - EXPECT_TRUE(opt_move->move); - EXPECT_FALSE((std::is_convertible<absl::optional<Explicit>&&, - absl::optional<Convert>>::value)); - } - { - // implicitly constructing absl::optional<ConvertFromOptional> from - // absl::optional<Implicit> via - // ConvertFromOptional(absl::optional<Implicit>&&) check that - // ConvertFromOptional(Implicit&&) is NOT called - static_assert( - std::is_convertible<absl::optional<Implicit>, - absl::optional<ConvertFromOptional>>::value, - ""); - absl::optional<ConvertFromOptional> opt0 = i_empty; - EXPECT_TRUE(opt0); - EXPECT_TRUE(opt0->implicit); - EXPECT_FALSE(opt0->move); - EXPECT_TRUE(opt0->from_optional); - absl::optional<ConvertFromOptional> opt1 = absl::optional<Implicit>(); - EXPECT_TRUE(opt1); - EXPECT_TRUE(opt1->implicit); - EXPECT_TRUE(opt1->move); - EXPECT_TRUE(opt1->from_optional); - } - { - // implicitly constructing absl::optional<ConvertFromOptional> from - // absl::optional<Explicit> via - // ConvertFromOptional(absl::optional<Explicit>&&) check that - // ConvertFromOptional(Explicit&&) is NOT called - absl::optional<ConvertFromOptional> opt0(e_empty); - EXPECT_TRUE(opt0); - EXPECT_FALSE(opt0->implicit); - EXPECT_FALSE(opt0->move); - EXPECT_TRUE(opt0->from_optional); - EXPECT_FALSE( - (std::is_convertible<const absl::optional<Explicit>&, - absl::optional<ConvertFromOptional>>::value)); - absl::optional<ConvertFromOptional> opt1{absl::optional<Explicit>()}; - EXPECT_TRUE(opt1); - EXPECT_FALSE(opt1->implicit); - EXPECT_TRUE(opt1->move); - EXPECT_TRUE(opt1->from_optional); - EXPECT_FALSE( - (std::is_convertible<absl::optional<Explicit>&&, - absl::optional<ConvertFromOptional>>::value)); - } -} - -TEST(optionalTest, StructorBasic) { - StructorListener listener; - Listenable::listener = &listener; - { - absl::optional<Listenable> empty; - EXPECT_FALSE(empty); - absl::optional<Listenable> opt0(absl::in_place); - EXPECT_TRUE(opt0); - absl::optional<Listenable> opt1(absl::in_place, 1); - EXPECT_TRUE(opt1); - absl::optional<Listenable> opt2(absl::in_place, 1, 2); - EXPECT_TRUE(opt2); - } - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.construct1); - EXPECT_EQ(1, listener.construct2); - EXPECT_EQ(3, listener.destruct); -} - -TEST(optionalTest, CopyMoveStructor) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> original(absl::in_place); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(0, listener.copy); - EXPECT_EQ(0, listener.move); - absl::optional<Listenable> copy(original); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.copy); - EXPECT_EQ(0, listener.move); - absl::optional<Listenable> move(std::move(original)); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.copy); - EXPECT_EQ(1, listener.move); -} - -TEST(optionalTest, ListInit) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> listinit1(absl::in_place, {1}); - absl::optional<Listenable> listinit2(absl::in_place, {1, 2}); - EXPECT_EQ(2, listener.listinit); -} - -TEST(optionalTest, AssignFromNullopt) { - absl::optional<int> opt(1); - opt = absl::nullopt; - EXPECT_FALSE(opt); - - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt1(absl::in_place); - opt1 = absl::nullopt; - EXPECT_FALSE(opt1); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.destruct); - - EXPECT_TRUE(( - std::is_nothrow_assignable<absl::optional<int>, absl::nullopt_t>::value)); - EXPECT_TRUE((std::is_nothrow_assignable<absl::optional<Listenable>, - absl::nullopt_t>::value)); -} - -TEST(optionalTest, CopyAssignment) { - const absl::optional<int> empty, opt1 = 1, opt2 = 2; - absl::optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty; - - EXPECT_FALSE(empty_to_opt1); - empty_to_opt1 = empty; - EXPECT_FALSE(empty_to_opt1); - empty_to_opt1 = opt1; - EXPECT_TRUE(empty_to_opt1); - EXPECT_EQ(1, empty_to_opt1.value()); - - EXPECT_FALSE(opt1_to_opt2); - opt1_to_opt2 = opt1; - EXPECT_TRUE(opt1_to_opt2); - EXPECT_EQ(1, opt1_to_opt2.value()); - opt1_to_opt2 = opt2; - EXPECT_TRUE(opt1_to_opt2); - EXPECT_EQ(2, opt1_to_opt2.value()); - - EXPECT_FALSE(opt2_to_empty); - opt2_to_empty = opt2; - EXPECT_TRUE(opt2_to_empty); - EXPECT_EQ(2, opt2_to_empty.value()); - opt2_to_empty = empty; - EXPECT_FALSE(opt2_to_empty); - - EXPECT_FALSE(absl::is_copy_assignable<absl::optional<const int>>::value); - EXPECT_TRUE(absl::is_copy_assignable<absl::optional<Copyable>>::value); - EXPECT_FALSE(absl::is_copy_assignable<absl::optional<MoveableThrow>>::value); - EXPECT_FALSE( - absl::is_copy_assignable<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(absl::is_copy_assignable<absl::optional<NonMovable>>::value); - - EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<volatile int>::value); - - struct Trivial { - int i; - }; - struct NonTrivial { - NonTrivial& operator=(const NonTrivial&) { return *this; } - int i; - }; - - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value); - EXPECT_FALSE(absl::is_copy_assignable<const Trivial>::value); - EXPECT_FALSE(absl::is_copy_assignable<volatile Trivial>::value); - EXPECT_TRUE(absl::is_copy_assignable<NonTrivial>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value); - - // std::optional doesn't support volatile nontrivial types. -#ifndef ABSL_USES_STD_OPTIONAL - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<volatile Listenable> empty, set(absl::in_place); - EXPECT_EQ(1, listener.construct0); - absl::optional<volatile Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(3, listener.construct0); - empty_to_empty = empty; // no effect - empty_to_set = set; // copy construct - set_to_empty = empty; // destruct - set_to_set = set; // copy assign - EXPECT_EQ(1, listener.volatile_copy); - EXPECT_EQ(0, listener.volatile_move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.volatile_copy_assign); - } -#endif // ABSL_USES_STD_OPTIONAL -} - -TEST(optionalTest, MoveAssignment) { - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<Listenable> empty1, empty2, set1(absl::in_place), - set2(absl::in_place); - EXPECT_EQ(2, listener.construct0); - absl::optional<Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(4, listener.construct0); - empty_to_empty = std::move(empty1); - empty_to_set = std::move(set1); - set_to_empty = std::move(empty2); - set_to_set = std::move(set2); - EXPECT_EQ(0, listener.copy); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.move_assign); - } - // std::optional doesn't support volatile nontrivial types. -#ifndef ABSL_USES_STD_OPTIONAL - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<volatile Listenable> empty1, empty2, set1(absl::in_place), - set2(absl::in_place); - EXPECT_EQ(2, listener.construct0); - absl::optional<volatile Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(4, listener.construct0); - empty_to_empty = std::move(empty1); // no effect - empty_to_set = std::move(set1); // move construct - set_to_empty = std::move(empty2); // destruct - set_to_set = std::move(set2); // move assign - EXPECT_EQ(0, listener.volatile_copy); - EXPECT_EQ(1, listener.volatile_move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.volatile_move_assign); - } -#endif // ABSL_USES_STD_OPTIONAL - EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value); - EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value); - EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value); - EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(absl::is_move_assignable<absl::optional<NonMovable>>::value); - - EXPECT_FALSE( - std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value); - EXPECT_TRUE( - std::is_nothrow_move_assignable<absl::optional<MoveableNoThrow>>::value); -} - -struct NoConvertToOptional { - // disable implicit conversion from const NoConvertToOptional& - // to absl::optional<NoConvertToOptional>. - NoConvertToOptional(const NoConvertToOptional&) = delete; -}; - -struct CopyConvert { - CopyConvert(const NoConvertToOptional&); - CopyConvert& operator=(const CopyConvert&) = delete; - CopyConvert& operator=(const NoConvertToOptional&); -}; - -struct CopyConvertFromOptional { - CopyConvertFromOptional(const NoConvertToOptional&); - CopyConvertFromOptional(const absl::optional<NoConvertToOptional>&); - CopyConvertFromOptional& operator=(const CopyConvertFromOptional&) = delete; - CopyConvertFromOptional& operator=(const NoConvertToOptional&); - CopyConvertFromOptional& operator=( - const absl::optional<NoConvertToOptional>&); -}; - -struct MoveConvert { - MoveConvert(NoConvertToOptional&&); - MoveConvert& operator=(const MoveConvert&) = delete; - MoveConvert& operator=(NoConvertToOptional&&); -}; - -struct MoveConvertFromOptional { - MoveConvertFromOptional(NoConvertToOptional&&); - MoveConvertFromOptional(absl::optional<NoConvertToOptional>&&); - MoveConvertFromOptional& operator=(const MoveConvertFromOptional&) = delete; - MoveConvertFromOptional& operator=(NoConvertToOptional&&); - MoveConvertFromOptional& operator=(absl::optional<NoConvertToOptional>&&); -}; - -// template <typename U = T> absl::optional<T>& operator=(U&& v); -TEST(optionalTest, ValueAssignment) { - absl::optional<int> opt; - EXPECT_FALSE(opt); - opt = 42; - EXPECT_TRUE(opt); - EXPECT_EQ(42, opt.value()); - opt = absl::nullopt; - EXPECT_FALSE(opt); - opt = 42; - EXPECT_TRUE(opt); - EXPECT_EQ(42, opt.value()); - opt = 43; - EXPECT_TRUE(opt); - EXPECT_EQ(43, opt.value()); - opt = {}; // this should clear optional - EXPECT_FALSE(opt); - - opt = {44}; - EXPECT_TRUE(opt); - EXPECT_EQ(44, opt.value()); - - // U = const NoConvertToOptional& - EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvert>&, - const NoConvertToOptional&>::value)); - // U = const absl::optional<NoConvertToOptional>& - EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvertFromOptional>&, - const NoConvertToOptional&>::value)); - // U = const NoConvertToOptional& triggers SFINAE because - // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false - EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvert>&, - const NoConvertToOptional&>::value)); - // U = NoConvertToOptional - EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvert>&, - NoConvertToOptional&&>::value)); - // U = const NoConvertToOptional& triggers SFINAE because - // std::is_constructible_v<MoveConvertFromOptional, const - // NoConvertToOptional&> is false - EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvertFromOptional>&, - const NoConvertToOptional&>::value)); - // U = NoConvertToOptional - EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvertFromOptional>&, - NoConvertToOptional&&>::value)); - // U = const absl::optional<NoConvertToOptional>& - EXPECT_TRUE( - (std::is_assignable<absl::optional<CopyConvertFromOptional>&, - const absl::optional<NoConvertToOptional>&>::value)); - // U = absl::optional<NoConvertToOptional> - EXPECT_TRUE( - (std::is_assignable<absl::optional<MoveConvertFromOptional>&, - absl::optional<NoConvertToOptional>&&>::value)); -} - -// template <typename U> absl::optional<T>& operator=(const absl::optional<U>& -// rhs); template <typename U> absl::optional<T>& operator=(absl::optional<U>&& -// rhs); -TEST(optionalTest, ConvertingAssignment) { - absl::optional<int> opt_i; - absl::optional<char> opt_c('c'); - opt_i = opt_c; - EXPECT_TRUE(opt_i); - EXPECT_EQ(*opt_c, *opt_i); - opt_i = absl::optional<char>(); - EXPECT_FALSE(opt_i); - opt_i = absl::optional<char>('d'); - EXPECT_TRUE(opt_i); - EXPECT_EQ('d', *opt_i); - - absl::optional<std::string> opt_str; - absl::optional<const char*> opt_cstr("abc"); - opt_str = opt_cstr; - EXPECT_TRUE(opt_str); - EXPECT_EQ(std::string("abc"), *opt_str); - opt_str = absl::optional<const char*>(); - EXPECT_FALSE(opt_str); - opt_str = absl::optional<const char*>("def"); - EXPECT_TRUE(opt_str); - EXPECT_EQ(std::string("def"), *opt_str); - - // operator=(const absl::optional<U>&) with U = NoConvertToOptional - EXPECT_TRUE( - (std::is_assignable<absl::optional<CopyConvert>, - const absl::optional<NoConvertToOptional>&>::value)); - // operator=(const absl::optional<U>&) with U = NoConvertToOptional - // triggers SFINAE because - // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false - EXPECT_FALSE( - (std::is_assignable<absl::optional<MoveConvert>&, - const absl::optional<NoConvertToOptional>&>::value)); - // operator=(absl::optional<U>&&) with U = NoConvertToOptional - EXPECT_TRUE( - (std::is_assignable<absl::optional<MoveConvert>&, - absl::optional<NoConvertToOptional>&&>::value)); - // operator=(const absl::optional<U>&) with U = NoConvertToOptional triggers - // SFINAE because std::is_constructible_v<MoveConvertFromOptional, const - // NoConvertToOptional&> is false. operator=(U&&) with U = const - // absl::optional<NoConverToOptional>& triggers SFINAE because - // std::is_constructible<MoveConvertFromOptional, - // absl::optional<NoConvertToOptional>&&> is true. - EXPECT_FALSE( - (std::is_assignable<absl::optional<MoveConvertFromOptional>&, - const absl::optional<NoConvertToOptional>&>::value)); -} - -TEST(optionalTest, ResetAndHasValue) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - opt.emplace(); - EXPECT_TRUE(opt); - EXPECT_TRUE(opt.has_value()); - opt.reset(); - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - EXPECT_EQ(1, listener.destruct); - opt.reset(); - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - - constexpr absl::optional<int> empty; - static_assert(!empty.has_value(), ""); - constexpr absl::optional<int> nonempty(1); - static_assert(nonempty.has_value(), ""); -} - -TEST(optionalTest, Emplace) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - opt.emplace(1); - EXPECT_TRUE(opt); - opt.emplace(1, 2); - EXPECT_EQ(1, listener.construct1); - EXPECT_EQ(1, listener.construct2); - EXPECT_EQ(1, listener.destruct); - - absl::optional<std::string> o; - EXPECT_TRUE((std::is_same<std::string&, decltype(o.emplace("abc"))>::value)); - std::string& ref = o.emplace("abc"); - EXPECT_EQ(&ref, &o.value()); -} - -TEST(optionalTest, ListEmplace) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - opt.emplace({1}); - EXPECT_TRUE(opt); - opt.emplace({1, 2}); - EXPECT_EQ(2, listener.listinit); - EXPECT_EQ(1, listener.destruct); - - absl::optional<Listenable> o; - EXPECT_TRUE((std::is_same<Listenable&, decltype(o.emplace({1}))>::value)); - Listenable& ref = o.emplace({1}); - EXPECT_EQ(&ref, &o.value()); -} - -TEST(optionalTest, Swap) { - absl::optional<int> opt_empty, opt1 = 1, opt2 = 2; - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(1, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt_empty, opt1); - EXPECT_FALSE(opt1); - EXPECT_TRUE(opt_empty); - EXPECT_EQ(1, opt_empty.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt_empty, opt1); - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(1, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt1, opt2); - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(2, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(1, opt2.value()); - - EXPECT_TRUE(noexcept(opt1.swap(opt2))); - EXPECT_TRUE(noexcept(swap(opt1, opt2))); -} - -template <int v> -struct DeletedOpAddr { - int value = v; - constexpr DeletedOpAddr() = default; - constexpr const DeletedOpAddr<v>* operator&() const = delete; // NOLINT - DeletedOpAddr<v>* operator&() = delete; // NOLINT -}; - -// The static_assert featuring a constexpr call to operator->() is commented out -// to document the fact that the current implementation of absl::optional<T> -// expects such usecases to be malformed and not compile. -TEST(optionalTest, OperatorAddr) { - constexpr int v = -1; - { // constexpr - constexpr absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{}); - static_assert(opt.has_value(), ""); - // static_assert(opt->value == v, ""); - static_assert((*opt).value == v, ""); - } - { // non-constexpr - const absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{}); - EXPECT_TRUE(opt.has_value()); - EXPECT_TRUE(opt->value == v); - EXPECT_TRUE((*opt).value == v); - } -} - -TEST(optionalTest, PointerStuff) { - absl::optional<std::string> opt(absl::in_place, "foo"); - EXPECT_EQ("foo", *opt); - const auto& opt_const = opt; - EXPECT_EQ("foo", *opt_const); - EXPECT_EQ(opt->size(), 3); - EXPECT_EQ(opt_const->size(), 3); - - constexpr absl::optional<ConstexprType> opt1(1); - static_assert((*opt1).x == ConstexprType::kCtorInt, ""); -} - -// gcc has a bug pre 4.9.1 where it doesn't do correct overload resolution -// when overloads are const-qualified and *this is an raluve. -// Skip that test to make the build green again when using the old compiler. -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59296 is fixed in 4.9.1. -#if defined(__GNUC__) && !defined(__clang__) -#define GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) -#if GCC_VERSION < 40901 -#define ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG -#endif -#endif - -// MSVC has a bug with "cv-qualifiers in class construction", fixed in 2017. See -// https://docs.microsoft.com/en-us/cpp/cpp-conformance-improvements-2017#bug-fixes -// The compiler some incorrectly ingores the cv-qualifier when generating a -// class object via a constructor call. For example: -// -// class optional { -// constexpr T&& value() &&; -// constexpr const T&& value() const &&; -// } -// -// using COI = const absl::optional<int>; -// static_assert(2 == COI(2).value(), ""); // const && -// -// This should invoke the "const &&" overload but since it ignores the const -// qualifier it finds the "&&" overload the best candidate. -#if defined(_MSC_VER) && _MSC_VER < 1910 -#define ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG -#endif - -TEST(optionalTest, Value) { - using O = absl::optional<std::string>; - using CO = const absl::optional<std::string>; - using OC = absl::optional<const std::string>; - O lvalue(absl::in_place, "lvalue"); - CO clvalue(absl::in_place, "clvalue"); - OC lvalue_c(absl::in_place, "lvalue_c"); - EXPECT_EQ("lvalue", lvalue.value()); - EXPECT_EQ("clvalue", clvalue.value()); - EXPECT_EQ("lvalue_c", lvalue_c.value()); - EXPECT_EQ("xvalue", O(absl::in_place, "xvalue").value()); - EXPECT_EQ("xvalue_c", OC(absl::in_place, "xvalue_c").value()); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG - EXPECT_EQ("cxvalue", CO(absl::in_place, "cxvalue").value()); -#endif - EXPECT_EQ("&", TypeQuals(lvalue.value())); - EXPECT_EQ("c&", TypeQuals(clvalue.value())); - EXPECT_EQ("c&", TypeQuals(lvalue_c.value())); - EXPECT_EQ("&&", TypeQuals(O(absl::in_place, "xvalue").value())); -#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \ - !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - EXPECT_EQ("c&&", TypeQuals(CO(absl::in_place, "cxvalue").value())); -#endif - EXPECT_EQ("c&&", TypeQuals(OC(absl::in_place, "xvalue_c").value())); - - // test on volatile type - using OV = absl::optional<volatile int>; - OV lvalue_v(absl::in_place, 42); - EXPECT_EQ(42, lvalue_v.value()); - EXPECT_EQ(42, OV(42).value()); - EXPECT_TRUE((std::is_same<volatile int&, decltype(lvalue_v.value())>::value)); - EXPECT_TRUE((std::is_same<volatile int&&, decltype(OV(42).value())>::value)); - - // test exception throw on value() - absl::optional<int> empty; -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW((void)empty.value(), absl::bad_optional_access); -#else - EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access"); -#endif - - // test constexpr value() - constexpr absl::optional<int> o1(1); - static_assert(1 == o1.value(), ""); // const & -#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - using COI = const absl::optional<int>; - static_assert(2 == COI(2).value(), ""); // const && -#endif -} - -TEST(optionalTest, DerefOperator) { - using O = absl::optional<std::string>; - using CO = const absl::optional<std::string>; - using OC = absl::optional<const std::string>; - O lvalue(absl::in_place, "lvalue"); - CO clvalue(absl::in_place, "clvalue"); - OC lvalue_c(absl::in_place, "lvalue_c"); - EXPECT_EQ("lvalue", *lvalue); - EXPECT_EQ("clvalue", *clvalue); - EXPECT_EQ("lvalue_c", *lvalue_c); - EXPECT_EQ("xvalue", *O(absl::in_place, "xvalue")); - EXPECT_EQ("xvalue_c", *OC(absl::in_place, "xvalue_c")); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG - EXPECT_EQ("cxvalue", *CO(absl::in_place, "cxvalue")); -#endif - EXPECT_EQ("&", TypeQuals(*lvalue)); - EXPECT_EQ("c&", TypeQuals(*clvalue)); - EXPECT_EQ("&&", TypeQuals(*O(absl::in_place, "xvalue"))); -#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \ - !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - EXPECT_EQ("c&&", TypeQuals(*CO(absl::in_place, "cxvalue"))); -#endif - EXPECT_EQ("c&&", TypeQuals(*OC(absl::in_place, "xvalue_c"))); - - // test on volatile type - using OV = absl::optional<volatile int>; - OV lvalue_v(absl::in_place, 42); - EXPECT_EQ(42, *lvalue_v); - EXPECT_EQ(42, *OV(42)); - EXPECT_TRUE((std::is_same<volatile int&, decltype(*lvalue_v)>::value)); - EXPECT_TRUE((std::is_same<volatile int&&, decltype(*OV(42))>::value)); - - constexpr absl::optional<int> opt1(1); - static_assert(*opt1 == 1, ""); -#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - using COI = const absl::optional<int>; - static_assert(*COI(2) == 2, ""); -#endif -} - -TEST(optionalTest, ValueOr) { - absl::optional<double> opt_empty, opt_set = 1.2; - EXPECT_EQ(42.0, opt_empty.value_or(42)); - EXPECT_EQ(1.2, opt_set.value_or(42)); - EXPECT_EQ(42.0, absl::optional<double>().value_or(42)); - EXPECT_EQ(1.2, absl::optional<double>(1.2).value_or(42)); - - constexpr absl::optional<double> copt_empty, copt_set = {1.2}; - static_assert(42.0 == copt_empty.value_or(42), ""); - static_assert(1.2 == copt_set.value_or(42), ""); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG - using COD = const absl::optional<double>; - static_assert(42.0 == COD().value_or(42), ""); - static_assert(1.2 == COD(1.2).value_or(42), ""); -#endif -} - -// make_optional cannot be constexpr until C++17 -TEST(optionalTest, make_optional) { - auto opt_int = absl::make_optional(42); - EXPECT_TRUE((std::is_same<decltype(opt_int), absl::optional<int>>::value)); - EXPECT_EQ(42, opt_int); - - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<Listenable> opt0 = absl::make_optional<Listenable>(); - EXPECT_EQ(1, listener.construct0); - absl::optional<Listenable> opt1 = absl::make_optional<Listenable>(1); - EXPECT_EQ(1, listener.construct1); - absl::optional<Listenable> opt2 = absl::make_optional<Listenable>(1, 2); - EXPECT_EQ(1, listener.construct2); - absl::optional<Listenable> opt3 = absl::make_optional<Listenable>({1}); - absl::optional<Listenable> opt4 = absl::make_optional<Listenable>({1, 2}); - EXPECT_EQ(2, listener.listinit); - - // Constexpr tests on trivially copyable types - // optional<T> has trivial copy/move ctors when T is trivially copyable. - // For nontrivial types with constexpr constructors, we need copy elision in - // C++17 for make_optional to be constexpr. - { - constexpr absl::optional<int> c_opt = absl::make_optional(42); - static_assert(c_opt.value() == 42, ""); - } - { - struct TrivialCopyable { - constexpr TrivialCopyable() : x(0) {} - constexpr explicit TrivialCopyable(int i) : x(i) {} - int x; - }; - - constexpr TrivialCopyable v; - constexpr absl::optional<TrivialCopyable> c_opt0 = absl::make_optional(v); - static_assert((*c_opt0).x == 0, ""); - constexpr absl::optional<TrivialCopyable> c_opt1 = - absl::make_optional<TrivialCopyable>(); - static_assert((*c_opt1).x == 0, ""); - constexpr absl::optional<TrivialCopyable> c_opt2 = - absl::make_optional<TrivialCopyable>(42); - static_assert((*c_opt2).x == 42, ""); - } -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_LESS(T x, U y) { - EXPECT_FALSE(x == y); - EXPECT_TRUE(x != y); - EXPECT_TRUE(x < y); - EXPECT_FALSE(x > y); - EXPECT_TRUE(x <= y); - EXPECT_FALSE(x >= y); -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_SAME(T x, U y) { - EXPECT_TRUE(x == y); - EXPECT_FALSE(x != y); - EXPECT_FALSE(x < y); - EXPECT_FALSE(x > y); - EXPECT_TRUE(x <= y); - EXPECT_TRUE(x >= y); -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_GREATER(T x, U y) { - EXPECT_FALSE(x == y); - EXPECT_TRUE(x != y); - EXPECT_FALSE(x < y); - EXPECT_TRUE(x > y); - EXPECT_FALSE(x <= y); - EXPECT_TRUE(x >= y); -} - - -template <typename T, typename U, typename V> -void TestComparisons() { - absl::optional<T> ae, a2{2}, a4{4}; - absl::optional<U> be, b2{2}, b4{4}; - V v3 = 3; - - // LHS: absl::nullopt, ae, a2, v3, a4 - // RHS: absl::nullopt, be, b2, v3, b4 - - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,absl::nullopt); - optionalTest_Comparisons_EXPECT_SAME(absl::nullopt, be); - optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b2); - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,v3); - optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b4); - - optionalTest_Comparisons_EXPECT_SAME(ae, absl::nullopt); - optionalTest_Comparisons_EXPECT_SAME(ae, be); - optionalTest_Comparisons_EXPECT_LESS(ae, b2); - optionalTest_Comparisons_EXPECT_LESS(ae, v3); - optionalTest_Comparisons_EXPECT_LESS(ae, b4); - - optionalTest_Comparisons_EXPECT_GREATER(a2, absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(a2, be); - optionalTest_Comparisons_EXPECT_SAME(a2, b2); - optionalTest_Comparisons_EXPECT_LESS(a2, v3); - optionalTest_Comparisons_EXPECT_LESS(a2, b4); - - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(v3,absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(v3, be); - optionalTest_Comparisons_EXPECT_GREATER(v3, b2); - optionalTest_Comparisons_EXPECT_SAME(v3, v3); - optionalTest_Comparisons_EXPECT_LESS(v3, b4); - - optionalTest_Comparisons_EXPECT_GREATER(a4, absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(a4, be); - optionalTest_Comparisons_EXPECT_GREATER(a4, b2); - optionalTest_Comparisons_EXPECT_GREATER(a4, v3); - optionalTest_Comparisons_EXPECT_SAME(a4, b4); -} - -struct Int1 { - Int1() = default; - Int1(int i) : i(i) {} // NOLINT(runtime/explicit) - int i; -}; - -struct Int2 { - Int2() = default; - Int2(int i) : i(i) {} // NOLINT(runtime/explicit) - int i; -}; - -// comparison between Int1 and Int2 -constexpr bool operator==(const Int1& lhs, const Int2& rhs) { - return lhs.i == rhs.i; -} -constexpr bool operator!=(const Int1& lhs, const Int2& rhs) { - return !(lhs == rhs); -} -constexpr bool operator<(const Int1& lhs, const Int2& rhs) { - return lhs.i < rhs.i; -} -constexpr bool operator<=(const Int1& lhs, const Int2& rhs) { - return lhs < rhs || lhs == rhs; -} -constexpr bool operator>(const Int1& lhs, const Int2& rhs) { - return !(lhs <= rhs); -} -constexpr bool operator>=(const Int1& lhs, const Int2& rhs) { - return !(lhs < rhs); -} - -TEST(optionalTest, Comparisons) { - TestComparisons<int, int, int>(); - TestComparisons<const int, int, int>(); - TestComparisons<Int1, int, int>(); - TestComparisons<int, Int2, int>(); - TestComparisons<Int1, Int2, int>(); - - // compare absl::optional<std::string> with const char* - absl::optional<std::string> opt_str = "abc"; - const char* cstr = "abc"; - EXPECT_TRUE(opt_str == cstr); - // compare absl::optional<std::string> with absl::optional<const char*> - absl::optional<const char*> opt_cstr = cstr; - EXPECT_TRUE(opt_str == opt_cstr); - // compare absl::optional<std::string> with absl::optional<absl::string_view> - absl::optional<absl::string_view> e1; - absl::optional<std::string> e2; - EXPECT_TRUE(e1 == e2); -} - - -TEST(optionalTest, SwapRegression) { - StructorListener listener; - Listenable::listener = &listener; - - { - absl::optional<Listenable> a; - absl::optional<Listenable> b(absl::in_place); - a.swap(b); - } - - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(2, listener.destruct); - - { - absl::optional<Listenable> a(absl::in_place); - absl::optional<Listenable> b; - a.swap(b); - } - - EXPECT_EQ(2, listener.construct0); - EXPECT_EQ(2, listener.move); - EXPECT_EQ(4, listener.destruct); -} - -TEST(optionalTest, BigStringLeakCheck) { - constexpr size_t n = 1 << 16; - - using OS = absl::optional<std::string>; - - OS a; - OS b = absl::nullopt; - OS c = std::string(n, 'c'); - std::string sd(n, 'd'); - OS d = sd; - OS e(absl::in_place, n, 'e'); - OS f; - f.emplace(n, 'f'); - - OS ca(a); - OS cb(b); - OS cc(c); - OS cd(d); - OS ce(e); - - OS oa; - OS ob = absl::nullopt; - OS oc = std::string(n, 'c'); - std::string sod(n, 'd'); - OS od = sod; - OS oe(absl::in_place, n, 'e'); - OS of; - of.emplace(n, 'f'); - - OS ma(std::move(oa)); - OS mb(std::move(ob)); - OS mc(std::move(oc)); - OS md(std::move(od)); - OS me(std::move(oe)); - OS mf(std::move(of)); - - OS aa1; - OS ab1 = absl::nullopt; - OS ac1 = std::string(n, 'c'); - std::string sad1(n, 'd'); - OS ad1 = sad1; - OS ae1(absl::in_place, n, 'e'); - OS af1; - af1.emplace(n, 'f'); - - OS aa2; - OS ab2 = absl::nullopt; - OS ac2 = std::string(n, 'c'); - std::string sad2(n, 'd'); - OS ad2 = sad2; - OS ae2(absl::in_place, n, 'e'); - OS af2; - af2.emplace(n, 'f'); - - aa1 = af2; - ab1 = ae2; - ac1 = ad2; - ad1 = ac2; - ae1 = ab2; - af1 = aa2; - - OS aa3; - OS ab3 = absl::nullopt; - OS ac3 = std::string(n, 'c'); - std::string sad3(n, 'd'); - OS ad3 = sad3; - OS ae3(absl::in_place, n, 'e'); - OS af3; - af3.emplace(n, 'f'); - - aa3 = absl::nullopt; - ab3 = absl::nullopt; - ac3 = absl::nullopt; - ad3 = absl::nullopt; - ae3 = absl::nullopt; - af3 = absl::nullopt; - - OS aa4; - OS ab4 = absl::nullopt; - OS ac4 = std::string(n, 'c'); - std::string sad4(n, 'd'); - OS ad4 = sad4; - OS ae4(absl::in_place, n, 'e'); - OS af4; - af4.emplace(n, 'f'); - - aa4 = OS(absl::in_place, n, 'a'); - ab4 = OS(absl::in_place, n, 'b'); - ac4 = OS(absl::in_place, n, 'c'); - ad4 = OS(absl::in_place, n, 'd'); - ae4 = OS(absl::in_place, n, 'e'); - af4 = OS(absl::in_place, n, 'f'); - - OS aa5; - OS ab5 = absl::nullopt; - OS ac5 = std::string(n, 'c'); - std::string sad5(n, 'd'); - OS ad5 = sad5; - OS ae5(absl::in_place, n, 'e'); - OS af5; - af5.emplace(n, 'f'); - - std::string saa5(n, 'a'); - std::string sab5(n, 'a'); - std::string sac5(n, 'a'); - std::string sad52(n, 'a'); - std::string sae5(n, 'a'); - std::string saf5(n, 'a'); - - aa5 = saa5; - ab5 = sab5; - ac5 = sac5; - ad5 = sad52; - ae5 = sae5; - af5 = saf5; - - OS aa6; - OS ab6 = absl::nullopt; - OS ac6 = std::string(n, 'c'); - std::string sad6(n, 'd'); - OS ad6 = sad6; - OS ae6(absl::in_place, n, 'e'); - OS af6; - af6.emplace(n, 'f'); - - aa6 = std::string(n, 'a'); - ab6 = std::string(n, 'b'); - ac6 = std::string(n, 'c'); - ad6 = std::string(n, 'd'); - ae6 = std::string(n, 'e'); - af6 = std::string(n, 'f'); - - OS aa7; - OS ab7 = absl::nullopt; - OS ac7 = std::string(n, 'c'); - std::string sad7(n, 'd'); - OS ad7 = sad7; - OS ae7(absl::in_place, n, 'e'); - OS af7; - af7.emplace(n, 'f'); - - aa7.emplace(n, 'A'); - ab7.emplace(n, 'B'); - ac7.emplace(n, 'C'); - ad7.emplace(n, 'D'); - ae7.emplace(n, 'E'); - af7.emplace(n, 'F'); -} - -TEST(optionalTest, MoveAssignRegression) { - StructorListener listener; - Listenable::listener = &listener; - - { - absl::optional<Listenable> a; - Listenable b; - a = std::move(b); - } - - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(2, listener.destruct); -} - -TEST(optionalTest, ValueType) { - EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value)); - EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type, - std::string>::value)); - EXPECT_FALSE( - (std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value)); -} - -template <typename T> -struct is_hash_enabled_for { - template <typename U, typename = decltype(std::hash<U>()(std::declval<U>()))> - static std::true_type test(int); - - template <typename U> - static std::false_type test(...); - - static constexpr bool value = decltype(test<T>(0))::value; -}; - -TEST(optionalTest, Hash) { - std::hash<absl::optional<int>> hash; - std::set<size_t> hashcodes; - hashcodes.insert(hash(absl::nullopt)); - for (int i = 0; i < 100; ++i) { - hashcodes.insert(hash(i)); - } - EXPECT_GT(hashcodes.size(), 90); - - static_assert(is_hash_enabled_for<absl::optional<int>>::value, ""); - static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, ""); - static_assert( - absl::type_traits_internal::IsHashable<absl::optional<int>>::value, ""); - static_assert( - absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value, - ""); - absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>(); - absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>(); - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, ""); - static_assert(!absl::type_traits_internal::IsHashable< - absl::optional<NonHashable>>::value, - ""); -#endif - - // libstdc++ std::optional is missing remove_const_t, i.e. it's using - // std::hash<T> rather than std::hash<std::remove_const_t<T>>. - // Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82262 -#ifndef __GLIBCXX__ - static_assert(is_hash_enabled_for<absl::optional<const int>>::value, ""); - static_assert(is_hash_enabled_for<absl::optional<const Hashable>>::value, ""); - std::hash<absl::optional<const int>> c_hash; - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(hash(i), c_hash(i)); - } -#endif -} - -struct MoveMeNoThrow { - MoveMeNoThrow() : x(0) {} - [[noreturn]] MoveMeNoThrow(const MoveMeNoThrow& other) : x(other.x) { - ABSL_RAW_LOG(FATAL, "Should not be called."); - abort(); - } - MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {} - int x; -}; - -struct MoveMeThrow { - MoveMeThrow() : x(0) {} - MoveMeThrow(const MoveMeThrow& other) : x(other.x) {} - MoveMeThrow(MoveMeThrow&& other) : x(other.x) {} - int x; -}; - -TEST(optionalTest, NoExcept) { - static_assert( - std::is_nothrow_move_constructible<absl::optional<MoveMeNoThrow>>::value, - ""); -#ifndef ABSL_USES_STD_OPTIONAL - static_assert(absl::default_allocator_is_nothrow::value == - std::is_nothrow_move_constructible< - absl::optional<MoveMeThrow>>::value, - ""); -#endif - std::vector<absl::optional<MoveMeNoThrow>> v; - for (int i = 0; i < 10; ++i) v.emplace_back(); -} - -struct AnyLike { - AnyLike(AnyLike&&) = default; - AnyLike(const AnyLike&) = default; - - template <typename ValueType, - typename T = typename std::decay<ValueType>::type, - typename std::enable_if< - !absl::disjunction< - std::is_same<AnyLike, T>, - absl::negation<std::is_copy_constructible<T>>>::value, - int>::type = 0> - AnyLike(ValueType&&) {} // NOLINT(runtime/explicit) - - AnyLike& operator=(AnyLike&&) = default; - AnyLike& operator=(const AnyLike&) = default; - - template <typename ValueType, - typename T = typename std::decay<ValueType>::type> - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same<AnyLike, T>>, - std::is_copy_constructible<T>>::value, - AnyLike&>::type - operator=(ValueType&& /* rhs */) { - return *this; - } -}; - -TEST(optionalTest, ConstructionConstraints) { - EXPECT_TRUE((std::is_constructible<AnyLike, absl::optional<AnyLike>>::value)); - - EXPECT_TRUE( - (std::is_constructible<AnyLike, const absl::optional<AnyLike>&>::value)); - - EXPECT_TRUE((std::is_constructible<absl::optional<AnyLike>, AnyLike>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<AnyLike>, const AnyLike&>::value)); - - EXPECT_TRUE((std::is_convertible<absl::optional<AnyLike>, AnyLike>::value)); - - EXPECT_TRUE( - (std::is_convertible<const absl::optional<AnyLike>&, AnyLike>::value)); - - EXPECT_TRUE((std::is_convertible<AnyLike, absl::optional<AnyLike>>::value)); - EXPECT_TRUE( - (std::is_convertible<const AnyLike&, absl::optional<AnyLike>>::value)); - - EXPECT_TRUE(std::is_move_constructible<absl::optional<AnyLike>>::value); - EXPECT_TRUE(std::is_copy_constructible<absl::optional<AnyLike>>::value); -} - -TEST(optionalTest, AssignmentConstraints) { - EXPECT_TRUE((std::is_assignable<AnyLike&, absl::optional<AnyLike>>::value)); - EXPECT_TRUE( - (std::is_assignable<AnyLike&, const absl::optional<AnyLike>&>::value)); - EXPECT_TRUE((std::is_assignable<absl::optional<AnyLike>&, AnyLike>::value)); - EXPECT_TRUE( - (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value)); - EXPECT_TRUE(std::is_move_assignable<absl::optional<AnyLike>>::value); - EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value); -} - -#if !defined(__EMSCRIPTEN__) -struct NestedClassBug { - struct Inner { - bool dummy = false; - }; - absl::optional<Inner> value; -}; - -TEST(optionalTest, InPlaceTSFINAEBug) { - NestedClassBug b; - ((void)b); - using Inner = NestedClassBug::Inner; - - EXPECT_TRUE((std::is_default_constructible<Inner>::value)); - EXPECT_TRUE((std::is_constructible<Inner>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value)); - - absl::optional<Inner> o(absl::in_place); - EXPECT_TRUE(o.has_value()); - o.emplace(); - EXPECT_TRUE(o.has_value()); -} -#endif // !defined(__EMSCRIPTEN__) - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_OPTIONAL) diff --git a/third_party/abseil_cpp/absl/types/span.h b/third_party/abseil_cpp/absl/types/span.h deleted file mode 100644 index 95fe79262d67..000000000000 --- a/third_party/abseil_cpp/absl/types/span.h +++ /dev/null @@ -1,726 +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. -// -// ----------------------------------------------------------------------------- -// 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. -// -// 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) -// * `absl::Span` has the factory functions `MakeSpan()` and -// `MakeConstSpan()` -// * 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` typedef -// * A read-only `absl::Span<const T>` can be implicitly constructed from an -// initializer list. -// * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or -// `as_mutable_bytes()` methods -// * `absl::Span` has no static extent template parameter, nor constructors -// which exist only because of the static extent parameter. -// * `absl::Span` has an explicit mutable-reference constructor -// -// For more information, see the class comments below. -#ifndef ABSL_TYPES_SPAN_H_ -#define ABSL_TYPES_SPAN_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <initializer_list> -#include <iterator> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/throw_delegate.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" // TODO(strel): remove this include -#include "absl/meta/type_traits.h" -#include "absl/types/internal/span.h" - -namespace absl { -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 -// contiguous sequences without needing to manage pointers and array lengths -// manually. - -// A span is conceptually a pointer (ptr) and a length (size) into an already -// existing array of contiguous memory; the array it represents references the -// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span` -// instead of raw pointers avoids many issues related to index out of bounds -// errors. -// -// Spans may also be constructed from containers holding contiguous sequences. -// Such containers must supply `data()` and `size() const` methods (e.g -// `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to -// `absl::Span` from such containers will create spans of type `const T`; -// spans which can mutate their values (of type `T`) must use explicit -// 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 -// pointed to outlives the `Span` itself. -// -// You can construct a `Span<T>` in several ways: -// -// * Explicitly from a reference to a container type -// * Explicitly from a pointer and size -// * Implicitly from a container type (but only for spans of type `const T`) -// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions. -// -// Examples: -// -// // Construct a Span explicitly from a container: -// std::vector<int> v = {1, 2, 3, 4, 5}; -// auto span = absl::Span<const int>(v); -// -// // Construct a Span explicitly from a C-style array: -// int a[5] = {1, 2, 3, 4, 5}; -// auto span = absl::Span<const int>(a); -// -// // Construct a Span implicitly from a container -// void MyRoutine(absl::Span<const int> a) { -// ... -// } -// std::vector v = {1,2,3,4,5}; -// MyRoutine(v) // convert to Span<const T> -// -// 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 -// (such as resizing) or invalidate iterators into the container. -// -// One common use for a `Span` is when passing arguments to a routine that can -// accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`, -// a C-style array, etc.). Instead of creating overloads for each case, you -// can simply specify a `Span` as the argument to such a routine. -// -// Example: -// -// void MyRoutine(absl::Span<const int> a) { -// ... -// } -// -// std::vector v = {1,2,3,4,5}; -// MyRoutine(v); -// -// absl::InlinedVector<int, 4> my_inline_vector; -// MyRoutine(my_inline_vector); -// -// // Explicit constructor from pointer,size -// int* my_array = new int[10]; -// MyRoutine(absl::Span<const int>(my_array, 10)); -template <typename T> -class Span { - private: - // Used to determine whether a Span can be constructed from a container of - // type C. - template <typename C> - using EnableIfConvertibleFrom = - typename std::enable_if<span_internal::HasData<T, C>::value && - span_internal::HasSize<C>::value>::type; - - // Used to SFINAE-enable a function when the slice elements are const. - template <typename U> - using EnableIfConstView = - typename std::enable_if<std::is_const<T>::value, U>::type; - - // Used to SFINAE-enable a function when the slice elements are mutable. - template <typename U> - using EnableIfMutableView = - typename std::enable_if<!std::is_const<T>::value, U>::type; - - public: - using value_type = absl::remove_cv_t<T>; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - 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 size_type = size_t; - using difference_type = ptrdiff_t; - - static const size_type npos = ~(size_type(0)); - - constexpr Span() noexcept : Span(nullptr, 0) {} - constexpr Span(pointer array, size_type length) noexcept - : ptr_(array), len_(length) {} - - // Implicit conversion constructors - template <size_t N> - constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit) - : Span(a, N) {} - - // Explicit reference constructor for a mutable `Span<T>` type. Can be - // replaced with MakeSpan() to infer the type parameter. - template <typename V, typename = EnableIfConvertibleFrom<V>, - typename = EnableIfMutableView<V>> - explicit Span(V& v) noexcept // NOLINT(runtime/references) - : Span(span_internal::GetData(v), v.size()) {} - - // Implicit reference constructor for a read-only `Span<const T>` type - template <typename V, typename = EnableIfConvertibleFrom<V>, - typename = EnableIfConstView<V>> - constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit) - : Span(span_internal::GetData(v), v.size()) {} - - // Implicit constructor from an initializer list, making it possible to pass a - // brace-enclosed initializer list to a function expecting a `Span`. Such - // spans constructed from an initializer list must be of type `Span<const T>`. - // - // void Process(absl::Span<const int> x); - // Process({1, 2, 3}); - // - // Note that as always the array referenced by the span must outlive the span. - // Since an initializer list constructor acts as if it is fed a temporary - // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this - // constructor only when the `std::initializer_list` itself outlives the span. - // In order to meet this requirement it's sufficient to ensure that neither - // the span nor a copy of it is used outside of the expression in which it's - // created: - // - // // Assume that this function uses the array directly, not retaining any - // // copy of the span or pointer to any of its elements. - // void Process(absl::Span<const int> ints); - // - // // Okay: the std::initializer_list<int> will reference a temporary array - // // that isn't destroyed until after the call to Process returns. - // Process({ 17, 19 }); - // - // // Not okay: the storage used by the std::initializer_list<int> is not - // // allowed to be referenced after the first line. - // absl::Span<const int> ints = { 17, 19 }; - // Process(ints); - // - // // Not okay for the same reason as above: even when the elements of the - // // initializer list expression are not temporaries the underlying array - // // is, so the initializer list must still outlive the span. - // const int foo = 17; - // absl::Span<const int> ints = { foo }; - // Process(ints); - // - template <typename LazyT = T, - typename = EnableIfConstView<LazyT>> - Span( - std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit) - : Span(v.begin(), v.size()) {} - - // Accessors - - // Span::data() - // - // Returns a pointer to the span's underlying array of data (which is held - // outside the span). - constexpr pointer data() const noexcept { return ptr_; } - - // Span::size() - // - // Returns the size of this span. - constexpr size_type size() const noexcept { return len_; } - - // Span::length() - // - // Returns the length (size) of this span. - constexpr size_type length() const noexcept { return size(); } - - // Span::empty() - // - // Returns a boolean indicating whether or not this span is considered empty. - constexpr bool empty() const noexcept { return size() == 0; } - - // Span::operator[] - // - // 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); - } - - // Span::at() - // - // Returns a reference to the i'th element of this span. - constexpr reference at(size_type i) const { - return ABSL_PREDICT_TRUE(i < size()) // - ? *(data() + i) - : (base_internal::ThrowStdOutOfRange( - "Span::at failed bounds check"), - *(data() + i)); - } - - // Span::front() - // - // Returns a reference to the first element of this span. The span must not - // be empty. - constexpr reference front() const noexcept { - return ABSL_HARDENING_ASSERT(size() > 0), *data(); - } - - // Span::back() - // - // Returns a reference to the last element of this span. The span must not - // be empty. - constexpr reference back() const noexcept { - return ABSL_HARDENING_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. - 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. - 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. - 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. - 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. - 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. - 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. - 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. - constexpr const_reverse_iterator crend() const noexcept { return rend(); } - - // Span mutations - - // Span::remove_prefix() - // - // Removes the first `n` elements from the span. - void remove_prefix(size_type n) noexcept { - ABSL_HARDENING_ASSERT(size() >= n); - ptr_ += n; - len_ -= n; - } - - // Span::remove_suffix() - // - // Removes the last `n` elements from the span. - void remove_suffix(size_type n) noexcept { - ABSL_HARDENING_ASSERT(size() >= n); - len_ -= n; - } - - // Span::subspan() - // - // Returns a `Span` starting at element `pos` and of length `len`. Both `pos` - // and `len` are of type `size_type` and thus non-negative. Parameter `pos` - // must be <= size(). Any `len` value that points past the end of the span - // will be trimmed to at most size() - `pos`. A default `len` value of `npos` - // ensures the returned subspan continues until the end of the span. - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).subspan(1, 2); // {11, 12} - // absl::MakeSpan(vec).subspan(2, 8); // {12, 13} - // absl::MakeSpan(vec).subspan(1); // {11, 12, 13} - // absl::MakeSpan(vec).subspan(4); // {} - // absl::MakeSpan(vec).subspan(5); // throws std::out_of_range - constexpr Span subspan(size_type pos = 0, size_type len = npos) const { - return (pos <= size()) - ? Span(data() + pos, span_internal::Min(size() - pos, len)) - : (base_internal::ThrowStdOutOfRange("pos > size()"), Span()); - } - - // Span::first() - // - // Returns a `Span` containing first `len` elements. Parameter `len` is of - // type `size_type` and thus non-negative. `len` value must be <= size(). - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).first(1); // {10} - // absl::MakeSpan(vec).first(3); // {10, 11, 12} - // absl::MakeSpan(vec).first(5); // throws std::out_of_range - constexpr Span first(size_type len) const { - return (len <= size()) - ? Span(data(), len) - : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); - } - - // Span::last() - // - // Returns a `Span` containing last `len` elements. Parameter `len` is of - // type `size_type` and thus non-negative. `len` value must be <= size(). - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).last(1); // {13} - // absl::MakeSpan(vec).last(3); // {11, 12, 13} - // absl::MakeSpan(vec).last(5); // throws std::out_of_range - constexpr Span last(size_type len) const { - return (len <= size()) - ? Span(size() - len + data(), len) - : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); - } - - // Support for absl::Hash. - template <typename H> - friend H AbslHashValue(H h, Span v) { - return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), - v.size()); - } - - private: - pointer ptr_; - size_type len_; -}; - -template <typename T> -const typename Span<T>::size_type Span<T>::npos; - -// Span relationals - -// Equality is compared element-by-element, while ordering is lexicographical. -// We provide three overloads for each operator to cover any combination on the -// left or right hand side of mutable Span<T>, read-only Span<const T>, and -// convertible-to-read-only Span<T>. -// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering -// template functions, 5 overloads per operator is needed as a workaround. We -// should update them to 3 overloads per operator using non-deduced context like -// string_view, i.e. -// - (Span<T>, Span<T>) -// - (Span<T>, non_deduced<Span<const T>>) -// - (non_deduced<Span<const T>>, Span<T>) - -// operator== -template <typename T> -bool operator==(Span<T> a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template <typename T> -bool operator==(Span<const T> a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template <typename T> -bool operator==(Span<T> a, Span<const T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(const U& a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(Span<T> a, const U& b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} - -// operator!= -template <typename T> -bool operator!=(Span<T> a, Span<T> b) { - return !(a == b); -} -template <typename T> -bool operator!=(Span<const T> a, Span<T> b) { - return !(a == b); -} -template <typename T> -bool operator!=(Span<T> a, Span<const T> b) { - return !(a == b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(const U& a, Span<T> b) { - return !(a == b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(Span<T> a, const U& b) { - return !(a == b); -} - -// operator< -template <typename T> -bool operator<(Span<T> a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template <typename T> -bool operator<(Span<const T> a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template <typename T> -bool operator<(Span<T> a, Span<const T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(const U& a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(Span<T> a, const U& b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} - -// operator> -template <typename T> -bool operator>(Span<T> a, Span<T> b) { - return b < a; -} -template <typename T> -bool operator>(Span<const T> a, Span<T> b) { - return b < a; -} -template <typename T> -bool operator>(Span<T> a, Span<const T> b) { - return b < a; -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(const U& a, Span<T> b) { - return b < a; -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(Span<T> a, const U& b) { - return b < a; -} - -// operator<= -template <typename T> -bool operator<=(Span<T> a, Span<T> b) { - return !(b < a); -} -template <typename T> -bool operator<=(Span<const T> a, Span<T> b) { - return !(b < a); -} -template <typename T> -bool operator<=(Span<T> a, Span<const T> b) { - return !(b < a); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(const U& a, Span<T> b) { - return !(b < a); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(Span<T> a, const U& b) { - return !(b < a); -} - -// operator>= -template <typename T> -bool operator>=(Span<T> a, Span<T> b) { - return !(a < b); -} -template <typename T> -bool operator>=(Span<const T> a, Span<T> b) { - return !(a < b); -} -template <typename T> -bool operator>=(Span<T> a, Span<const T> b) { - return !(a < b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(const U& a, Span<T> b) { - return !(a < b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(Span<T> a, const U& b) { - return !(a < b); -} - -// MakeSpan() -// -// Constructs a mutable `Span<T>`, deducing `T` automatically from either a -// container or pointer+size. -// -// Because a read-only `Span<const T>` is implicitly constructed from container -// types regardless of whether the container itself is a const container, -// constructing mutable spans of type `Span<T>` from containers requires -// explicit constructors. The container-accepting version of `MakeSpan()` -// deduces the type of `T` by the constness of the pointer received from the -// container's `data()` member. Similarly, the pointer-accepting version returns -// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise. -// -// Examples: -// -// void MyRoutine(absl::Span<MyComplicatedType> a) { -// ... -// }; -// // my_vector is a container of non-const types -// std::vector<MyComplicatedType> my_vector; -// -// // Constructing a Span implicitly attempts to create a Span of type -// // `Span<const T>` -// MyRoutine(my_vector); // error, type mismatch -// -// // Explicitly constructing the Span is verbose -// MyRoutine(absl::Span<MyComplicatedType>(my_vector)); -// -// // Use MakeSpan() to make an absl::Span<T> -// MyRoutine(absl::MakeSpan(my_vector)); -// -// // Construct a span from an array ptr+size -// absl::Span<T> my_span() { -// return absl::MakeSpan(&array[0], num_elements_); -// } -// -template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept { - return Span<T>(ptr, size); -} - -template <int&... ExplicitArgumentBarrier, typename T> -Span<T> MakeSpan(T* begin, T* end) noexcept { - return ABSL_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin); -} - -template <int&... ExplicitArgumentBarrier, typename C> -constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references) - -> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) { - return MakeSpan(span_internal::GetData(c), c.size()); -} - -template <int&... ExplicitArgumentBarrier, typename T, size_t N> -constexpr Span<T> MakeSpan(T (&array)[N]) noexcept { - return Span<T>(array, N); -} - -// MakeConstSpan() -// -// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically, -// but always returning a `Span<const T>`. -// -// Examples: -// -// void ProcessInts(absl::Span<const int> some_ints); -// -// // Call with a pointer and size. -// int array[3] = { 0, 0, 0 }; -// ProcessInts(absl::MakeConstSpan(&array[0], 3)); -// -// // Call with a [begin, end) pair. -// ProcessInts(absl::MakeConstSpan(&array[0], &array[3])); -// -// // Call directly with an array. -// ProcessInts(absl::MakeConstSpan(array)); -// -// // Call with a contiguous container. -// std::vector<int> some_ints = ...; -// ProcessInts(absl::MakeConstSpan(some_ints)); -// ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 })); -// -template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept { - return Span<const T>(ptr, size); -} - -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); -} - -template <int&... ExplicitArgumentBarrier, typename C> -constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) { - return MakeSpan(c); -} - -template <int&... ExplicitArgumentBarrier, typename T, size_t N> -constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept { - return Span<const T>(array, N); -} -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_TYPES_SPAN_H_ diff --git a/third_party/abseil_cpp/absl/types/span_test.cc b/third_party/abseil_cpp/absl/types/span_test.cc deleted file mode 100644 index 2584339bd309..000000000000 --- a/third_party/abseil_cpp/absl/types/span_test.cc +++ /dev/null @@ -1,846 +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/types/span.h" - -#include <array> -#include <initializer_list> -#include <numeric> -#include <stdexcept> -#include <string> -#include <type_traits> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#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" -#include "absl/strings/str_cat.h" - -namespace { - -MATCHER_P(DataIs, data, - absl::StrCat("data() ", negation ? "isn't " : "is ", - testing::PrintToString(data))) { - return arg.data() == data; -} - -template <typename T> -auto SpanIs(T data, size_t size) - -> decltype(testing::AllOf(DataIs(data), testing::SizeIs(size))) { - return testing::AllOf(DataIs(data), testing::SizeIs(size)); -} - -template <typename Container> -auto SpanIs(const Container& c) -> decltype(SpanIs(c.data(), c.size())) { - return SpanIs(c.data(), c.size()); -} - -std::vector<int> MakeRamp(int len, int offset = 0) { - std::vector<int> v(len); - std::iota(v.begin(), v.end(), offset); - return v; -} - -TEST(IntSpan, EmptyCtors) { - absl::Span<int> s; - EXPECT_THAT(s, SpanIs(nullptr, 0)); -} - -TEST(IntSpan, PtrLenCtor) { - int a[] = {1, 2, 3}; - absl::Span<int> s(&a[0], 2); - EXPECT_THAT(s, SpanIs(a, 2)); -} - -TEST(IntSpan, ArrayCtor) { - int a[] = {1, 2, 3}; - absl::Span<int> s(a); - EXPECT_THAT(s, SpanIs(a, 3)); - - EXPECT_TRUE((std::is_constructible<absl::Span<const int>, int[3]>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::Span<const int>, const int[3]>::value)); - EXPECT_FALSE((std::is_constructible<absl::Span<int>, const int[3]>::value)); - EXPECT_TRUE((std::is_convertible<int[3], absl::Span<const int>>::value)); - EXPECT_TRUE( - (std::is_convertible<const int[3], absl::Span<const int>>::value)); -} - -template <typename T> -void TakesGenericSpan(absl::Span<T>) {} - -TEST(IntSpan, ContainerCtor) { - std::vector<int> empty; - absl::Span<int> s_empty(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> filled{1, 2, 3}; - absl::Span<int> s_filled(filled); - EXPECT_THAT(s_filled, SpanIs(filled)); - - absl::Span<int> s_from_span(filled); - EXPECT_THAT(s_from_span, SpanIs(s_filled)); - - absl::Span<const int> const_filled = filled; - EXPECT_THAT(const_filled, SpanIs(filled)); - - absl::Span<const int> const_from_span = s_filled; - EXPECT_THAT(const_from_span, SpanIs(s_filled)); - - EXPECT_TRUE( - (std::is_convertible<std::vector<int>&, absl::Span<const int>>::value)); - EXPECT_TRUE( - (std::is_convertible<absl::Span<int>&, absl::Span<const int>>::value)); - - TakesGenericSpan(absl::Span<int>(filled)); -} - -// A struct supplying shallow data() const. -struct ContainerWithShallowConstData { - std::vector<int> storage; - int* data() const { return const_cast<int*>(storage.data()); } - int size() const { return storage.size(); } -}; - -TEST(IntSpan, ShallowConstness) { - const ContainerWithShallowConstData c{MakeRamp(20)}; - absl::Span<int> s( - c); // We should be able to do this even though data() is const. - s[0] = -1; - EXPECT_EQ(c.storage[0], -1); -} - -TEST(CharSpan, StringCtor) { - std::string empty = ""; - absl::Span<char> s_empty(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::string abc = "abc"; - absl::Span<char> s_abc(abc); - EXPECT_THAT(s_abc, SpanIs(abc)); - - absl::Span<const char> s_const_abc = abc; - EXPECT_THAT(s_const_abc, SpanIs(abc)); - - EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<const int>, std::string>::value)); - EXPECT_TRUE( - (std::is_convertible<std::string, absl::Span<const char>>::value)); -} - -TEST(IntSpan, FromConstPointer) { - EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>, - std::vector<int*>>::value)); - EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>, - std::vector<const int*>>::value)); - EXPECT_FALSE(( - std::is_constructible<absl::Span<const int*>, std::vector<int*>>::value)); - EXPECT_FALSE(( - std::is_constructible<absl::Span<int*>, std::vector<const int*>>::value)); -} - -struct TypeWithMisleadingData { - int& data() { return i; } - int size() { return 1; } - int i; -}; - -struct TypeWithMisleadingSize { - int* data() { return &i; } - const char* size() { return "1"; } - int i; -}; - -TEST(IntSpan, EvilTypes) { - EXPECT_FALSE( - (std::is_constructible<absl::Span<int>, TypeWithMisleadingData&>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<int>, TypeWithMisleadingSize&>::value)); -} - -struct Base { - int* data() { return &i; } - int size() { return 1; } - int i; -}; -struct Derived : Base {}; - -TEST(IntSpan, SpanOfDerived) { - EXPECT_TRUE((std::is_constructible<absl::Span<int>, Base&>::value)); - EXPECT_TRUE((std::is_constructible<absl::Span<int>, Derived&>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<Base>, std::vector<Derived>>::value)); -} - -void TestInitializerList(absl::Span<const int> s, const std::vector<int>& v) { - EXPECT_TRUE(absl::equal(s.begin(), s.end(), v.begin(), v.end())); -} - -TEST(ConstIntSpan, InitializerListConversion) { - TestInitializerList({}, {}); - TestInitializerList({1}, {1}); - TestInitializerList({1, 2, 3}, {1, 2, 3}); - - EXPECT_FALSE((std::is_constructible<absl::Span<int>, - std::initializer_list<int>>::value)); - EXPECT_FALSE(( - std::is_convertible<absl::Span<int>, std::initializer_list<int>>::value)); -} - -TEST(IntSpan, Data) { - int i; - absl::Span<int> s(&i, 1); - EXPECT_EQ(&i, s.data()); -} - -TEST(IntSpan, SizeLengthEmpty) { - absl::Span<int> empty; - EXPECT_EQ(empty.size(), 0); - EXPECT_TRUE(empty.empty()); - EXPECT_EQ(empty.size(), empty.length()); - - auto v = MakeRamp(10); - absl::Span<int> s(v); - EXPECT_EQ(s.size(), 10); - EXPECT_FALSE(s.empty()); - EXPECT_EQ(s.size(), s.length()); -} - -TEST(IntSpan, ElementAccess) { - auto v = MakeRamp(10); - absl::Span<int> s(v); - for (int i = 0; i < s.size(); ++i) { - EXPECT_EQ(s[i], s.at(i)); - } - - 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) { - auto v = MakeRamp(10); - absl::Span<int> s(v); - - EXPECT_EQ(s.at(9), 9); - ABSL_BASE_INTERNAL_EXPECT_FAIL(s.at(10), std::out_of_range, - "failed bounds check"); -} - -TEST(IntSpan, RemovePrefixAndSuffix) { - auto v = MakeRamp(20, 1); - absl::Span<int> s(v); - EXPECT_EQ(s.size(), 20); - - s.remove_suffix(0); - s.remove_prefix(0); - EXPECT_EQ(s.size(), 20); - - s.remove_prefix(1); - EXPECT_EQ(s.size(), 19); - EXPECT_EQ(s[0], 2); - - s.remove_suffix(1); - EXPECT_EQ(s.size(), 18); - EXPECT_EQ(s.back(), 19); - - s.remove_prefix(7); - EXPECT_EQ(s.size(), 11); - EXPECT_EQ(s[0], 9); - - s.remove_suffix(11); - 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) { - std::vector<int> empty; - EXPECT_EQ(absl::MakeSpan(empty).subspan(), empty); - EXPECT_THAT(absl::MakeSpan(empty).subspan(0, 0), SpanIs(empty)); - EXPECT_THAT(absl::MakeSpan(empty).subspan(0, absl::Span<const int>::npos), - SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, absl::Span<const int>::npos), - SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 3), SpanIs(ramp.data(), 3)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(5, absl::Span<const int>::npos), - SpanIs(ramp.data() + 5, 5)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(3, 3), SpanIs(ramp.data() + 3, 3)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(10, 5), SpanIs(ramp.data() + 10, 0)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), ""); -#endif -} - -TEST(IntSpan, First) { - std::vector<int> empty; - EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0)); - EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), ""); -#endif -} - -TEST(IntSpan, Last) { - std::vector<int> empty; - EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0)); - EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), ""); -#endif -} - -TEST(IntSpan, MakeSpanPtrLength) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty.data(), empty.size()); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::array<int, 3> a{{1, 2, 3}}; - auto s = absl::MakeSpan(a.data(), a.size()); - EXPECT_THAT(s, SpanIs(a)); - - EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.size()), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(a.data(), a.size()), SpanIs(s)); -} - -TEST(IntSpan, MakeSpanTwoPtrs) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty.data(), empty.data()); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> v{1, 2, 3}; - auto s = absl::MakeSpan(v.data(), v.data() + 1); - EXPECT_THAT(s, SpanIs(v.data(), 1)); - - EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.data()), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(v.data(), v.data() + 1), SpanIs(s)); -} - -TEST(IntSpan, MakeSpanContainer) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> v{1, 2, 3}; - auto s = absl::MakeSpan(v); - EXPECT_THAT(s, SpanIs(v)); - - EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(v), SpanIs(s)); - - EXPECT_THAT(absl::MakeSpan(s), SpanIs(s)); - EXPECT_THAT(absl::MakeConstSpan(s), SpanIs(s)); -} - -TEST(CharSpan, MakeSpanString) { - std::string empty = ""; - auto s_empty = absl::MakeSpan(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::string str = "abc"; - auto s_str = absl::MakeSpan(str); - EXPECT_THAT(s_str, SpanIs(str)); - - EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(str), SpanIs(s_str)); -} - -TEST(IntSpan, MakeSpanArray) { - int a[] = {1, 2, 3}; - auto s = absl::MakeSpan(a); - EXPECT_THAT(s, SpanIs(a, 3)); - - const int ca[] = {1, 2, 3}; - auto s_ca = absl::MakeSpan(ca); - EXPECT_THAT(s_ca, SpanIs(ca, 3)); - - EXPECT_THAT(absl::MakeConstSpan(a), SpanIs(s)); - EXPECT_THAT(absl::MakeConstSpan(ca), SpanIs(s_ca)); -} - -// Compile-asserts that the argument has the expected decayed type. -template <typename Expected, typename T> -void CheckType(const T& /* value */) { - testing::StaticAssertTypeEq<Expected, T>(); -} - -TEST(IntSpan, MakeSpanTypes) { - std::vector<int> vec; - const std::vector<int> cvec; - int a[1]; - const int ca[] = {1}; - int* ip = a; - const int* cip = ca; - std::string s = ""; - const std::string cs = ""; - CheckType<absl::Span<int>>(absl::MakeSpan(vec)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cvec)); - CheckType<absl::Span<int>>(absl::MakeSpan(ip, ip + 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(ip, 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cip, cip + 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cip, 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(a)); - CheckType<absl::Span<int>>(absl::MakeSpan(a, a + 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(a, 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca, ca + 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca, 1)); - CheckType<absl::Span<char>>(absl::MakeSpan(s)); - CheckType<absl::Span<const char>>(absl::MakeSpan(cs)); -} - -TEST(ConstIntSpan, MakeConstSpanTypes) { - std::vector<int> vec; - const std::vector<int> cvec; - int array[1]; - const int carray[] = {0}; - int* ptr = array; - const int* cptr = carray; - std::string s = ""; - std::string cs = ""; - CheckType<absl::Span<const int>>(absl::MakeConstSpan(vec)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cvec)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, ptr + 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, cptr + 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(array)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(carray)); - CheckType<absl::Span<const char>>(absl::MakeConstSpan(s)); - CheckType<absl::Span<const char>>(absl::MakeConstSpan(cs)); -} - -TEST(IntSpan, Equality) { - const int arr1[] = {1, 2, 3, 4, 5}; - int arr2[] = {1, 2, 3, 4, 5}; - std::vector<int> vec1(std::begin(arr1), std::end(arr1)); - std::vector<int> vec2 = vec1; - std::vector<int> other_vec = {2, 4, 6, 8, 10}; - // These two slices are from different vectors, but have the same size and - // have the same elements (right now). They should compare equal. Test both - // == and !=. - const absl::Span<const int> from1 = vec1; - const absl::Span<const int> from2 = vec2; - EXPECT_EQ(from1, from1); - EXPECT_FALSE(from1 != from1); - EXPECT_EQ(from1, from2); - EXPECT_FALSE(from1 != from2); - - // These two slices have different underlying vector values. They should be - // considered not equal. Test both == and !=. - const absl::Span<const int> from_other = other_vec; - EXPECT_NE(from1, from_other); - EXPECT_FALSE(from1 == from_other); - - // Comparison between a vector and its slice should be equal. And vice-versa. - // This ensures implicit conversion to Span works on both sides of ==. - EXPECT_EQ(vec1, from1); - EXPECT_FALSE(vec1 != from1); - EXPECT_EQ(from1, vec1); - EXPECT_FALSE(from1 != vec1); - - // This verifies that absl::Span<T> can be compared freely with - // absl::Span<const T>. - const absl::Span<int> mutable_from1(vec1); - const absl::Span<int> mutable_from2(vec2); - EXPECT_EQ(from1, mutable_from1); - EXPECT_EQ(mutable_from1, from1); - EXPECT_EQ(mutable_from1, mutable_from2); - EXPECT_EQ(mutable_from2, mutable_from1); - - // Comparison between a vector and its slice should be equal for mutable - // Spans as well. - EXPECT_EQ(vec1, mutable_from1); - EXPECT_FALSE(vec1 != mutable_from1); - EXPECT_EQ(mutable_from1, vec1); - EXPECT_FALSE(mutable_from1 != vec1); - - // Comparison between convertible-to-Span-of-const and Span-of-mutable. Arrays - // are used because they're the only value type which converts to a - // Span-of-mutable. EXPECT_TRUE is used instead of EXPECT_EQ to avoid - // array-to-pointer decay. - EXPECT_TRUE(arr1 == mutable_from1); - EXPECT_FALSE(arr1 != mutable_from1); - EXPECT_TRUE(mutable_from1 == arr1); - EXPECT_FALSE(mutable_from1 != arr1); - - // Comparison between convertible-to-Span-of-mutable and Span-of-const - EXPECT_TRUE(arr2 == from1); - EXPECT_FALSE(arr2 != from1); - EXPECT_TRUE(from1 == arr2); - EXPECT_FALSE(from1 != arr2); - - // With a different size, the array slices should not be equal. - EXPECT_NE(from1, absl::Span<const int>(from1).subspan(0, from1.size() - 1)); - - // With different contents, the array slices should not be equal. - ++vec2.back(); - EXPECT_NE(from1, from2); -} - -class IntSpanOrderComparisonTest : public testing::Test { - public: - IntSpanOrderComparisonTest() - : arr_before_{1, 2, 3}, - arr_after_{1, 2, 4}, - carr_after_{1, 2, 4}, - vec_before_(std::begin(arr_before_), std::end(arr_before_)), - vec_after_(std::begin(arr_after_), std::end(arr_after_)), - before_(vec_before_), - after_(vec_after_), - cbefore_(vec_before_), - cafter_(vec_after_) {} - - protected: - int arr_before_[3], arr_after_[3]; - const int carr_after_[3]; - std::vector<int> vec_before_, vec_after_; - absl::Span<int> before_, after_; - absl::Span<const int> cbefore_, cafter_; -}; - -TEST_F(IntSpanOrderComparisonTest, CompareSpans) { - EXPECT_TRUE(cbefore_ < cafter_); - EXPECT_TRUE(cbefore_ <= cafter_); - EXPECT_TRUE(cafter_ > cbefore_); - EXPECT_TRUE(cafter_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > cafter_); - EXPECT_FALSE(cafter_ < cbefore_); - - EXPECT_TRUE(before_ < after_); - EXPECT_TRUE(before_ <= after_); - EXPECT_TRUE(after_ > before_); - EXPECT_TRUE(after_ >= before_); - - EXPECT_FALSE(before_ > after_); - EXPECT_FALSE(after_ < before_); - - EXPECT_TRUE(cbefore_ < after_); - EXPECT_TRUE(cbefore_ <= after_); - EXPECT_TRUE(after_ > cbefore_); - EXPECT_TRUE(after_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > after_); - EXPECT_FALSE(after_ < cbefore_); -} - -TEST_F(IntSpanOrderComparisonTest, SpanOfConstAndContainer) { - EXPECT_TRUE(cbefore_ < vec_after_); - EXPECT_TRUE(cbefore_ <= vec_after_); - EXPECT_TRUE(vec_after_ > cbefore_); - EXPECT_TRUE(vec_after_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > vec_after_); - EXPECT_FALSE(vec_after_ < cbefore_); - - EXPECT_TRUE(arr_before_ < cafter_); - EXPECT_TRUE(arr_before_ <= cafter_); - EXPECT_TRUE(cafter_ > arr_before_); - EXPECT_TRUE(cafter_ >= arr_before_); - - EXPECT_FALSE(arr_before_ > cafter_); - EXPECT_FALSE(cafter_ < arr_before_); -} - -TEST_F(IntSpanOrderComparisonTest, SpanOfMutableAndContainer) { - EXPECT_TRUE(vec_before_ < after_); - EXPECT_TRUE(vec_before_ <= after_); - EXPECT_TRUE(after_ > vec_before_); - EXPECT_TRUE(after_ >= vec_before_); - - EXPECT_FALSE(vec_before_ > after_); - EXPECT_FALSE(after_ < vec_before_); - - EXPECT_TRUE(before_ < carr_after_); - EXPECT_TRUE(before_ <= carr_after_); - EXPECT_TRUE(carr_after_ > before_); - EXPECT_TRUE(carr_after_ >= before_); - - EXPECT_FALSE(before_ > carr_after_); - EXPECT_FALSE(carr_after_ < before_); -} - -TEST_F(IntSpanOrderComparisonTest, EqualSpans) { - EXPECT_FALSE(before_ < before_); - EXPECT_TRUE(before_ <= before_); - EXPECT_FALSE(before_ > before_); - EXPECT_TRUE(before_ >= before_); -} - -TEST_F(IntSpanOrderComparisonTest, Subspans) { - auto subspan = before_.subspan(0, 1); - EXPECT_TRUE(subspan < before_); - EXPECT_TRUE(subspan <= before_); - EXPECT_TRUE(before_ > subspan); - EXPECT_TRUE(before_ >= subspan); - - EXPECT_FALSE(subspan > before_); - EXPECT_FALSE(before_ < subspan); -} - -TEST_F(IntSpanOrderComparisonTest, EmptySpans) { - absl::Span<int> empty; - EXPECT_FALSE(empty < empty); - EXPECT_TRUE(empty <= empty); - EXPECT_FALSE(empty > empty); - EXPECT_TRUE(empty >= empty); - - EXPECT_TRUE(empty < before_); - EXPECT_TRUE(empty <= before_); - EXPECT_TRUE(before_ > empty); - EXPECT_TRUE(before_ >= empty); - - EXPECT_FALSE(empty > before_); - EXPECT_FALSE(before_ < empty); -} - -TEST(IntSpan, ExposesContainerTypesAndConsts) { - absl::Span<int> slice; - CheckType<absl::Span<int>::iterator>(slice.begin()); - EXPECT_TRUE((std::is_convertible<decltype(slice.begin()), - absl::Span<int>::const_iterator>::value)); - CheckType<absl::Span<int>::const_iterator>(slice.cbegin()); - EXPECT_TRUE((std::is_convertible<decltype(slice.end()), - absl::Span<int>::const_iterator>::value)); - CheckType<absl::Span<int>::const_iterator>(slice.cend()); - CheckType<absl::Span<int>::reverse_iterator>(slice.rend()); - EXPECT_TRUE( - (std::is_convertible<decltype(slice.rend()), - absl::Span<int>::const_reverse_iterator>::value)); - 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>::pointer>(); - testing::StaticAssertTypeEq<const int*, absl::Span<const int>::pointer>(); - testing::StaticAssertTypeEq<int&, absl::Span<int>::reference>(); - testing::StaticAssertTypeEq<const int&, absl::Span<const int>::reference>(); - testing::StaticAssertTypeEq<const int&, absl::Span<int>::const_reference>(); - testing::StaticAssertTypeEq<const int&, - absl::Span<const int>::const_reference>(); - EXPECT_EQ(static_cast<absl::Span<int>::size_type>(-1), absl::Span<int>::npos); -} - -TEST(IntSpan, IteratorsAndReferences) { - auto accept_pointer = [](int*) {}; - auto accept_reference = [](int&) {}; - auto accept_iterator = [](absl::Span<int>::iterator) {}; - auto accept_const_iterator = [](absl::Span<int>::const_iterator) {}; - auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {}; - auto accept_const_reverse_iterator = - [](absl::Span<int>::const_reverse_iterator) {}; - - int a[1]; - absl::Span<int> s = a; - - accept_pointer(s.data()); - accept_iterator(s.begin()); - accept_const_iterator(s.begin()); - accept_const_iterator(s.cbegin()); - accept_iterator(s.end()); - accept_const_iterator(s.end()); - accept_const_iterator(s.cend()); - accept_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.crbegin()); - accept_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.crend()); - - accept_reference(s[0]); - accept_reference(s.at(0)); - accept_reference(s.front()); - accept_reference(s.back()); -} - -TEST(IntSpan, IteratorsAndReferences_Const) { - auto accept_pointer = [](int*) {}; - auto accept_reference = [](int&) {}; - auto accept_iterator = [](absl::Span<int>::iterator) {}; - auto accept_const_iterator = [](absl::Span<int>::const_iterator) {}; - auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {}; - auto accept_const_reverse_iterator = - [](absl::Span<int>::const_reverse_iterator) {}; - - int a[1]; - const absl::Span<int> s = a; - - accept_pointer(s.data()); - accept_iterator(s.begin()); - accept_const_iterator(s.begin()); - accept_const_iterator(s.cbegin()); - accept_iterator(s.end()); - accept_const_iterator(s.end()); - accept_const_iterator(s.cend()); - accept_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.crbegin()); - accept_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.crend()); - - accept_reference(s[0]); - accept_reference(s.at(0)); - accept_reference(s.front()); - accept_reference(s.back()); -} - -TEST(IntSpan, NoexceptTest) { - int a[] = {1, 2, 3}; - std::vector<int> v; - EXPECT_TRUE(noexcept(absl::Span<const int>())); - EXPECT_TRUE(noexcept(absl::Span<const int>(a, 2))); - EXPECT_TRUE(noexcept(absl::Span<const int>(a))); - EXPECT_TRUE(noexcept(absl::Span<const int>(v))); - EXPECT_TRUE(noexcept(absl::Span<int>(v))); - EXPECT_TRUE(noexcept(absl::Span<const int>({1, 2, 3}))); - EXPECT_TRUE(noexcept(absl::MakeSpan(v))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a, 2))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a, a + 1))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(v))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, 2))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, a + 1))); - - absl::Span<int> s(v); - EXPECT_TRUE(noexcept(s.data())); - EXPECT_TRUE(noexcept(s.size())); - EXPECT_TRUE(noexcept(s.length())); - EXPECT_TRUE(noexcept(s.empty())); - EXPECT_TRUE(noexcept(s[0])); - EXPECT_TRUE(noexcept(s.front())); - EXPECT_TRUE(noexcept(s.back())); - EXPECT_TRUE(noexcept(s.begin())); - EXPECT_TRUE(noexcept(s.cbegin())); - EXPECT_TRUE(noexcept(s.end())); - EXPECT_TRUE(noexcept(s.cend())); - EXPECT_TRUE(noexcept(s.rbegin())); - EXPECT_TRUE(noexcept(s.crbegin())); - EXPECT_TRUE(noexcept(s.rend())); - EXPECT_TRUE(noexcept(s.crend())); - EXPECT_TRUE(noexcept(s.remove_prefix(0))); - EXPECT_TRUE(noexcept(s.remove_suffix(0))); -} - -// ConstexprTester exercises expressions in a constexpr context. Simply placing -// the expression in a constexpr function is not enough, as some compilers will -// simply compile the constexpr function as runtime code. Using template -// parameters forces compile-time execution. -template <int i> -struct ConstexprTester {}; - -#define ABSL_TEST_CONSTEXPR(expr) \ - do { \ - ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \ - } while (0) - -struct ContainerWithConstexprMethods { - constexpr int size() const { return 1; } - constexpr const int* data() const { return &i; } - const int i; -}; - -TEST(ConstIntSpan, ConstexprTest) { - static constexpr int a[] = {1, 2, 3}; - static constexpr int sized_arr[2] = {1, 2}; - static constexpr ContainerWithConstexprMethods c{1}; - ABSL_TEST_CONSTEXPR(absl::Span<const int>()); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(a, 2)); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(sized_arr)); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(c)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(&a[0], 1)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(c)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(a)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(&a[0], 1)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(c)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(a)); - - constexpr absl::Span<const int> span = c; - ABSL_TEST_CONSTEXPR(span.data()); - ABSL_TEST_CONSTEXPR(span.size()); - ABSL_TEST_CONSTEXPR(span.length()); - ABSL_TEST_CONSTEXPR(span.empty()); - ABSL_TEST_CONSTEXPR(span.begin()); - ABSL_TEST_CONSTEXPR(span.cbegin()); - ABSL_TEST_CONSTEXPR(span.subspan(0, 0)); - ABSL_TEST_CONSTEXPR(span.first(1)); - ABSL_TEST_CONSTEXPR(span.last(1)); - ABSL_TEST_CONSTEXPR(span[0]); -} - -struct BigStruct { - char bytes[10000]; -}; - -TEST(Span, SpanSize) { - EXPECT_LE(sizeof(absl::Span<int>), 2 * sizeof(void*)); - EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*)); -} - -TEST(Span, Hash) { - int array[] = {1, 2, 3, 4}; - int array2[] = {1, 2, 3}; - using T = absl::Span<const int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {// Empties - T(), T(nullptr, 0), T(array, 0), T(array2, 0), - // Different array with same value - T(array, 3), T(array2), T({1, 2, 3}), - // Same array, but different length - T(array, 1), T(array, 2), - // Same length, but different array - T(array + 1, 2), T(array + 2, 2)})); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/variant.h b/third_party/abseil_cpp/absl/types/variant.h deleted file mode 100644 index ac93464bf8d0..000000000000 --- a/third_party/abseil_cpp/absl/types/variant.h +++ /dev/null @@ -1,866 +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. -// -// ----------------------------------------------------------------------------- -// variant.h -// ----------------------------------------------------------------------------- -// -// This header file defines an `absl::variant` type for holding a type-safe -// value of some prescribed set of types (noted as alternative types), and -// associated functions for managing variants. -// -// The `absl::variant` type is a form of type-safe union. An `absl::variant` -// should always hold a value of one of its alternative types (except in the -// "valueless by exception state" -- see below). A default-constructed -// `absl::variant` will hold the value of its first alternative type, provided -// it is default-constructible. -// -// In exceptional cases due to error, an `absl::variant` can hold no -// value (known as a "valueless by exception" state), though this is not the -// norm. -// -// As with `absl::optional`, an `absl::variant` -- when it holds a value -- -// allocates a value of that type directly within the `variant` itself; it -// cannot hold a reference, array, or the type `void`; it can, however, hold a -// pointer to externally managed memory. -// -// `absl::variant` is a C++11 compatible version of the C++17 `std::variant` -// abstraction and is designed to be a drop-in replacement for code compliant -// with C++17. - -#ifndef ABSL_TYPES_VARIANT_H_ -#define ABSL_TYPES_VARIANT_H_ - -#include "absl/base/config.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_VARIANT - -#include <variant> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_variant_access; -using std::get; -using std::get_if; -using std::holds_alternative; -using std::monostate; -using std::variant; -using std::variant_alternative; -using std::variant_alternative_t; -using std::variant_npos; -using std::variant_size; -using std::variant_size_v; -using std::visit; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_VARIANT - -#include <functional> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" -#include "absl/types/internal/variant.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// absl::variant -// ----------------------------------------------------------------------------- -// -// An `absl::variant` type is a form of type-safe union. An `absl::variant` -- -// except in exceptional cases -- always holds a value of one of its alternative -// types. -// -// Example: -// -// // Construct a variant that holds either an integer or a std::string and -// // assign it to a std::string. -// absl::variant<int, std::string> v = std::string("abc"); -// -// // A default-constructed variant will hold a value-initialized value of -// // the first alternative type. -// auto a = absl::variant<int, std::string>(); // Holds an int of value '0'. -// -// // variants are assignable. -// -// // copy assignment -// auto v1 = absl::variant<int, std::string>("abc"); -// auto v2 = absl::variant<int, std::string>(10); -// v2 = v1; // copy assign -// -// // move assignment -// auto v1 = absl::variant<int, std::string>("abc"); -// v1 = absl::variant<int, std::string>(10); -// -// // assignment through type conversion -// a = 128; // variant contains int -// a = "128"; // variant contains std::string -// -// An `absl::variant` holding a value of one of its alternative types `T` holds -// an allocation of `T` directly within the variant itself. An `absl::variant` -// is not allowed to allocate additional storage, such as dynamic memory, to -// allocate the contained value. The contained value shall be allocated in a -// region of the variant storage suitably aligned for all alternative types. -template <typename... Ts> -class variant; - -// swap() -// -// Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)` -// where `v` and `w` are `absl::variant` types. -// -// Note that this function requires all alternative types to be both swappable -// and move-constructible, because any two variants may refer to either the same -// type (in which case, they will be swapped) or to two different types (in -// which case the values will need to be moved). -// -template < - typename... Ts, - absl::enable_if_t< - absl::conjunction<std::is_move_constructible<Ts>..., - type_traits_internal::IsSwappable<Ts>...>::value, - int> = 0> -void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) { - v.swap(w); -} - -// variant_size -// -// Returns the number of alternative types available for a given `absl::variant` -// type as a compile-time constant expression. As this is a class template, it -// is not generally useful for accessing the number of alternative types of -// any given `absl::variant` instance. -// -// Example: -// -// auto a = absl::variant<int, std::string>; -// constexpr int num_types = -// absl::variant_size<absl::variant<int, std::string>>(); -// -// // You can also use the member constant `value`. -// constexpr int num_types = -// absl::variant_size<absl::variant<int, std::string>>::value; -// -// // `absl::variant_size` is more valuable for use in generic code: -// template <typename Variant> -// constexpr bool IsVariantMultivalue() { -// return absl::variant_size<Variant>() > 1; -// } -// -// Note that the set of cv-qualified specializations of `variant_size` are -// provided to ensure that those specializations compile (especially when passed -// within template logic). -template <class T> -struct variant_size; - -template <class... Ts> -struct variant_size<variant<Ts...>> - : std::integral_constant<std::size_t, sizeof...(Ts)> {}; - -// Specialization of `variant_size` for const qualified variants. -template <class T> -struct variant_size<const T> : variant_size<T>::type {}; - -// Specialization of `variant_size` for volatile qualified variants. -template <class T> -struct variant_size<volatile T> : variant_size<T>::type {}; - -// Specialization of `variant_size` for const volatile qualified variants. -template <class T> -struct variant_size<const volatile T> : variant_size<T>::type {}; - -// variant_alternative -// -// Returns the alternative type for a given `absl::variant` at the passed -// index value as a compile-time constant expression. As this is a class -// template resulting in a type, it is not useful for access of the run-time -// value of any given `absl::variant` variable. -// -// Example: -// -// // The type of the 0th alternative is "int". -// using alternative_type_0 -// = absl::variant_alternative<0, absl::variant<int, std::string>>::type; -// -// static_assert(std::is_same<alternative_type_0, int>::value, ""); -// -// // `absl::variant_alternative` is more valuable for use in generic code: -// template <typename Variant> -// constexpr bool IsFirstElementTrivial() { -// return std::is_trivial_v<variant_alternative<0, Variant>::type>; -// } -// -// Note that the set of cv-qualified specializations of `variant_alternative` -// are provided to ensure that those specializations compile (especially when -// passed within template logic). -template <std::size_t I, class T> -struct variant_alternative; - -template <std::size_t I, class... Types> -struct variant_alternative<I, variant<Types...>> { - using type = - variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>; -}; - -// Specialization of `variant_alternative` for const qualified variants. -template <std::size_t I, class T> -struct variant_alternative<I, const T> { - using type = const typename variant_alternative<I, T>::type; -}; - -// Specialization of `variant_alternative` for volatile qualified variants. -template <std::size_t I, class T> -struct variant_alternative<I, volatile T> { - using type = volatile typename variant_alternative<I, T>::type; -}; - -// Specialization of `variant_alternative` for const volatile qualified -// variants. -template <std::size_t I, class T> -struct variant_alternative<I, const volatile T> { - using type = const volatile typename variant_alternative<I, T>::type; -}; - -// Template type alias for variant_alternative<I, T>::type. -// -// Example: -// -// using alternative_type_0 -// = absl::variant_alternative_t<0, absl::variant<int, std::string>>; -// static_assert(std::is_same<alternative_type_0, int>::value, ""); -template <std::size_t I, class T> -using variant_alternative_t = typename variant_alternative<I, T>::type; - -// holds_alternative() -// -// Checks whether the given variant currently holds a given alternative type, -// returning `true` if so. -// -// Example: -// -// absl::variant<int, std::string> foo = 42; -// if (absl::holds_alternative<int>(foo)) { -// std::cout << "The variant holds an integer"; -// } -template <class T, class... Types> -constexpr bool holds_alternative(const variant<Types...>& v) noexcept { - static_assert( - variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T, - 0>::value != sizeof...(Types), - "The type T must occur exactly once in Types..."); - return v.index() == - variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value; -} - -// get() -// -// Returns a reference to the value currently within a given variant, using -// either a unique alternative type amongst the variant's set of alternative -// types, or the variant's index value. Attempting to get a variant's value -// using a type that is not unique within the variant's set of alternative types -// is a compile-time error. If the index of the alternative being specified is -// different from the index of the alternative that is currently stored, throws -// `absl::bad_variant_access`. -// -// Example: -// -// auto a = absl::variant<int, std::string>; -// -// // Get the value by type (if unique). -// int i = absl::get<int>(a); -// -// auto b = absl::variant<int, int>; -// -// // Getting the value by a type that is not unique is ill-formed. -// int j = absl::get<int>(b); // Compile Error! -// -// // Getting value by index not ambiguous and allowed. -// int k = absl::get<1>(b); - -// Overload for getting a variant's lvalue by type. -template <class T, class... Types> -constexpr T& get(variant<Types...>& v) { // NOLINT - return variant_internal::VariantCoreAccess::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a variant's rvalue by type. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <class T, class... Types> -constexpr T&& get(variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); -} - -// Overload for getting a variant's const lvalue by type. -template <class T, class... Types> -constexpr const T& get(const variant<Types...>& v) { - return variant_internal::VariantCoreAccess::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a variant's const rvalue by type. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <class T, class... Types> -constexpr const T&& get(const variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); -} - -// Overload for getting a variant's lvalue by index. -template <std::size_t I, class... Types> -constexpr variant_alternative_t<I, variant<Types...>>& get( - variant<Types...>& v) { // NOLINT - return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); -} - -// Overload for getting a variant's rvalue by index. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <std::size_t I, class... Types> -constexpr variant_alternative_t<I, variant<Types...>>&& get( - variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); -} - -// Overload for getting a variant's const lvalue by index. -template <std::size_t I, class... Types> -constexpr const variant_alternative_t<I, variant<Types...>>& get( - const variant<Types...>& v) { - return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); -} - -// Overload for getting a variant's const rvalue by index. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <std::size_t I, class... Types> -constexpr const variant_alternative_t<I, variant<Types...>>&& get( - const variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); -} - -// get_if() -// -// Returns a pointer to the value currently stored within a given variant, if -// present, using either a unique alternative type amongst the variant's set of -// alternative types, or the variant's index value. If such a value does not -// exist, returns `nullptr`. -// -// As with `get`, attempting to get a variant's value using a type that is not -// unique within the variant's set of alternative types is a compile-time error. - -// Overload for getting a pointer to the value stored in the given variant by -// index. -template <std::size_t I, class... Types> -constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>> -get_if(variant<Types...>* v) noexcept { - return (v != nullptr && v->index() == I) - ? std::addressof( - variant_internal::VariantCoreAccess::Access<I>(*v)) - : nullptr; -} - -// Overload for getting a pointer to the const value stored in the given -// variant by index. -template <std::size_t I, class... Types> -constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>> -get_if(const variant<Types...>* v) noexcept { - return (v != nullptr && v->index() == I) - ? std::addressof( - variant_internal::VariantCoreAccess::Access<I>(*v)) - : nullptr; -} - -// Overload for getting a pointer to the value stored in the given variant by -// type. -template <class T, class... Types> -constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept { - return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a pointer to the const value stored in the given variant -// by type. -template <class T, class... Types> -constexpr absl::add_pointer_t<const T> get_if( - const variant<Types...>* v) noexcept { - return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); -} - -// visit() -// -// Calls a provided functor on a given set of variants. `absl::visit()` is -// commonly used to conditionally inspect the state of a given variant (or set -// of variants). -// -// The functor must return the same type when called with any of the variants' -// alternatives. -// -// Example: -// -// // Define a visitor functor -// struct GetVariant { -// template<typename T> -// void operator()(const T& i) const { -// std::cout << "The variant's value is: " << i; -// } -// }; -// -// // Declare our variant, and call `absl::visit()` on it. -// // Note that `GetVariant()` returns void in either case. -// absl::variant<int, std::string> foo = std::string("foo"); -// GetVariant visitor; -// absl::visit(visitor, foo); // Prints `The variant's value is: foo' -template <typename Visitor, typename... Variants> -variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis, - Variants&&... vars) { - return variant_internal:: - VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run( - variant_internal::PerformVisitation<Visitor, Variants...>{ - std::forward_as_tuple(absl::forward<Variants>(vars)...), - absl::forward<Visitor>(vis)}, - vars.index()...); -} - -// monostate -// -// The monostate class serves as a first alternative type for a variant for -// which the first variant type is otherwise not default-constructible. -struct monostate {}; - -// `absl::monostate` Relational Operators - -constexpr bool operator<(monostate, monostate) noexcept { return false; } -constexpr bool operator>(monostate, monostate) noexcept { return false; } -constexpr bool operator<=(monostate, monostate) noexcept { return true; } -constexpr bool operator>=(monostate, monostate) noexcept { return true; } -constexpr bool operator==(monostate, monostate) noexcept { return true; } -constexpr bool operator!=(monostate, monostate) noexcept { return false; } - - -//------------------------------------------------------------------------------ -// `absl::variant` Template Definition -//------------------------------------------------------------------------------ -template <typename T0, typename... Tn> -class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { - static_assert(absl::conjunction<std::is_object<T0>, - std::is_object<Tn>...>::value, - "Attempted to instantiate a variant containing a non-object " - "type."); - // Intentionally not qualifying `negation` with `absl::` to work around a bug - // in MSVC 2015 with inline namespace and variadic template. - static_assert(absl::conjunction<negation<std::is_array<T0> >, - negation<std::is_array<Tn> >...>::value, - "Attempted to instantiate a variant containing an array type."); - static_assert(absl::conjunction<std::is_nothrow_destructible<T0>, - std::is_nothrow_destructible<Tn>...>::value, - "Attempted to instantiate a variant containing a non-nothrow " - "destructible type."); - - friend struct variant_internal::VariantCoreAccess; - - private: - using Base = variant_internal::VariantBase<T0, Tn...>; - - public: - // Constructors - - // Constructs a variant holding a default-initialized value of the first - // alternative type. - constexpr variant() /*noexcept(see 111above)*/ = default; - - // Copy constructor, standard semantics - variant(const variant& other) = default; - - // Move constructor, standard semantics - variant(variant&& other) /*noexcept(see above)*/ = default; - - // Constructs a variant of an alternative type specified by overload - // resolution of the provided forwarding arguments through - // direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - // - // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html - // has been voted passed the design phase in the C++ standard meeting in Mar - // 2018. It will be implemented and integrated into `absl::variant`. - template < - class T, - std::size_t I = std::enable_if< - variant_internal::IsNeitherSelfNorInPlace<variant, - absl::decay_t<T>>::value, - variant_internal::IndexOfConstructedType<variant, T>>::type::value, - class Tj = absl::variant_alternative_t<I, variant>, - absl::enable_if_t<std::is_constructible<Tj, T>::value>* = - nullptr> - constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value) - : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {} - - // Constructs a variant of an alternative type from the arguments through - // direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - template <class T, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::UnambiguousTypeOfT<variant, T>, - Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_type_t<T>, Args&&... args) - : Base(variant_internal::EmplaceTag< - variant_internal::UnambiguousIndexOf<variant, T>::value>(), - absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from an initializer list - // and other arguments through direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - template <class T, class U, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::UnambiguousTypeOfT<variant, T>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il, - Args&&... args) - : Base(variant_internal::EmplaceTag< - variant_internal::UnambiguousIndexOf<variant, T>::value>(), - il, absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from a provided index, - // through value-initialization using the provided forwarded arguments. - template <std::size_t I, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::VariantAlternativeSfinaeT<I, variant>, - Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_index_t<I>, Args&&... args) - : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from a provided index, - // through value-initialization of an initializer list and the provided - // forwarded arguments. - template <std::size_t I, class U, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::VariantAlternativeSfinaeT<I, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il, - Args&&... args) - : Base(variant_internal::EmplaceTag<I>(), il, - absl::forward<Args>(args)...) {} - - // Destructors - - // Destroys the variant's currently contained value, provided that - // `absl::valueless_by_exception()` is false. - ~variant() = default; - - // Assignment Operators - - // Copy assignment operator - variant& operator=(const variant& other) = default; - - // Move assignment operator - variant& operator=(variant&& other) /*noexcept(see above)*/ = default; - - // Converting assignment operator - // - // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html - // has been voted passed the design phase in the C++ standard meeting in Mar - // 2018. It will be implemented and integrated into `absl::variant`. - template < - class T, - std::size_t I = std::enable_if< - !std::is_same<absl::decay_t<T>, variant>::value, - variant_internal::IndexOfConstructedType<variant, T>>::type::value, - class Tj = absl::variant_alternative_t<I, variant>, - typename std::enable_if<std::is_assignable<Tj&, T>::value && - std::is_constructible<Tj, T>::value>::type* = - nullptr> - variant& operator=(T&& t) noexcept( - std::is_nothrow_assignable<Tj&, T>::value&& - std::is_nothrow_constructible<Tj, T>::value) { - variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( - variant_internal::VariantCoreAccess::MakeConversionAssignVisitor( - this, absl::forward<T>(t)), - index()); - - return *this; - } - - - // 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. - // - // Example: - // - // absl::variant<std::vector<int>, int, std::string> v; - // v.emplace<int>(99); - // v.emplace<std::string>("abc"); - template < - class T, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t< - variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, - Args...>::value>::type* = nullptr> - T& emplace(Args&&... args) { - return variant_internal::VariantCoreAccess::Replace< - variant_internal::UnambiguousIndexOf<variant, T>::value>( - this, absl::forward<Args>(args)...); - } - - // 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. - // - // Example: - // - // absl::variant<std::vector<int>, int, std::string> v; - // v.emplace<std::vector<int>>({0, 1, 2}); - template < - class T, class U, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t< - variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - T& emplace(std::initializer_list<U> il, Args&&... args) { - return variant_internal::VariantCoreAccess::Replace< - variant_internal::UnambiguousIndexOf<variant, T>::value>( - this, il, absl::forward<Args>(args)...); - } - - // Destroys the current value of the variant (provided that - // `absl::valueless_by_exception()` is false) and constructs a new value at - // the given index. - // - // Example: - // - // absl::variant<std::vector<int>, int, int> v; - // v.emplace<1>(99); - // v.emplace<2>(98); - // v.emplace<int>(99); // Won't compile. 'int' isn't a unique type. - template <std::size_t I, class... Args, - typename std::enable_if< - std::is_constructible<absl::variant_alternative_t<I, variant>, - Args...>::value>::type* = nullptr> - absl::variant_alternative_t<I, variant>& emplace(Args&&... args) { - return variant_internal::VariantCoreAccess::Replace<I>( - this, absl::forward<Args>(args)...); - } - - // Destroys the current value of the variant (provided that - // `absl::valueless_by_exception()` is false) and constructs a new value at - // the given index using an initializer list and the provided arguments. - // - // Example: - // - // absl::variant<std::vector<int>, int, int> v; - // v.emplace<0>({0, 1, 2}); - template <std::size_t I, class U, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t<I, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, - Args&&... args) { - return variant_internal::VariantCoreAccess::Replace<I>( - this, il, absl::forward<Args>(args)...); - } - - // variant::valueless_by_exception() - // - // Returns false if and only if the variant currently holds a valid value. - constexpr bool valueless_by_exception() const noexcept { - return this->index_ == absl::variant_npos; - } - - // variant::index() - // - // Returns the index value of the variant's currently selected alternative - // type. - constexpr std::size_t index() const noexcept { return this->index_; } - - // variant::swap() - // - // Swaps the values of two variant objects. - // - void swap(variant& rhs) noexcept( - absl::conjunction< - std::is_nothrow_move_constructible<T0>, - std::is_nothrow_move_constructible<Tn>..., - type_traits_internal::IsNothrowSwappable<T0>, - type_traits_internal::IsNothrowSwappable<Tn>...>::value) { - return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( - variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index()); - } -}; - -// We need a valid declaration of variant<> for SFINAE and overload resolution -// to work properly above, but we don't need a full declaration since this type -// will never be constructed. This declaration, though incomplete, suffices. -template <> -class variant<>; - -//------------------------------------------------------------------------------ -// Relational Operators -//------------------------------------------------------------------------------ -// -// If neither operand is in the `variant::valueless_by_exception` state: -// -// * If the index of both variants is the same, the relational operator -// returns the result of the corresponding relational operator for the -// corresponding alternative type. -// * If the index of both variants is not the same, the relational operator -// returns the result of that operation applied to the value of the left -// operand's index and the value of the right operand's index. -// * If at least one operand is in the valueless_by_exception state: -// - A variant in the valueless_by_exception state is only considered equal -// to another variant in the valueless_by_exception state. -// - If exactly one operand is in the valueless_by_exception state, the -// variant in the valueless_by_exception state is less than the variant -// that is not in the valueless_by_exception state. -// -// Note: The value 1 is added to each index in the relational comparisons such -// that the index corresponding to the valueless_by_exception state wraps around -// to 0 (the lowest value for the index type), and the remaining indices stay in -// the same relative order. - -// Equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() == b.index()) && - variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::EqualsOp<Types...>{&a, &b}, a.index()); -} - -// Not equal operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) || - variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index()); -} - -// Less-than operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) < (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::LessThanOp<Types...>{&a, &b}, a.index()); -} - -// Greater-than operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) > (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::GreaterThanOp<Types...>{&a, &b}, - a.index()); -} - -// Less-than or equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) < (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::LessThanOrEqualsOp<Types...>{&a, &b}, - a.index()); -} - -// Greater-than or equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...> -operator>=(const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) > (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b}, - a.index()); -} - -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -// hash() -template <> // NOLINT -struct hash<absl::monostate> { - std::size_t operator()(absl::monostate) const { return 0; } -}; - -template <class... T> // NOLINT -struct hash<absl::variant<T...>> - : absl::variant_internal::VariantHashBase<absl::variant<T...>, void, - absl::remove_const_t<T>...> {}; - -} // namespace std - -#endif // ABSL_USES_STD_VARIANT - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace variant_internal { - -// Helper visitor for converting a variant<Ts...>` into another type (mostly -// variant) that can be constructed from any type. -template <typename To> -struct ConversionVisitor { - template <typename T> - To operator()(T&& v) const { - return To(std::forward<T>(v)); - } -}; - -} // namespace variant_internal - -// ConvertVariantTo() -// -// Helper functions to convert an `absl::variant` to a variant of another set of -// types, provided that the alternative type of the new variant type can be -// converted from any type in the source variant. -// -// Example: -// -// absl::variant<name1, name2, float> InternalReq(const Req&); -// -// // name1 and name2 are convertible to name -// absl::variant<name, float> ExternalReq(const Req& req) { -// return absl::ConvertVariantTo<absl::variant<name, float>>( -// InternalReq(req)); -// } -template <typename To, typename Variant> -To ConvertVariantTo(Variant&& variant) { - return absl::visit(variant_internal::ConversionVisitor<To>{}, - std::forward<Variant>(variant)); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_VARIANT_H_ diff --git a/third_party/abseil_cpp/absl/types/variant_benchmark.cc b/third_party/abseil_cpp/absl/types/variant_benchmark.cc deleted file mode 100644 index 350b17536413..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_benchmark.cc +++ /dev/null @@ -1,222 +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. - -// Unit tests for the variant template. The 'is' and 'IsEmpty' methods -// of variant are not explicitly tested because they are used repeatedly -// in building other tests. All other public variant methods should have -// explicit tests. - -#include "absl/types/variant.h" - -#include <cstddef> -#include <cstdlib> -#include <string> -#include <tuple> - -#include "benchmark/benchmark.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -template <std::size_t I> -struct VariantAlternative { - char member; -}; - -template <class Indices> -struct VariantOfAlternativesImpl; - -template <std::size_t... Indices> -struct VariantOfAlternativesImpl<absl::index_sequence<Indices...>> { - using type = absl::variant<VariantAlternative<Indices>...>; -}; - -template <std::size_t NumAlternatives> -using VariantOfAlternatives = typename VariantOfAlternativesImpl< - absl::make_index_sequence<NumAlternatives>>::type; - -struct Empty {}; - -template <class... T> -void Ignore(T...) noexcept {} - -template <class T> -Empty DoNotOptimizeAndReturnEmpty(T&& arg) noexcept { - benchmark::DoNotOptimize(arg); - return {}; -} - -struct VisitorApplier { - struct Visitor { - template <class... T> - void operator()(T&&... args) const noexcept { - Ignore(DoNotOptimizeAndReturnEmpty(args)...); - } - }; - - template <class... Vars> - void operator()(const Vars&... vars) const noexcept { - absl::visit(Visitor(), vars...); - } -}; - -template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1> -struct MakeWithIndex { - using Variant = VariantOfAlternatives<NumIndices>; - - static Variant Run(std::size_t index) { - return index == CurrIndex - ? Variant(absl::in_place_index_t<CurrIndex>()) - : MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index); - } -}; - -template <std::size_t NumIndices> -struct MakeWithIndex<NumIndices, 0> { - using Variant = VariantOfAlternatives<NumIndices>; - - static Variant Run(std::size_t /*index*/) { return Variant(); } -}; - -template <std::size_t NumIndices, class Dimensions> -struct MakeVariantTuple; - -template <class T, std::size_t /*I*/> -using always_t = T; - -template <std::size_t NumIndices> -VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension, - std::size_t index) { - return dimension == 0 - ? MakeWithIndex<NumIndices>::Run(index % NumIndices) - : MakeVariant<NumIndices>(dimension - 1, index / NumIndices); -} - -template <std::size_t NumIndices, std::size_t... Dimensions> -struct MakeVariantTuple<NumIndices, absl::index_sequence<Dimensions...>> { - using VariantTuple = - std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>; - - static VariantTuple Run(int index) { - return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...); - } -}; - -constexpr std::size_t integral_pow(std::size_t base, std::size_t power) { - return power == 0 ? 1 : base * integral_pow(base, power - 1); -} - -template <std::size_t End, std::size_t I = 0> -struct VisitTestBody { - template <class Vars, class State> - static bool Run(Vars& vars, State& state) { - if (state.KeepRunning()) { - absl::apply(VisitorApplier(), vars[I]); - return VisitTestBody<End, I + 1>::Run(vars, state); - } - return false; - } -}; - -template <std::size_t End> -struct VisitTestBody<End, End> { - template <class Vars, class State> - static bool Run(Vars& /*vars*/, State& /*state*/) { - return true; - } -}; - -// Visit operations where branch prediction is likely to give a boost. -template <std::size_t NumIndices, std::size_t NumDimensions = 1> -void BM_RedundantVisit(benchmark::State& state) { - auto vars = - MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>:: - Run(static_cast<std::size_t>(state.range(0))); - - for (auto _ : state) { // NOLINT - benchmark::DoNotOptimize(vars); - absl::apply(VisitorApplier(), vars); - } -} - -// Visit operations where branch prediction is unlikely to give a boost. -template <std::size_t NumIndices, std::size_t NumDimensions = 1> -void BM_Visit(benchmark::State& state) { - constexpr std::size_t num_possibilities = - integral_pow(NumIndices, NumDimensions); - - using VariantTupleMaker = - MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>; - using Tuple = typename VariantTupleMaker::VariantTuple; - - Tuple vars[num_possibilities]; - for (std::size_t i = 0; i < num_possibilities; ++i) - vars[i] = VariantTupleMaker::Run(i); - - while (VisitTestBody<num_possibilities>::Run(vars, state)) { - } -} - -// Visitation -// Each visit is on a different variant with a different active alternative) - -// Unary visit -BENCHMARK_TEMPLATE(BM_Visit, 1); -BENCHMARK_TEMPLATE(BM_Visit, 2); -BENCHMARK_TEMPLATE(BM_Visit, 3); -BENCHMARK_TEMPLATE(BM_Visit, 4); -BENCHMARK_TEMPLATE(BM_Visit, 5); -BENCHMARK_TEMPLATE(BM_Visit, 6); -BENCHMARK_TEMPLATE(BM_Visit, 7); -BENCHMARK_TEMPLATE(BM_Visit, 8); -BENCHMARK_TEMPLATE(BM_Visit, 16); -BENCHMARK_TEMPLATE(BM_Visit, 32); -BENCHMARK_TEMPLATE(BM_Visit, 64); - -// Binary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 2); -BENCHMARK_TEMPLATE(BM_Visit, 2, 2); -BENCHMARK_TEMPLATE(BM_Visit, 3, 2); -BENCHMARK_TEMPLATE(BM_Visit, 4, 2); -BENCHMARK_TEMPLATE(BM_Visit, 5, 2); - -// Ternary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 3); -BENCHMARK_TEMPLATE(BM_Visit, 2, 3); -BENCHMARK_TEMPLATE(BM_Visit, 3, 3); - -// Quaternary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 4); -BENCHMARK_TEMPLATE(BM_Visit, 2, 4); - -// Redundant Visitation -// Each visit consistently has the same alternative active - -// Unary visit -BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7); - -// Binary visit -BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2) - ->DenseRange(0, integral_pow(2, 2) - 1); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2) - ->DenseRange(0, integral_pow(4, 2) - 1); - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc deleted file mode 100644 index 439c6e1df367..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc +++ /dev/null @@ -1,532 +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/types/variant.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::variant is an alias for std::variant and when -// exceptions are not enabled. -#if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS) - -#include <iostream> -#include <memory> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" -#include "absl/memory/memory.h" - -// See comment in absl/base/config.h -#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -using ::testing::MakeExceptionSafetyTester; -using ::testing::strong_guarantee; -using ::testing::TestNothrowOp; -using ::testing::TestThrowingCtor; - -using Thrower = testing::ThrowingValue<>; -using CopyNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowCopy>; -using MoveNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using ThrowingAlloc = testing::ThrowingAllocator<Thrower>; -using ThrowerVec = std::vector<Thrower, ThrowingAlloc>; -using ThrowingVariant = - absl::variant<Thrower, CopyNothrow, MoveNothrow, ThrowerVec>; - -struct ConversionException {}; - -template <class T> -struct ExceptionOnConversion { - operator T() const { // NOLINT - throw ConversionException(); - } -}; - -// Forces a variant into the valueless by exception state. -void ToValuelessByException(ThrowingVariant& v) { // NOLINT - try { - v.emplace<Thrower>(); - v.emplace<Thrower>(ExceptionOnConversion<Thrower>()); - } catch (const ConversionException&) { - // This space intentionally left blank. - } -} - -// Check that variant is still in a usable state after an exception is thrown. -testing::AssertionResult VariantInvariants(ThrowingVariant* v) { - using testing::AssertionFailure; - using testing::AssertionSuccess; - - // Try using the active alternative - if (absl::holds_alternative<Thrower>(*v)) { - auto& t = absl::get<Thrower>(*v); - t = Thrower{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "Thrower should be assigned -100"; - } - } else if (absl::holds_alternative<ThrowerVec>(*v)) { - auto& tv = absl::get<ThrowerVec>(*v); - tv.clear(); - tv.emplace_back(-100); - if (tv.size() != 1 || tv[0].Get() != -100) { - return AssertionFailure() << "ThrowerVec should be {Thrower{-100}}"; - } - } else if (absl::holds_alternative<CopyNothrow>(*v)) { - auto& t = absl::get<CopyNothrow>(*v); - t = CopyNothrow{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "CopyNothrow should be assigned -100"; - } - } else if (absl::holds_alternative<MoveNothrow>(*v)) { - auto& t = absl::get<MoveNothrow>(*v); - t = MoveNothrow{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "MoveNothrow should be assigned -100"; - } - } - - // Try making variant valueless_by_exception - if (!v->valueless_by_exception()) ToValuelessByException(*v); - if (!v->valueless_by_exception()) { - return AssertionFailure() << "Variant should be valueless_by_exception"; - } - try { - auto unused = absl::get<Thrower>(*v); - static_cast<void>(unused); - return AssertionFailure() << "Variant should not contain Thrower"; - } catch (const absl::bad_variant_access&) { - } catch (...) { - return AssertionFailure() << "Unexpected exception throw from absl::get"; - } - - // Try using the variant - v->emplace<Thrower>(100); - if (!absl::holds_alternative<Thrower>(*v) || - absl::get<Thrower>(*v) != Thrower(100)) { - return AssertionFailure() << "Variant should contain Thrower(100)"; - } - v->emplace<ThrowerVec>({Thrower(100)}); - if (!absl::holds_alternative<ThrowerVec>(*v) || - absl::get<ThrowerVec>(*v)[0] != Thrower(100)) { - return AssertionFailure() - << "Variant should contain ThrowerVec{Thrower(100)}"; - } - return AssertionSuccess(); -} - -template <typename... Args> -Thrower ExpectedThrower(Args&&... args) { - return Thrower(42, args...); -} - -ThrowerVec ExpectedThrowerVec() { return {Thrower(100), Thrower(200)}; } -ThrowingVariant ValuelessByException() { - ThrowingVariant v; - ToValuelessByException(v); - return v; -} -ThrowingVariant WithThrower() { return Thrower(39); } -ThrowingVariant WithThrowerVec() { - return ThrowerVec{Thrower(1), Thrower(2), Thrower(3)}; -} -ThrowingVariant WithCopyNoThrow() { return CopyNothrow(39); } -ThrowingVariant WithMoveNoThrow() { return MoveNothrow(39); } - -TEST(VariantExceptionSafetyTest, DefaultConstructor) { - TestThrowingCtor<ThrowingVariant>(); -} - -TEST(VariantExceptionSafetyTest, CopyConstructor) { - { - ThrowingVariant v(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(v); - } - { - ThrowingVariant v(ExpectedThrowerVec()); - TestThrowingCtor<ThrowingVariant>(v); - } - { - ThrowingVariant v(ValuelessByException()); - TestThrowingCtor<ThrowingVariant>(v); - } -} - -TEST(VariantExceptionSafetyTest, MoveConstructor) { - { - ThrowingVariant v(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } - { - ThrowingVariant v(ExpectedThrowerVec()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } - { - ThrowingVariant v(ValuelessByException()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } -} - -TEST(VariantExceptionSafetyTest, ValueConstructor) { - TestThrowingCtor<ThrowingVariant>(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, InPlaceTypeConstructor) { - TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<Thrower>{}, - ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<ThrowerVec>{}, - ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, InPlaceIndexConstructor) { - TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<0>{}, - ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<3>{}, - ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, CopyAssign) { - // variant& operator=(const variant& rhs); - // Let j be rhs.index() - { - // - neither *this nor rhs holds a value - const ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - // - *this holds a value but rhs does not - const ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - // - index() == j - { - const ThrowingVariant rhs(ExpectedThrower()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - { - const ThrowingVariant rhs(ExpectedThrowerVec()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrowerVec()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - // libstdc++ std::variant has bugs on copy assignment regarding exception - // safety. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - // index() != j - // if is_nothrow_copy_constructible_v<Tj> or - // !is_nothrow_move_constructible<Tj> is true, equivalent to - // emplace<j>(get<j>(rhs)) - { - // is_nothrow_copy_constructible_v<Tj> == true - // should not throw because emplace() invokes Tj's copy ctor - // which should not throw. - const ThrowingVariant rhs(CopyNothrow{}); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - // is_nothrow_copy_constructible<Tj> == false && - // is_nothrow_move_constructible<Tj> == false - // should provide basic guarantee because emplace() invokes Tj's copy ctor - // which may throw. - const ThrowingVariant rhs(ExpectedThrower()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - { - // is_nothrow_copy_constructible_v<Tj> == false && - // is_nothrow_move_constructible_v<Tj> == true - // should provide strong guarantee because it is equivalent to - // operator=(variant(rhs)) which creates a temporary then invoke the move - // ctor which shouldn't throw. - const ThrowingVariant rhs(MoveNothrow{}); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, strong_guarantee) - .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); - } -} - -TEST(VariantExceptionSafetyTest, MoveAssign) { - // variant& operator=(variant&& rhs); - // Let j be rhs.index() - { - // - neither *this nor rhs holds a value - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - { - // - *this holds a value but rhs does not - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - { - // - index() == j - // assign get<j>(std::move(rhs)) to the value contained in *this. - // If an exception is thrown during call to Tj's move assignment, the state - // of the contained value is as defined by the exception safety guarantee of - // Tj's move assignment; index() will be j. - ThrowingVariant rhs(ExpectedThrower()); - size_t j = rhs.index(); - // Since Thrower's move assignment has basic guarantee, so should variant's. - auto tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - }); - EXPECT_TRUE(tester - .WithContracts( - VariantInvariants, - [&](ThrowingVariant* lhs) { return lhs->index() == j; }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - { - // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06. - // The fix is targeted for gcc-9. - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 - // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614 -#if !(defined(ABSL_USES_STD_VARIANT) && \ - defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) - // - otherwise (index() != j), equivalent to - // emplace<j>(get<j>(std::move(rhs))) - // - If an exception is thrown during the call to Tj's move construction - // (with j being rhs.index()), the variant will hold no value. - ThrowingVariant rhs(CopyNothrow{}); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - })); -#endif // !(defined(ABSL_USES_STD_VARIANT) && - // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) - } -} - -TEST(VariantExceptionSafetyTest, ValueAssign) { - // template<class T> variant& operator=(T&& t); - // Let Tj be the type that is selected by overload resolution to be assigned. - { - // If *this holds a Tj, assigns std::forward<T>(t) to the value contained in - // *this. If an exception is thrown during the assignment of - // std::forward<T>(t) to the value contained in *this, the state of the - // contained value and t are as defined by the exception safety guarantee of - // the assignment expression; valueless_by_exception() will be false. - // Since Thrower's copy/move assignment has basic guarantee, so should - // variant's. - Thrower rhs = ExpectedThrower(); - // copy assign - auto copy_tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(copy_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); - // move assign - auto move_tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - }); - EXPECT_TRUE(move_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) - .Test()); - - EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test()); - } - // Otherwise (*this holds something else), if is_nothrow_constructible_v<Tj, - // T> || !is_nothrow_move_constructible_v<Tj> is true, equivalent to - // emplace<j>(std::forward<T>(t)). - // We simplify the test by letting T = `const Tj&` or `Tj&&`, so we can reuse - // the CopyNothrow and MoveNothrow types. - - // if is_nothrow_constructible_v<Tj, T> - // (i.e. is_nothrow_copy/move_constructible_v<Tj>) is true, emplace() just - // invokes the copy/move constructor and it should not throw. - { - const CopyNothrow rhs; - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - MoveNothrow rhs; - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - // if is_nothrow_constructible_v<Tj, T> == false && - // is_nothrow_move_constructible<Tj> == false - // emplace() invokes the copy/move constructor which may throw so it should - // provide basic guarantee and variant object might not hold a value. - { - Thrower rhs = ExpectedThrower(); - // copy - auto copy_tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(copy_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); - // move - auto move_tester = MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([](ThrowingVariant* lhs) { - *lhs = ExpectedThrower(testing::nothrow_ctor); - }); - EXPECT_TRUE(move_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test()); - } - // Otherwise (if is_nothrow_constructible_v<Tj, T> == false && - // is_nothrow_move_constructible<Tj> == true), - // equivalent to operator=(variant(std::forward<T>(t))) - // This should have strong guarantee because it creates a temporary variant - // and operator=(variant&&) invokes Tj's move ctor which doesn't throw. - // libstdc++ std::variant has bugs on conversion assignment regarding - // exception safety. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - { - MoveNothrow rhs; - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, strong_guarantee) - .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); - } -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -} - -TEST(VariantExceptionSafetyTest, Emplace) { - // If an exception during the initialization of the contained value, the - // variant might not hold a value. The standard requires emplace() to provide - // only basic guarantee. - { - Thrower args = ExpectedThrower(); - auto tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&args](ThrowingVariant* v) { - v->emplace<Thrower>(args); - }); - EXPECT_TRUE(tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* v) { - return v->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } -} - -TEST(VariantExceptionSafetyTest, Swap) { - // if both are valueless_by_exception(), no effect - { - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs.swap(rhs); })); - } - // if index() == rhs.index(), calls swap(get<i>(*this), get<i>(rhs)) - // where i is index(). - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - lhs->swap(copy); - })); - } - // Otherwise, exchanges the value of rhs and *this. The exception safety - // involves variant in moved-from state which is not specified in the - // standard, and since swap is 3-step it's impossible for it to provide a - // overall strong guarantee. So, we are only checking basic guarantee here. - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - lhs->swap(copy); - })); - } - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - copy.swap(*lhs); - })); - } -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) - -#endif // #if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/types/variant_test.cc b/third_party/abseil_cpp/absl/types/variant_test.cc deleted file mode 100644 index cf237334da02..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_test.cc +++ /dev/null @@ -1,2718 +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. - -// Unit tests for the variant template. The 'is' and 'IsEmpty' methods -// of variant are not explicitly tested because they are used repeatedly -// in building other tests. All other public variant methods should have -// explicit tests. - -#include "absl/types/variant.h" - -// This test is a no-op when absl::variant is an alias for std::variant. -#if !defined(ABSL_USES_STD_VARIANT) - -#include <algorithm> -#include <cstddef> -#include <functional> -#include <initializer_list> -#include <memory> -#include <ostream> -#include <queue> -#include <type_traits> -#include <unordered_set> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/port.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_THROW(expr, exception_t) - -#else - -#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_DEATH_IF_SUPPORTED(expr, text) - -#endif // ABSL_HAVE_EXCEPTIONS - -#define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...) \ - ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \ - "Bad variant access") - -struct Hashable {}; - -namespace std { -template <> -struct hash<Hashable> { - size_t operator()(const Hashable&); -}; -} // namespace std - -struct NonHashable {}; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -using ::testing::DoubleEq; -using ::testing::Pointee; -using ::testing::VariantWith; - -struct MoveCanThrow { - MoveCanThrow() : v(0) {} - MoveCanThrow(int v) : v(v) {} // NOLINT(runtime/explicit) - MoveCanThrow(const MoveCanThrow& other) : v(other.v) {} - MoveCanThrow& operator=(const MoveCanThrow& /*other*/) { return *this; } - int v; -}; - -bool operator==(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v == rhs.v; } -bool operator!=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v != rhs.v; } -bool operator<(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v < rhs.v; } -bool operator<=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v <= rhs.v; } -bool operator>=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v >= rhs.v; } -bool operator>(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v > rhs.v; } - -// This helper class allows us to determine if it was swapped with std::swap() -// or with its friend swap() function. -struct SpecialSwap { - explicit SpecialSwap(int i) : i(i) {} - friend void swap(SpecialSwap& a, SpecialSwap& b) { - a.special_swap = b.special_swap = true; - std::swap(a.i, b.i); - } - bool operator==(SpecialSwap other) const { return i == other.i; } - int i; - bool special_swap = false; -}; - -struct MoveOnlyWithListConstructor { - MoveOnlyWithListConstructor() = default; - explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/, - int value) - : value(value) {} - MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default; - MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) = - default; - - int value = 0; -}; - -#ifdef ABSL_HAVE_EXCEPTIONS - -struct ConversionException {}; - -template <class T> -struct ExceptionOnConversion { - operator T() const { // NOLINT(runtime/explicit) - throw ConversionException(); - } -}; - -// Forces a variant into the valueless by exception state. -template <class H, class... T> -void ToValuelessByException(absl::variant<H, T...>& v) { // NOLINT - try { - v.template emplace<0>(ExceptionOnConversion<H>()); - } catch (ConversionException& /*e*/) { - // This space intentionally left blank. - } -} - -#endif // ABSL_HAVE_EXCEPTIONS - -// An indexed sequence of distinct structures holding a single -// value of type T -template<typename T, size_t N> -struct ValueHolder { - explicit ValueHolder(const T& x) : value(x) {} - typedef T value_type; - value_type value; - static const size_t kIndex = N; -}; -template<typename T, size_t N> -const size_t ValueHolder<T, N>::kIndex; - -// The following three functions make ValueHolder compatible with -// EXPECT_EQ and EXPECT_NE -template<typename T, size_t N> -inline bool operator==(const ValueHolder<T, N>& left, - const ValueHolder<T, N>& right) { - return left.value == right.value; -} - -template<typename T, size_t N> -inline bool operator!=(const ValueHolder<T, N>& left, - const ValueHolder<T, N>& right) { - return left.value != right.value; -} - -template<typename T, size_t N> -inline std::ostream& operator<<( - std::ostream& stream, const ValueHolder<T, N>& object) { - return stream << object.value; -} - -// Makes a variant holding twelve uniquely typed T wrappers. -template<typename T> -struct VariantFactory { - typedef variant<ValueHolder<T, 1>, ValueHolder<T, 2>, ValueHolder<T, 3>, - ValueHolder<T, 4>> - Type; -}; - -// A typelist in 1:1 with VariantFactory, to use type driven unit tests. -typedef ::testing::Types<ValueHolder<size_t, 1>, ValueHolder<size_t, 2>, - ValueHolder<size_t, 3>, - ValueHolder<size_t, 4>> VariantTypes; - -// Increments the provided counter pointer in the destructor -struct IncrementInDtor { - explicit IncrementInDtor(int* counter) : counter(counter) {} - ~IncrementInDtor() { *counter += 1; } - int* counter; -}; - -struct IncrementInDtorCopyCanThrow { - explicit IncrementInDtorCopyCanThrow(int* counter) : counter(counter) {} - IncrementInDtorCopyCanThrow(IncrementInDtorCopyCanThrow&& other) noexcept = - default; - IncrementInDtorCopyCanThrow(const IncrementInDtorCopyCanThrow& other) - : counter(other.counter) {} - IncrementInDtorCopyCanThrow& operator=( - IncrementInDtorCopyCanThrow&&) noexcept = default; - IncrementInDtorCopyCanThrow& operator=( - IncrementInDtorCopyCanThrow const& other) { - counter = other.counter; - return *this; - } - ~IncrementInDtorCopyCanThrow() { *counter += 1; } - int* counter; -}; - -// This is defined so operator== for ValueHolder<IncrementInDtor> will -// return true if two IncrementInDtor objects increment the same -// counter -inline bool operator==(const IncrementInDtor& left, - const IncrementInDtor& right) { - return left.counter == right.counter; -} - -// This is defined so EXPECT_EQ can work with IncrementInDtor -inline std::ostream& operator<<( - std::ostream& stream, const IncrementInDtor& object) { - return stream << object.counter; -} - -// A class that can be copied, but not assigned. -class CopyNoAssign { - public: - explicit CopyNoAssign(int value) : foo(value) {} - CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} - int foo; - private: - const CopyNoAssign& operator=(const CopyNoAssign&); -}; - -// A class that can neither be copied nor assigned. We provide -// overloads for the constructor with up to four parameters so we can -// test the overloads of variant::emplace. -class NonCopyable { - public: - NonCopyable() - : value(0) {} - explicit NonCopyable(int value1) - : value(value1) {} - - NonCopyable(int value1, int value2) - : value(value1 + value2) {} - - NonCopyable(int value1, int value2, int value3) - : value(value1 + value2 + value3) {} - - NonCopyable(int value1, int value2, int value3, int value4) - : value(value1 + value2 + value3 + value4) {} - NonCopyable(const NonCopyable&) = delete; - NonCopyable& operator=(const NonCopyable&) = delete; - int value; -}; - -// A typed test and typed test case over the VariantTypes typelist, -// from which we derive a number of tests that will execute for one of -// each type. -template <typename T> -class VariantTypesTest : public ::testing::Test {}; -TYPED_TEST_SUITE(VariantTypesTest, VariantTypes); - -//////////////////// -// [variant.ctor] // -//////////////////// - -struct NonNoexceptDefaultConstructible { - NonNoexceptDefaultConstructible() {} - int value = 5; -}; - -struct NonDefaultConstructible { - NonDefaultConstructible() = delete; -}; - -TEST(VariantTest, TestDefaultConstructor) { - { - using X = variant<int>; - constexpr variant<int> x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(0, absl::get<0>(x)); - EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<NonNoexceptDefaultConstructible>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(5, absl::get<0>(x).value); - EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<int, NonNoexceptDefaultConstructible>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(0, absl::get<0>(x)); - EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<NonNoexceptDefaultConstructible, int>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(5, absl::get<0>(x).value); - EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value); - } - EXPECT_FALSE( - std::is_default_constructible<variant<NonDefaultConstructible>>::value); - EXPECT_FALSE((std::is_default_constructible< - variant<NonDefaultConstructible, int>>::value)); - EXPECT_TRUE((std::is_default_constructible< - variant<int, NonDefaultConstructible>>::value)); -} - -// Test that for each slot, copy constructing a variant with that type -// produces a sensible object that correctly reports its type, and -// that copies the provided value. -TYPED_TEST(VariantTypesTest, TestCopyCtor) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - const TypeParam value(TypeParam::kIndex); - Variant original(value); - Variant copied(original); - EXPECT_TRUE(absl::holds_alternative<value_type1>(copied) || - TypeParam::kIndex != 1); - EXPECT_TRUE(absl::holds_alternative<value_type2>(copied) || - TypeParam::kIndex != 2); - EXPECT_TRUE(absl::holds_alternative<value_type3>(copied) || - TypeParam::kIndex != 3); - EXPECT_TRUE(absl::holds_alternative<value_type4>(copied) || - TypeParam::kIndex != 4); - EXPECT_TRUE((absl::get_if<value_type1>(&original) == - absl::get_if<value_type1>(&copied)) || - TypeParam::kIndex == 1); - EXPECT_TRUE((absl::get_if<value_type2>(&original) == - absl::get_if<value_type2>(&copied)) || - TypeParam::kIndex == 2); - EXPECT_TRUE((absl::get_if<value_type3>(&original) == - absl::get_if<value_type3>(&copied)) || - TypeParam::kIndex == 3); - EXPECT_TRUE((absl::get_if<value_type4>(&original) == - absl::get_if<value_type4>(&copied)) || - TypeParam::kIndex == 4); - EXPECT_TRUE((absl::get_if<value_type1>(&original) == - absl::get_if<value_type1>(&copied)) || - TypeParam::kIndex == 1); - EXPECT_TRUE((absl::get_if<value_type2>(&original) == - absl::get_if<value_type2>(&copied)) || - TypeParam::kIndex == 2); - EXPECT_TRUE((absl::get_if<value_type3>(&original) == - absl::get_if<value_type3>(&copied)) || - TypeParam::kIndex == 3); - EXPECT_TRUE((absl::get_if<value_type4>(&original) == - absl::get_if<value_type4>(&copied)) || - TypeParam::kIndex == 4); - const TypeParam* ovalptr = absl::get_if<TypeParam>(&original); - const TypeParam* cvalptr = absl::get_if<TypeParam>(&copied); - ASSERT_TRUE(ovalptr != nullptr); - ASSERT_TRUE(cvalptr != nullptr); - EXPECT_EQ(*ovalptr, *cvalptr); - TypeParam* mutable_ovalptr = absl::get_if<TypeParam>(&original); - TypeParam* mutable_cvalptr = absl::get_if<TypeParam>(&copied); - ASSERT_TRUE(mutable_ovalptr != nullptr); - ASSERT_TRUE(mutable_cvalptr != nullptr); - EXPECT_EQ(*mutable_ovalptr, *mutable_cvalptr); -} - -template <class> -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int value) : value(value) {} - MoveOnly(MoveOnly&&) = default; - MoveOnly& operator=(MoveOnly&&) = default; - int value = 5; -}; - -TEST(VariantTest, TestMoveConstruct) { - using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>; - - V v(in_place_index<1>, 10); - V v2 = absl::move(v); - EXPECT_EQ(10, absl::get<1>(v2).value); -} - -// Used internally to emulate missing triviality traits for tests. -template <class T> -union SingleUnion { - T member; -}; - -// NOTE: These don't work with types that can't be union members. -// They are just for testing. -template <class T> -struct is_trivially_move_constructible - : std::is_move_constructible<SingleUnion<T>>::type {}; - -template <class T> -struct is_trivially_move_assignable - : absl::is_move_assignable<SingleUnion<T>>::type {}; - -TEST(VariantTest, NothrowMoveConstructible) { - // Verify that variant is nothrow move constructible iff its template - // arguments are. - using U = std::unique_ptr<int>; - struct E { - E(E&&) {} - }; - static_assert(std::is_nothrow_move_constructible<variant<U>>::value, ""); - static_assert(std::is_nothrow_move_constructible<variant<U, int>>::value, ""); - static_assert(!std::is_nothrow_move_constructible<variant<U, E>>::value, ""); -} - -// Test that for each slot, constructing a variant with that type -// produces a sensible object that correctly reports its type, and -// that copies the provided value. -TYPED_TEST(VariantTypesTest, TestValueCtor) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - const TypeParam value(TypeParam::kIndex); - Variant v(value); - EXPECT_TRUE(absl::holds_alternative<value_type1>(v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(absl::holds_alternative<value_type2>(v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(absl::holds_alternative<value_type3>(v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(absl::holds_alternative<value_type4>(v) || - TypeParam::kIndex != 4); - EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) || - TypeParam::kIndex != 4); - EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) || - TypeParam::kIndex != 4); - const TypeParam* valptr = absl::get_if<TypeParam>(&v); - ASSERT_TRUE(nullptr != valptr); - EXPECT_EQ(value.value, valptr->value); - const TypeParam* mutable_valptr = absl::get_if<TypeParam>(&v); - ASSERT_TRUE(nullptr != mutable_valptr); - EXPECT_EQ(value.value, mutable_valptr->value); -} - -TEST(VariantTest, AmbiguousValueConstructor) { - EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value)); - EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value)); -} - -TEST(VariantTest, InPlaceType) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_type_t<int>(), 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_type_t<std::string>(), "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_type_t<std::string>(), "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_type_t<NonCopyable>{}); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - Var v5(in_place_type_t<std::vector<int>>(), {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceTypeVariableTemplate) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_type<int>, 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_type<std::string>, "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_type<std::string>, "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_type<NonCopyable>); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - Var v5(in_place_type<std::vector<int>>, {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceTypeInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_type<MoveOnlyWithListConstructor>, {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceIndex) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_index_t<0>(), 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_index_t<1>(), "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_index_t<1>(), "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_index_t<2>{}); - EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - // Verify that a variant with only non-copyables can still be constructed. - EXPECT_TRUE(absl::holds_alternative<NonCopyable>( - variant<NonCopyable>(in_place_index_t<0>{}))); - - Var v5(in_place_index_t<3>(), {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceIndexVariableTemplate) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_index<0>, 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_index<1>, "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_index<1>, "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_index<2>); - EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - // Verify that a variant with only non-copyables can still be constructed. - EXPECT_TRUE(absl::holds_alternative<NonCopyable>( - variant<NonCopyable>(in_place_index<0>))); - - Var v5(in_place_index<3>, {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceIndexInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -//////////////////// -// [variant.dtor] // -//////////////////// - -// Make sure that the destructor destroys the contained value -TEST(VariantTest, TestDtor) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - EXPECT_EQ(0, counter); - - value_type1 value1(counter_adjuster); - { Variant object(value1); } - EXPECT_EQ(1, counter); - - value_type2 value2(counter_adjuster); - { Variant object(value2); } - EXPECT_EQ(2, counter); - - value_type3 value3(counter_adjuster); - { Variant object(value3); } - EXPECT_EQ(3, counter); - - value_type4 value4(counter_adjuster); - { Variant object(value4); } - EXPECT_EQ(4, counter); -} - -#ifdef ABSL_HAVE_EXCEPTIONS - -// See comment in absl/base/config.h -#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) -TEST(VariantTest, DISABLED_TestDtorValuelessByException) -#else -// Test destruction when in the valueless_by_exception state. -TEST(VariantTest, TestDtorValuelessByException) -#endif -{ - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - - { - using Variant = VariantFactory<IncrementInDtor>::Type; - - Variant v(in_place_index<0>, counter_adjuster); - EXPECT_EQ(0, counter); - - ToValuelessByException(v); - ASSERT_TRUE(v.valueless_by_exception()); - EXPECT_EQ(1, counter); - } - EXPECT_EQ(1, counter); -} - -#endif // ABSL_HAVE_EXCEPTIONS - -////////////////////// -// [variant.assign] // -////////////////////// - -// Test that self-assignment doesn't destroy the current value -TEST(VariantTest, TestSelfAssignment) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - absl::variant_alternative_t<0, Variant> value(counter_adjuster); - Variant object(value); - object.operator=(object); - EXPECT_EQ(0, counter); - - // A string long enough that it's likely to defeat any inline representation - // optimization. - const std::string long_str(128, 'a'); - - std::string foo = long_str; - foo = *&foo; - EXPECT_EQ(long_str, foo); - - variant<int, std::string> so = long_str; - ASSERT_EQ(1, so.index()); - EXPECT_EQ(long_str, absl::get<1>(so)); - so = *&so; - - ASSERT_EQ(1, so.index()); - EXPECT_EQ(long_str, absl::get<1>(so)); -} - -// Test that assigning a variant<..., T, ...> to a variant<..., T, ...> produces -// a variant<..., T, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValueSameTypes) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - const TypeParam value(TypeParam::kIndex); - const Variant source(value); - Variant target(TypeParam(value.value + 1)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - ASSERT_NE(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); - target = source; - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); -} - -// Test that assisnging a variant<..., T, ...> to a variant<1, ...> -// produces a variant<..., T, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingSourceType) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - const TypeParam value(TypeParam::kIndex); - const Variant source(value); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - Variant target(value_type1(1)); - ASSERT_TRUE(absl::holds_alternative<value_type1>(target)); - target = source; - EXPECT_TRUE(absl::holds_alternative<TypeParam>(source)); - EXPECT_TRUE(absl::holds_alternative<TypeParam>(target)); - EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); -} - -// Test that assigning a variant<1, ...> to a variant<..., T, ...> -// produces a variant<1, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingTargetType) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - const Variant source(value_type1(1)); - ASSERT_TRUE(absl::holds_alternative<value_type1>(source)); - const TypeParam value(TypeParam::kIndex); - Variant target(value); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - target = source; - EXPECT_TRUE(absl::holds_alternative<value_type1>(target)); - EXPECT_TRUE(absl::holds_alternative<value_type1>(source)); - EXPECT_EQ(absl::get<value_type1>(source), absl::get<value_type1>(target)); -} - -// Test that operator=<T> works, that assigning a new value destroys -// the old and that assigning the new value again does not redestroy -// the old -TEST(VariantTest, TestAssign) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - - const int kSize = 4; - int counter[kSize]; - std::unique_ptr<IncrementInDtor> counter_adjustor[kSize]; - for (int i = 0; i != kSize; i++) { - counter[i] = 0; - counter_adjustor[i] = absl::make_unique<IncrementInDtor>(&counter[i]); - } - - value_type1 v1(*counter_adjustor[0]); - value_type2 v2(*counter_adjustor[1]); - value_type3 v3(*counter_adjustor[2]); - value_type4 v4(*counter_adjustor[3]); - - // Test that reassignment causes destruction of old value - { - Variant object(v1); - object = v2; - object = v3; - object = v4; - object = v1; - } - - EXPECT_EQ(2, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); - - std::fill(std::begin(counter), std::end(counter), 0); - - // Test that self-assignment does not cause destruction of old value - { - Variant object(v1); - object.operator=(object); - EXPECT_EQ(0, counter[0]); - } - { - Variant object(v2); - object.operator=(object); - EXPECT_EQ(0, counter[1]); - } - { - Variant object(v3); - object.operator=(object); - EXPECT_EQ(0, counter[2]); - } - { - Variant object(v4); - object.operator=(object); - EXPECT_EQ(0, counter[3]); - } - - EXPECT_EQ(1, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); -} - -// This tests that we perform a backup if the copy-assign can throw but the move -// cannot throw. -TEST(VariantTest, TestBackupAssign) { - typedef VariantFactory<IncrementInDtorCopyCanThrow>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - - const int kSize = 4; - int counter[kSize]; - std::unique_ptr<IncrementInDtorCopyCanThrow> counter_adjustor[kSize]; - for (int i = 0; i != kSize; i++) { - counter[i] = 0; - counter_adjustor[i].reset(new IncrementInDtorCopyCanThrow(&counter[i])); - } - - value_type1 v1(*counter_adjustor[0]); - value_type2 v2(*counter_adjustor[1]); - value_type3 v3(*counter_adjustor[2]); - value_type4 v4(*counter_adjustor[3]); - - // Test that reassignment causes destruction of old value - { - Variant object(v1); - object = v2; - object = v3; - object = v4; - object = v1; - } - - // libstdc++ doesn't pass this test -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - EXPECT_EQ(3, counter[0]); - EXPECT_EQ(2, counter[1]); - EXPECT_EQ(2, counter[2]); - EXPECT_EQ(2, counter[3]); -#endif - - std::fill(std::begin(counter), std::end(counter), 0); - - // Test that self-assignment does not cause destruction of old value - { - Variant object(v1); - object.operator=(object); - EXPECT_EQ(0, counter[0]); - } - { - Variant object(v2); - object.operator=(object); - EXPECT_EQ(0, counter[1]); - } - { - Variant object(v3); - object.operator=(object); - EXPECT_EQ(0, counter[2]); - } - { - Variant object(v4); - object.operator=(object); - EXPECT_EQ(0, counter[3]); - } - - EXPECT_EQ(1, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); -} - -/////////////////// -// [variant.mod] // -/////////////////// - -TEST(VariantTest, TestEmplaceBasic) { - using Variant = variant<int, char>; - - Variant v(absl::in_place_index<0>, 0); - - { - char& emplace_result = v.emplace<char>(); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<char>(v)); - } - - // Make sure that another emplace does zero-initialization - absl::get<char>(v) = 'a'; - v.emplace<char>('b'); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 'b'); - - { - int& emplace_result = v.emplace<int>(); - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(absl::get<int>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<int>(v)); - } -} - -TEST(VariantTest, TestEmplaceInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(absl::in_place_index<0>, 555); - MoveOnlyWithListConstructor& emplace_result = - v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); - EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1)); -} - -TEST(VariantTest, TestEmplaceIndex) { - using Variant = variant<int, char>; - - Variant v(absl::in_place_index<0>, 555); - - { - char& emplace_result = v.emplace<1>(); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<char>(v)); - } - - // Make sure that another emplace does zero-initialization - absl::get<char>(v) = 'a'; - v.emplace<1>('b'); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 'b'); - - { - int& emplace_result = v.emplace<0>(); - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(absl::get<int>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<int>(v)); - } -} - -TEST(VariantTest, TestEmplaceIndexInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(absl::in_place_index<0>, 555); - MoveOnlyWithListConstructor& emplace_result = - v1.emplace<3>({1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); - EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1)); -} - -////////////////////// -// [variant.status] // -////////////////////// - -TEST(VariantTest, Index) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_EQ(0, v.index()); - v = "str"; - EXPECT_EQ(1, v.index()); - v = 0.; - EXPECT_EQ(2, v.index()); - - Var v2 = v; - EXPECT_EQ(2, v2.index()); - v2.emplace<int>(3); - EXPECT_EQ(0, v2.index()); -} - -TEST(VariantTest, NotValuelessByException) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_FALSE(v.valueless_by_exception()); - v = "str"; - EXPECT_FALSE(v.valueless_by_exception()); - v = 0.; - EXPECT_FALSE(v.valueless_by_exception()); - - Var v2 = v; - EXPECT_FALSE(v.valueless_by_exception()); - v2.emplace<int>(3); - EXPECT_FALSE(v.valueless_by_exception()); -} - -#ifdef ABSL_HAVE_EXCEPTIONS - -TEST(VariantTest, IndexValuelessByException) { - using Var = variant<MoveCanThrow, std::string, double>; - - Var v(absl::in_place_index<0>); - EXPECT_EQ(0, v.index()); - ToValuelessByException(v); - EXPECT_EQ(absl::variant_npos, v.index()); - v = "str"; - EXPECT_EQ(1, v.index()); -} - -TEST(VariantTest, ValuelessByException) { - using Var = variant<MoveCanThrow, std::string, double>; - - Var v(absl::in_place_index<0>); - EXPECT_FALSE(v.valueless_by_exception()); - ToValuelessByException(v); - EXPECT_TRUE(v.valueless_by_exception()); - v = "str"; - EXPECT_FALSE(v.valueless_by_exception()); -} - -#endif // ABSL_HAVE_EXCEPTIONS - -//////////////////// -// [variant.swap] // -//////////////////// - -TEST(VariantTest, MemberSwap) { - SpecialSwap v1(3); - SpecialSwap v2(7); - - variant<SpecialSwap> a = v1, b = v2; - - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - - a.swap(b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v2)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v1)); - EXPECT_TRUE(absl::get<SpecialSwap>(a).special_swap); - - using V = variant<MoveCanThrow, std::string, int>; - int i = 33; - std::string s = "abc"; - { - // lhs and rhs holds different alternative - V lhs(i), rhs(s); - lhs.swap(rhs); - EXPECT_THAT(lhs, VariantWith<std::string>(s)); - EXPECT_THAT(rhs, VariantWith<int>(i)); - } -#ifdef ABSL_HAVE_EXCEPTIONS - V valueless(in_place_index<0>); - ToValuelessByException(valueless); - { - // lhs is valueless - V lhs(valueless), rhs(i); - lhs.swap(rhs); - EXPECT_THAT(lhs, VariantWith<int>(i)); - EXPECT_TRUE(rhs.valueless_by_exception()); - } - { - // rhs is valueless - V lhs(s), rhs(valueless); - lhs.swap(rhs); - EXPECT_THAT(rhs, VariantWith<std::string>(s)); - EXPECT_TRUE(lhs.valueless_by_exception()); - } - { - // both are valueless - V lhs(valueless), rhs(valueless); - lhs.swap(rhs); - EXPECT_TRUE(lhs.valueless_by_exception()); - EXPECT_TRUE(rhs.valueless_by_exception()); - } -#endif // ABSL_HAVE_EXCEPTIONS -} - -////////////////////// -// [variant.helper] // -////////////////////// - -TEST(VariantTest, VariantSize) { - { - using Size1Variant = absl::variant<int>; - EXPECT_EQ(1, absl::variant_size<Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<const Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<volatile Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<const volatile Size1Variant>::value); - } - - { - using Size3Variant = absl::variant<int, float, int>; - EXPECT_EQ(3, absl::variant_size<Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<const Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<volatile Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<const volatile Size3Variant>::value); - } -} - -TEST(VariantTest, VariantAlternative) { - { - using V = absl::variant<float, int, const char*>; - EXPECT_TRUE( - (std::is_same<float, absl::variant_alternative_t<0, V>>::value)); - EXPECT_TRUE((std::is_same<const float, - absl::variant_alternative_t<0, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile float, - absl::variant_alternative_t<0, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile float, - absl::variant_alternative_t<0, const volatile V>>::value)); - - EXPECT_TRUE((std::is_same<int, absl::variant_alternative_t<1, V>>::value)); - EXPECT_TRUE((std::is_same<const int, - absl::variant_alternative_t<1, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile int, - absl::variant_alternative_t<1, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile int, - absl::variant_alternative_t<1, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value)); - EXPECT_TRUE((std::is_same<const char* const, - absl::variant_alternative_t<2, const V>>::value)); - EXPECT_TRUE( - (std::is_same<const char* volatile, - absl::variant_alternative_t<2, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const char* const volatile, - absl::variant_alternative_t<2, const volatile V>>::value)); - } - - { - using V = absl::variant<float, volatile int, const char*>; - EXPECT_TRUE( - (std::is_same<float, absl::variant_alternative_t<0, V>>::value)); - EXPECT_TRUE((std::is_same<const float, - absl::variant_alternative_t<0, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile float, - absl::variant_alternative_t<0, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile float, - absl::variant_alternative_t<0, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<volatile int, absl::variant_alternative_t<1, V>>::value)); - EXPECT_TRUE((std::is_same<const volatile int, - absl::variant_alternative_t<1, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile int, - absl::variant_alternative_t<1, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile int, - absl::variant_alternative_t<1, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value)); - EXPECT_TRUE((std::is_same<const char* const, - absl::variant_alternative_t<2, const V>>::value)); - EXPECT_TRUE( - (std::is_same<const char* volatile, - absl::variant_alternative_t<2, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const char* const volatile, - absl::variant_alternative_t<2, const volatile V>>::value)); - } -} - -/////////////////// -// [variant.get] // -/////////////////// - -TEST(VariantTest, HoldsAlternative) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v)); - EXPECT_FALSE(absl::holds_alternative<double>(v)); - v = "str"; - EXPECT_FALSE(absl::holds_alternative<int>(v)); - EXPECT_TRUE(absl::holds_alternative<std::string>(v)); - EXPECT_FALSE(absl::holds_alternative<double>(v)); - v = 0.; - EXPECT_FALSE(absl::holds_alternative<int>(v)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v)); - EXPECT_TRUE(absl::holds_alternative<double>(v)); - - Var v2 = v; - EXPECT_FALSE(absl::holds_alternative<int>(v2)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v2)); - EXPECT_TRUE(absl::holds_alternative<double>(v2)); - v2.emplace<int>(3); - EXPECT_TRUE(absl::holds_alternative<int>(v2)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v2)); - EXPECT_FALSE(absl::holds_alternative<double>(v2)); -} - -TEST(VariantTest, GetIndex) { - using Var = variant<int, std::string, double, int>; - - { - Var v(absl::in_place_index<0>, 0); - - using LValueGetType = decltype(absl::get<0>(v)); - using RValueGetType = decltype(absl::get<0>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<0>(v), 0); - EXPECT_EQ(absl::get<0>(absl::move(v)), 0); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<0>(const_v)); - using ConstRValueGetType = decltype(absl::get<0>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<0>(const_v), 0); - EXPECT_EQ(absl::get<0>(absl::move(const_v)), 0); - } - - { - Var v = std::string("Hello"); - - using LValueGetType = decltype(absl::get<1>(v)); - using RValueGetType = decltype(absl::get<1>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value)); - EXPECT_EQ(absl::get<1>(v), "Hello"); - EXPECT_EQ(absl::get<1>(absl::move(v)), "Hello"); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<1>(const_v)); - using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value)); - EXPECT_EQ(absl::get<1>(const_v), "Hello"); - EXPECT_EQ(absl::get<1>(absl::move(const_v)), "Hello"); - } - - { - Var v = 2.0; - - using LValueGetType = decltype(absl::get<2>(v)); - using RValueGetType = decltype(absl::get<2>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, double&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value)); - EXPECT_EQ(absl::get<2>(v), 2.); - EXPECT_EQ(absl::get<2>(absl::move(v)), 2.); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<2>(const_v)); - using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value)); - EXPECT_EQ(absl::get<2>(const_v), 2.); - EXPECT_EQ(absl::get<2>(absl::move(const_v)), 2.); - } - - { - Var v(absl::in_place_index<0>, 0); - v.emplace<3>(1); - - using LValueGetType = decltype(absl::get<3>(v)); - using RValueGetType = decltype(absl::get<3>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<3>(v), 1); - EXPECT_EQ(absl::get<3>(absl::move(v)), 1); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<3>(const_v)); - using ConstRValueGetType = decltype(absl::get<3>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<3>(const_v), 1); - EXPECT_EQ(absl::get<3>(absl::move(const_v)), 1); // NOLINT - } -} - -TEST(VariantTest, BadGetIndex) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<1>(std::move(const_v))); // NOLINT - } - - { - Var v = std::string("Hello"); - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<0>(std::move(const_v))); // NOLINT - } -} - -TEST(VariantTest, GetType) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - using LValueGetType = decltype(absl::get<int>(v)); - using RValueGetType = decltype(absl::get<int>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<int>(v), 1); - EXPECT_EQ(absl::get<int>(absl::move(v)), 1); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<int>(const_v)); - using ConstRValueGetType = decltype(absl::get<int>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<int>(const_v), 1); - EXPECT_EQ(absl::get<int>(absl::move(const_v)), 1); - } - - { - Var v = std::string("Hello"); - - using LValueGetType = decltype(absl::get<1>(v)); - using RValueGetType = decltype(absl::get<1>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value)); - EXPECT_EQ(absl::get<std::string>(v), "Hello"); - EXPECT_EQ(absl::get<std::string>(absl::move(v)), "Hello"); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<1>(const_v)); - using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value)); - EXPECT_EQ(absl::get<std::string>(const_v), "Hello"); - EXPECT_EQ(absl::get<std::string>(absl::move(const_v)), "Hello"); - } - - { - Var v = 2.0; - - using LValueGetType = decltype(absl::get<2>(v)); - using RValueGetType = decltype(absl::get<2>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, double&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value)); - EXPECT_EQ(absl::get<double>(v), 2.); - EXPECT_EQ(absl::get<double>(absl::move(v)), 2.); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<2>(const_v)); - using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value)); - EXPECT_EQ(absl::get<double>(const_v), 2.); - EXPECT_EQ(absl::get<double>(absl::move(const_v)), 2.); - } -} - -TEST(VariantTest, BadGetType) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(std::move(const_v))); // NOLINT - } - - { - Var v = std::string("Hello"); - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<int>(std::move(const_v))); // NOLINT - } -} - -TEST(VariantTest, GetIfIndex) { - using Var = variant<int, std::string, double, int>; - - { - Var v(absl::in_place_index<0>, 0); - EXPECT_TRUE(noexcept(absl::get_if<0>(&v))); - - { - auto* elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 0); - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<0>(&const_v))); - - { - auto* elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 0); - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v = std::string("Hello"); - EXPECT_TRUE(noexcept(absl::get_if<1>(&v))); - - { - auto* elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), std::string*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, "Hello"); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<1>(&const_v))); - - { - auto* elem = absl::get_if<1>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const std::string*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, "Hello"); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v = 2.0; - EXPECT_TRUE(noexcept(absl::get_if<2>(&v))); - - { - auto* elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), double*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 2.0); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<2>(&const_v))); - - { - auto* elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const double*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 2.0); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v(absl::in_place_index<0>, 0); - v.emplace<3>(1); - EXPECT_TRUE(noexcept(absl::get_if<3>(&v))); - - { - auto* elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 1); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<3>(&const_v))); - - { - auto* elem = absl::get_if<3>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 1); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - } - } - } -} - -////////////////////// -// [variant.relops] // -////////////////////// - -TEST(VariantTest, OperatorEquals) { - variant<int, std::string> a(1), b(1); - EXPECT_TRUE(a == b); - EXPECT_TRUE(b == a); - EXPECT_FALSE(a != b); - EXPECT_FALSE(b != a); - - b = "str"; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); - - b = 0; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); - - a = b = "foo"; - EXPECT_TRUE(a == b); - EXPECT_TRUE(b == a); - EXPECT_FALSE(a != b); - EXPECT_FALSE(b != a); - - a = "bar"; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); -} - -TEST(VariantTest, OperatorRelational) { - variant<int, std::string> a(1), b(1); - EXPECT_FALSE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_FALSE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_TRUE(b >= a); - - b = "str"; - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_TRUE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); - EXPECT_FALSE(a >= b); - EXPECT_TRUE(b >= a); - - b = 0; - EXPECT_FALSE(a < b); - EXPECT_TRUE(b < a); - EXPECT_TRUE(a > b); - EXPECT_FALSE(b > a); - EXPECT_FALSE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_FALSE(b >= a); - - a = b = "foo"; - EXPECT_FALSE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_FALSE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_TRUE(b >= a); - - a = "bar"; - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_TRUE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); - EXPECT_FALSE(a >= b); - EXPECT_TRUE(b >= a); -} - -#ifdef ABSL_HAVE_EXCEPTIONS - -TEST(VariantTest, ValuelessOperatorEquals) { - variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"), - valueless(absl::in_place_index<0>), - other_valueless(absl::in_place_index<0>); - ToValuelessByException(valueless); - ToValuelessByException(other_valueless); - - EXPECT_TRUE(valueless == other_valueless); - EXPECT_TRUE(other_valueless == valueless); - EXPECT_FALSE(valueless == int_v); - EXPECT_FALSE(valueless == string_v); - EXPECT_FALSE(int_v == valueless); - EXPECT_FALSE(string_v == valueless); - - EXPECT_FALSE(valueless != other_valueless); - EXPECT_FALSE(other_valueless != valueless); - EXPECT_TRUE(valueless != int_v); - EXPECT_TRUE(valueless != string_v); - EXPECT_TRUE(int_v != valueless); - EXPECT_TRUE(string_v != valueless); -} - -TEST(VariantTest, ValuelessOperatorRelational) { - variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"), - valueless(absl::in_place_index<0>), - other_valueless(absl::in_place_index<0>); - ToValuelessByException(valueless); - ToValuelessByException(other_valueless); - - EXPECT_FALSE(valueless < other_valueless); - EXPECT_FALSE(other_valueless < valueless); - EXPECT_TRUE(valueless < int_v); - EXPECT_TRUE(valueless < string_v); - EXPECT_FALSE(int_v < valueless); - EXPECT_FALSE(string_v < valueless); - - EXPECT_TRUE(valueless <= other_valueless); - EXPECT_TRUE(other_valueless <= valueless); - EXPECT_TRUE(valueless <= int_v); - EXPECT_TRUE(valueless <= string_v); - EXPECT_FALSE(int_v <= valueless); - EXPECT_FALSE(string_v <= valueless); - - EXPECT_TRUE(valueless >= other_valueless); - EXPECT_TRUE(other_valueless >= valueless); - EXPECT_FALSE(valueless >= int_v); - EXPECT_FALSE(valueless >= string_v); - EXPECT_TRUE(int_v >= valueless); - EXPECT_TRUE(string_v >= valueless); - - EXPECT_FALSE(valueless > other_valueless); - EXPECT_FALSE(other_valueless > valueless); - EXPECT_FALSE(valueless > int_v); - EXPECT_FALSE(valueless > string_v); - EXPECT_TRUE(int_v > valueless); - EXPECT_TRUE(string_v > valueless); -} - -#endif - -///////////////////// -// [variant.visit] // -///////////////////// - -template <typename T> -struct ConvertTo { - template <typename U> - T operator()(const U& u) const { - return u; - } -}; - -TEST(VariantTest, VisitSimple) { - variant<std::string, const char*> v = "A"; - - std::string str = absl::visit(ConvertTo<std::string>{}, v); - EXPECT_EQ("A", str); - - v = std::string("B"); - - absl::string_view piece = absl::visit(ConvertTo<absl::string_view>{}, v); - EXPECT_EQ("B", piece); - - struct StrLen { - int operator()(const char* s) const { return strlen(s); } - int operator()(const std::string& s) const { return s.size(); } - }; - - v = "SomeStr"; - EXPECT_EQ(7, absl::visit(StrLen{}, v)); - v = std::string("VeryLargeThisTime"); - EXPECT_EQ(17, absl::visit(StrLen{}, v)); -} - -TEST(VariantTest, VisitRValue) { - variant<std::string> v = std::string("X"); - struct Visitor { - bool operator()(const std::string&) const { return false; } - bool operator()(std::string&&) const { return true; } // NOLINT - - int operator()(const std::string&, const std::string&) const { return 0; } - int operator()(const std::string&, std::string&&) const { - return 1; - } // NOLINT - int operator()(std::string&&, const std::string&) const { - return 2; - } // NOLINT - int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT - }; - EXPECT_FALSE(absl::visit(Visitor{}, v)); - EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v))); - - // Also test the variadic overload. - EXPECT_EQ(0, absl::visit(Visitor{}, v, v)); - EXPECT_EQ(1, absl::visit(Visitor{}, v, absl::move(v))); - EXPECT_EQ(2, absl::visit(Visitor{}, absl::move(v), v)); - EXPECT_EQ(3, absl::visit(Visitor{}, absl::move(v), absl::move(v))); -} - -TEST(VariantTest, VisitRValueVisitor) { - variant<std::string> v = std::string("X"); - struct Visitor { - bool operator()(const std::string&) const& { return false; } - bool operator()(const std::string&) && { return true; } - }; - Visitor visitor; - EXPECT_FALSE(absl::visit(visitor, v)); - EXPECT_TRUE(absl::visit(Visitor{}, v)); -} - -TEST(VariantTest, VisitResultTypeDifferent) { - variant<std::string> v = std::string("X"); - struct LValue_LValue {}; - struct RValue_LValue {}; - struct LValue_RValue {}; - struct RValue_RValue {}; - struct Visitor { - LValue_LValue operator()(const std::string&) const& { return {}; } - RValue_LValue operator()(std::string&&) const& { return {}; } // NOLINT - LValue_RValue operator()(const std::string&) && { return {}; } - RValue_RValue operator()(std::string&&) && { return {}; } // NOLINT - } visitor; - - EXPECT_TRUE( - (std::is_same<LValue_LValue, decltype(absl::visit(visitor, v))>::value)); - EXPECT_TRUE( - (std::is_same<RValue_LValue, - decltype(absl::visit(visitor, absl::move(v)))>::value)); - EXPECT_TRUE(( - std::is_same<LValue_RValue, decltype(absl::visit(Visitor{}, v))>::value)); - EXPECT_TRUE( - (std::is_same<RValue_RValue, - decltype(absl::visit(Visitor{}, absl::move(v)))>::value)); -} - -TEST(VariantTest, VisitVariadic) { - using A = variant<int, std::string>; - using B = variant<std::unique_ptr<int>, absl::string_view>; - - struct Visitor { - std::pair<int, int> operator()(int a, std::unique_ptr<int> b) const { - return {a, *b}; - } - std::pair<int, int> operator()(absl::string_view a, - std::unique_ptr<int> b) const { - return {static_cast<int>(a.size()), static_cast<int>(*b)}; - } - std::pair<int, int> operator()(int a, absl::string_view b) const { - return {a, static_cast<int>(b.size())}; - } - std::pair<int, int> operator()(absl::string_view a, - absl::string_view b) const { - return {static_cast<int>(a.size()), static_cast<int>(b.size())}; - } - }; - - EXPECT_THAT(absl::visit(Visitor(), A(1), B(std::unique_ptr<int>(new int(7)))), - ::testing::Pair(1, 7)); - EXPECT_THAT(absl::visit(Visitor(), A(1), B(absl::string_view("ABC"))), - ::testing::Pair(1, 3)); - EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")), - B(std::unique_ptr<int>(new int(7)))), - ::testing::Pair(5, 7)); - EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")), - B(absl::string_view("ABC"))), - ::testing::Pair(5, 3)); -} - -TEST(VariantTest, VisitNoArgs) { - EXPECT_EQ(5, absl::visit([] { return 5; })); -} - -struct ConstFunctor { - int operator()(int a, int b) const { return a - b; } -}; - -struct MutableFunctor { - int operator()(int a, int b) { return a - b; } -}; - -struct Class { - int Method(int a, int b) { return a - b; } - int ConstMethod(int a, int b) const { return a - b; } - - int member; -}; - -TEST(VariantTest, VisitReferenceWrapper) { - ConstFunctor cf; - MutableFunctor mf; - absl::variant<int> three = 3; - absl::variant<int> two = 2; - - EXPECT_EQ(1, absl::visit(std::cref(cf), three, two)); - EXPECT_EQ(1, absl::visit(std::ref(cf), three, two)); - EXPECT_EQ(1, absl::visit(std::ref(mf), three, two)); -} - -// libstdc++ std::variant doesn't support the INVOKE semantics. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -TEST(VariantTest, VisitMemberFunction) { - absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>()); - absl::variant<std::unique_ptr<const Class>> cp( - absl::make_unique<const Class>()); - absl::variant<int> three = 3; - absl::variant<int> two = 2; - - EXPECT_EQ(1, absl::visit(&Class::Method, p, three, two)); - EXPECT_EQ(1, absl::visit(&Class::ConstMethod, p, three, two)); - EXPECT_EQ(1, absl::visit(&Class::ConstMethod, cp, three, two)); -} - -TEST(VariantTest, VisitDataMember) { - absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>(Class{42})); - absl::variant<std::unique_ptr<const Class>> cp( - absl::make_unique<const Class>(Class{42})); - EXPECT_EQ(42, absl::visit(&Class::member, p)); - - absl::visit(&Class::member, p) = 5; - EXPECT_EQ(5, absl::visit(&Class::member, p)); - - EXPECT_EQ(42, absl::visit(&Class::member, cp)); -} -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - -///////////////////////// -// [variant.monostate] // -///////////////////////// - -TEST(VariantTest, MonostateBasic) { - absl::monostate mono; - (void)mono; - - // TODO(mattcalabrese) Expose move triviality metafunctions in absl. - EXPECT_TRUE(absl::is_trivially_default_constructible<absl::monostate>::value); - EXPECT_TRUE(is_trivially_move_constructible<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<absl::monostate>::value); - EXPECT_TRUE(is_trivially_move_assignable<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_destructible<absl::monostate>::value); -} - -TEST(VariantTest, VariantMonostateDefaultConstruction) { - absl::variant<absl::monostate, NonDefaultConstructible> var; - EXPECT_EQ(var.index(), 0); -} - -//////////////////////////////// -// [variant.monostate.relops] // -//////////////////////////////// - -TEST(VariantTest, MonostateComparisons) { - absl::monostate lhs, rhs; - - EXPECT_EQ(lhs, lhs); - EXPECT_EQ(lhs, rhs); - - EXPECT_FALSE(lhs != lhs); - EXPECT_FALSE(lhs != rhs); - EXPECT_FALSE(lhs < lhs); - EXPECT_FALSE(lhs < rhs); - EXPECT_FALSE(lhs > lhs); - EXPECT_FALSE(lhs > rhs); - - EXPECT_LE(lhs, lhs); - EXPECT_LE(lhs, rhs); - EXPECT_GE(lhs, lhs); - EXPECT_GE(lhs, rhs); - - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() == - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() != - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() < - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() > - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <= - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >= - std::declval<absl::monostate>())); -} - -/////////////////////// -// [variant.specalg] // -/////////////////////// - -TEST(VariantTest, NonmemberSwap) { - using std::swap; - - SpecialSwap v1(3); - SpecialSwap v2(7); - - variant<SpecialSwap> a = v1, b = v2; - - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - - std::swap(a, b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v2)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v1)); -#ifndef ABSL_USES_STD_VARIANT - EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap); -#endif - - swap(a, b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - EXPECT_TRUE(absl::get<SpecialSwap>(b).special_swap); -} - -////////////////////////// -// [variant.bad.access] // -////////////////////////// - -TEST(VariantTest, BadAccess) { - EXPECT_TRUE(noexcept(absl::bad_variant_access())); - absl::bad_variant_access exception_obj; - std::exception* base = &exception_obj; - (void)base; -} - -//////////////////// -// [variant.hash] // -//////////////////// - -TEST(VariantTest, MonostateHash) { - absl::monostate mono, other_mono; - std::hash<absl::monostate> const hasher{}; - static_assert(std::is_same<decltype(hasher(mono)), std::size_t>::value, ""); - EXPECT_EQ(hasher(mono), hasher(other_mono)); -} - -TEST(VariantTest, Hash) { - static_assert(type_traits_internal::IsHashable<variant<int>>::value, ""); - static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, ""); - static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value, - ""); - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value, - ""); - static_assert( - !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value, - ""); -#endif - -// MSVC std::hash<std::variant> does not use the index, thus produce the same -// result on the same value as different alternative. -#if !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT)) - { - // same value as different alternative - variant<int, int> v0(in_place_index<0>, 42); - variant<int, int> v1(in_place_index<1>, 42); - std::hash<variant<int, int>> hash; - EXPECT_NE(hash(v0), hash(v1)); - } -#endif // !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT)) - - { - std::hash<variant<int>> hash; - std::set<size_t> hashcodes; - for (int i = 0; i < 100; ++i) { - hashcodes.insert(hash(i)); - } - EXPECT_GT(hashcodes.size(), 90); - - // test const-qualified - static_assert(type_traits_internal::IsHashable<variant<const int>>::value, - ""); - static_assert( - type_traits_internal::IsHashable<variant<const Hashable>>::value, ""); - std::hash<absl::variant<const int>> c_hash; - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(hash(i), c_hash(i)); - } - } -} - -//////////////////////////////////////// -// Miscellaneous and deprecated tests // -//////////////////////////////////////// - -// Test that a set requiring a basic type conversion works correctly -#if !defined(ABSL_USES_STD_VARIANT) -TEST(VariantTest, TestConvertingSet) { - typedef variant<double> Variant; - Variant v(1.0); - const int two = 2; - v = two; - EXPECT_TRUE(absl::holds_alternative<double>(v)); - ASSERT_TRUE(nullptr != absl::get_if<double>(&v)); - EXPECT_DOUBLE_EQ(2, absl::get<double>(v)); -} -#endif // ABSL_USES_STD_VARIANT - -// Test that a vector of variants behaves reasonably. -TEST(VariantTest, Container) { - typedef variant<int, float> Variant; - - // Creation of vector should work - std::vector<Variant> vec; - vec.push_back(Variant(10)); - vec.push_back(Variant(20.0f)); - - // Vector resizing should work if we supply a value for new slots - vec.resize(10, Variant(0)); -} - -// Test that a variant with a non-copyable type can be constructed and -// manipulated to some degree. -TEST(VariantTest, TestVariantWithNonCopyableType) { - typedef variant<int, NonCopyable> Variant; - const int kValue = 1; - Variant v(kValue); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(kValue, absl::get<int>(v)); -} - -// Test that a variant with a non-copyable type can be transformed to -// the non-copyable type with a call to `emplace` for different numbers -// of arguments. We do not need to test this for each of T1 ... T8 -// because `emplace` does not overload on T1 ... to T8, so if this -// works for any one of T1 ... T8, then it works for all of them. We -// do need to test that it works with varying numbers of parameters -// though. -TEST(VariantTest, TestEmplace) { - typedef variant<int, NonCopyable> Variant; - const int kValue = 1; - Variant v(kValue); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(kValue, absl::get<int>(v)); - - // emplace with zero arguments, then back to 'int' - v.emplace<NonCopyable>(); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(0, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with one argument: - v.emplace<NonCopyable>(1); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(1, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with two arguments: - v.emplace<NonCopyable>(1, 2); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(3, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with three arguments - v.emplace<NonCopyable>(1, 2, 3); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(6, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with four arguments - v.emplace<NonCopyable>(1, 2, 3, 4); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(10, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); -} - -TEST(VariantTest, TestEmplaceDestroysCurrentValue) { - typedef variant<int, IncrementInDtor, NonCopyable> Variant; - int counter = 0; - Variant v(0); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - v.emplace<IncrementInDtor>(&counter); - ASSERT_TRUE(absl::holds_alternative<IncrementInDtor>(v)); - ASSERT_EQ(0, counter); - v.emplace<NonCopyable>(); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(1, counter); -} - -TEST(VariantTest, TestMoveSemantics) { - typedef variant<std::unique_ptr<int>, std::unique_ptr<std::string>> Variant; - - // Construct a variant by moving from an element value. - Variant v(absl::WrapUnique(new int(10))); - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v)); - - // Construct a variant by moving from another variant. - Variant v2(absl::move(v)); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v2)); - ASSERT_NE(nullptr, absl::get<std::unique_ptr<int>>(v2)); - EXPECT_EQ(10, *absl::get<std::unique_ptr<int>>(v2)); - - // Moving from a variant object leaves it holding moved-from value of the - // same element type. - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v)); - ASSERT_NE(nullptr, absl::get_if<std::unique_ptr<int>>(&v)); - EXPECT_EQ(nullptr, absl::get<std::unique_ptr<int>>(v)); - - // Assign a variant from an element value by move. - v = absl::make_unique<std::string>("foo"); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v)); - - // Move-assign a variant. - v2 = absl::move(v); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v2)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v2)); - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v)); -} - -variant<int, std::string> PassThrough(const variant<int, std::string>& arg) { - return arg; -} - -TEST(VariantTest, TestImplicitConversion) { - EXPECT_TRUE(absl::holds_alternative<int>(PassThrough(0))); - - // We still need the explicit cast for std::string, because C++ won't apply - // two user-defined implicit conversions in a row. - EXPECT_TRUE( - absl::holds_alternative<std::string>(PassThrough(std::string("foo")))); -} - -struct Convertible2; -struct Convertible1 { - Convertible1() {} - Convertible1(const Convertible1&) {} - Convertible1& operator=(const Convertible1&) { return *this; } - - // implicit conversion from Convertible2 - Convertible1(const Convertible2&) {} // NOLINT(runtime/explicit) -}; - -struct Convertible2 { - Convertible2() {} - Convertible2(const Convertible2&) {} - Convertible2& operator=(const Convertible2&) { return *this; } - - // implicit conversion from Convertible1 - Convertible2(const Convertible1&) {} // NOLINT(runtime/explicit) -}; - -TEST(VariantTest, TestRvalueConversion) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<double, std::string> var( - ConvertVariantTo<variant<double, std::string>>( - variant<std::string, int>(0))); - ASSERT_TRUE(absl::holds_alternative<double>(var)); - EXPECT_EQ(0.0, absl::get<double>(var)); - - var = ConvertVariantTo<variant<double, std::string>>( - variant<const char*, float>("foo")); - ASSERT_TRUE(absl::holds_alternative<std::string>(var)); - EXPECT_EQ("foo", absl::get<std::string>(var)); - - variant<double> singleton( - ConvertVariantTo<variant<double>>(variant<int, float>(42))); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(42.0, absl::get<double>(singleton)); - - singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - - singleton = ConvertVariantTo<variant<double>>(variant<int>(0)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(0.0, absl::get<double>(singleton)); - - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42))); - 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)); - ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2)); - EXPECT_EQ(42, absl::get<uint32_t>(variant2)); -#endif // !ABSL_USES_STD_VARIANT - - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>( - (variant<Convertible2, Convertible1>(Convertible1())))); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>( - variant<Convertible2, Convertible1>(Convertible2())); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestLvalueConversion) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<std::string, int> source1 = 0; - variant<double, std::string> destination( - ConvertVariantTo<variant<double, std::string>>(source1)); - ASSERT_TRUE(absl::holds_alternative<double>(destination)); - EXPECT_EQ(0.0, absl::get<double>(destination)); - - variant<const char*, float> source2 = "foo"; - destination = ConvertVariantTo<variant<double, std::string>>(source2); - ASSERT_TRUE(absl::holds_alternative<std::string>(destination)); - EXPECT_EQ("foo", absl::get<std::string>(destination)); - - variant<int, float> source3(42); - variant<double> singleton(ConvertVariantTo<variant<double>>(source3)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(42.0, absl::get<double>(singleton)); - - source3 = 3.14f; - singleton = ConvertVariantTo<variant<double>>(source3); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - - variant<int> source4(0); - singleton = ConvertVariantTo<variant<double>>(source4); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(0.0, absl::get<double>(singleton)); - - variant<int32_t> source5(42); - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(source5)); - ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2)); - EXPECT_EQ(42, absl::get<int32_t>(variant2)); - - variant<uint32_t> source6(42); - variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6); - ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2)); - EXPECT_EQ(42, absl::get<uint32_t>(variant2)); -#endif - - variant<Convertible2, Convertible1> source7((Convertible1())); - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>(source7)); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - source7 = Convertible2(); - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestMoveConversion) { - using Variant = - variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>; - using OtherVariant = - variant<std::unique_ptr<int>, std::unique_ptr<std::string>>; - - Variant var( - ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)})); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const int>>(var)); - ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr); - EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var)); - - var = ConvertVariantTo<Variant>( - OtherVariant(absl::make_unique<std::string>("foo"))); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var)); -} - -TEST(VariantTest, DoesNotMoveFromLvalues) { - // We use shared_ptr here because it's both copyable and movable, and - // a moved-from shared_ptr is guaranteed to be null, so we can detect - // whether moving or copying has occurred. - using Variant = - variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>; - using OtherVariant = - variant<std::shared_ptr<int>, std::shared_ptr<std::string>>; - - Variant v1(std::make_shared<const int>(0)); - - // Test copy constructor - Variant v2(v1); - EXPECT_EQ(absl::get<std::shared_ptr<const int>>(v1), - absl::get<std::shared_ptr<const int>>(v2)); - - // Test copy-assignment operator - v1 = std::make_shared<const std::string>("foo"); - v2 = v1; - EXPECT_EQ(absl::get<std::shared_ptr<const std::string>>(v1), - absl::get<std::shared_ptr<const std::string>>(v2)); - - // Test converting copy constructor - OtherVariant other(std::make_shared<int>(0)); - Variant v3(ConvertVariantTo<Variant>(other)); - EXPECT_EQ(absl::get<std::shared_ptr<int>>(other), - absl::get<std::shared_ptr<const int>>(v3)); - - other = std::make_shared<std::string>("foo"); - v3 = ConvertVariantTo<Variant>(other); - EXPECT_EQ(absl::get<std::shared_ptr<std::string>>(other), - absl::get<std::shared_ptr<const std::string>>(v3)); -} - -TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<double, std::string> var( - ConvertVariantTo<variant<double, std::string>>( - variant<std::string, int>(3))); - EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0)); - - var = ConvertVariantTo<variant<double, std::string>>( - variant<const char*, float>("foo")); - EXPECT_THAT(absl::get_if<std::string>(&var), Pointee(std::string("foo"))); - - variant<double> singleton( - ConvertVariantTo<variant<double>>(variant<int, float>(42))); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0)); - - singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f))); - - singleton = ConvertVariantTo<variant<double>>(variant<int>(3)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0)); - - variant<int32_t, uint32_t> variant2( - 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)); - EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42)); -#endif - - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>( - (variant<Convertible2, Convertible1>(Convertible1())))); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>( - variant<Convertible2, Convertible1>(Convertible2())); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<std::string, int> source1 = 3; - variant<double, std::string> destination( - ConvertVariantTo<variant<double, std::string>>(source1)); - EXPECT_THAT(absl::get_if<double>(&destination), Pointee(3.0)); - - variant<const char*, float> source2 = "foo"; - destination = ConvertVariantTo<variant<double, std::string>>(source2); - EXPECT_THAT(absl::get_if<std::string>(&destination), - Pointee(std::string("foo"))); - - variant<int, float> source3(42); - variant<double> singleton(ConvertVariantTo<variant<double>>(source3)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0)); - - source3 = 3.14f; - singleton = ConvertVariantTo<variant<double>>(source3); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f))); - - variant<int> source4(3); - singleton = ConvertVariantTo<variant<double>>(source4); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0)); - - variant<int32_t> source5(42); - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(source5)); - EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42)); - - variant<uint32_t> source6(42); - variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6); - EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42)); -#endif // !ABSL_USES_STD_VARIANT - - variant<Convertible2, Convertible1> source7((Convertible1())); - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>(source7)); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - source7 = Convertible2(); - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestMoveConversionViaConvertVariantTo) { - using Variant = - variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>; - using OtherVariant = - variant<std::unique_ptr<int>, std::unique_ptr<std::string>>; - - Variant var( - ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)})); - EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var), - Pointee(Pointee(3))); - - var = ConvertVariantTo<Variant>( - OtherVariant(absl::make_unique<std::string>("foo"))); - EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var), - Pointee(Pointee(std::string("foo")))); -} - -// If all alternatives are trivially copy/move constructible, variant should -// also be trivially copy/move constructible. This is not required by the -// standard and we know that libstdc++ variant doesn't have this feature. -// For more details see the paper: -// http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -#define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1 -#endif - -TEST(VariantTest, TestCopyAndMoveTypeTraits) { - EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value); - EXPECT_TRUE(absl::is_copy_assignable<variant<std::string>>::value); - EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value); - EXPECT_TRUE(absl::is_move_assignable<variant<std::string>>::value); - EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value); - EXPECT_TRUE(absl::is_move_assignable<variant<std::unique_ptr<int>>>::value); - EXPECT_FALSE( - std::is_copy_constructible<variant<std::unique_ptr<int>>>::value); - EXPECT_FALSE(absl::is_copy_assignable<variant<std::unique_ptr<int>>>::value); - - EXPECT_FALSE( - absl::is_trivially_copy_constructible<variant<std::string>>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<variant<std::string>>::value); -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - EXPECT_TRUE(absl::is_trivially_copy_constructible<variant<int>>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<variant<int>>::value); - EXPECT_TRUE(is_trivially_move_constructible<variant<int>>::value); - EXPECT_TRUE(is_trivially_move_assignable<variant<int>>::value); -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY -} - -TEST(VariantTest, TestVectorOfMoveonlyVariant) { - // Verify that variant<MoveonlyType> works correctly as a std::vector element. - std::vector<variant<std::unique_ptr<int>, std::string>> vec; - vec.push_back(absl::make_unique<int>(42)); - vec.emplace_back("Hello"); - vec.reserve(3); - auto another_vec = absl::move(vec); - // As a sanity check, verify vector contents. - ASSERT_EQ(2, another_vec.size()); - EXPECT_EQ(42, *absl::get<std::unique_ptr<int>>(another_vec[0])); - EXPECT_EQ("Hello", absl::get<std::string>(another_vec[1])); -} - -TEST(VariantTest, NestedVariant) { -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - static_assert(absl::is_trivially_copy_constructible<variant<int>>(), ""); - static_assert(absl::is_trivially_copy_assignable<variant<int>>(), ""); - static_assert(is_trivially_move_constructible<variant<int>>(), ""); - static_assert(is_trivially_move_assignable<variant<int>>(), ""); - - static_assert(absl::is_trivially_copy_constructible<variant<variant<int>>>(), - ""); - static_assert(absl::is_trivially_copy_assignable<variant<variant<int>>>(), - ""); - static_assert(is_trivially_move_constructible<variant<variant<int>>>(), ""); - static_assert(is_trivially_move_assignable<variant<variant<int>>>(), ""); -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - - variant<int> x(42); - variant<variant<int>> y(x); - variant<variant<int>> z(y); - EXPECT_TRUE(absl::holds_alternative<variant<int>>(z)); - EXPECT_EQ(x, absl::get<variant<int>>(z)); -} - -struct TriviallyDestructible { - TriviallyDestructible(TriviallyDestructible&&) {} - TriviallyDestructible(const TriviallyDestructible&) {} - TriviallyDestructible& operator=(TriviallyDestructible&&) { return *this; } - TriviallyDestructible& operator=(const TriviallyDestructible&) { - return *this; - } -}; - -struct TriviallyMovable { - TriviallyMovable(TriviallyMovable&&) = default; - TriviallyMovable(TriviallyMovable const&) {} - TriviallyMovable& operator=(const TriviallyMovable&) { return *this; } -}; - -struct TriviallyCopyable { - TriviallyCopyable(const TriviallyCopyable&) = default; - TriviallyCopyable& operator=(const TriviallyCopyable&) { return *this; } -}; - -struct TriviallyMoveAssignable { - TriviallyMoveAssignable(TriviallyMoveAssignable&&) = default; - TriviallyMoveAssignable(const TriviallyMoveAssignable&) {} - TriviallyMoveAssignable& operator=(TriviallyMoveAssignable&&) = default; - TriviallyMoveAssignable& operator=(const TriviallyMoveAssignable&) { - return *this; - } -}; - -struct TriviallyCopyAssignable {}; - -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY -TEST(VariantTest, TestTriviality) { - { - using TrivDestVar = absl::variant<TriviallyDestructible>; - - EXPECT_FALSE(is_trivially_move_constructible<TrivDestVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivDestVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivDestVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivDestVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivDestVar>::value); - } - - { - using TrivMoveVar = absl::variant<TriviallyMovable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivMoveVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivMoveVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivMoveVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveVar>::value); - } - - { - using TrivCopyVar = absl::variant<TriviallyCopyable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivCopyVar>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivCopyVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivCopyVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivCopyVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyVar>::value); - } - - { - using TrivMoveAssignVar = absl::variant<TriviallyMoveAssignable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivMoveAssignVar>::value); - EXPECT_FALSE( - absl::is_trivially_copy_constructible<TrivMoveAssignVar>::value); - EXPECT_TRUE(is_trivially_move_assignable<TrivMoveAssignVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveAssignVar>::value); - } - - { - using TrivCopyAssignVar = absl::variant<TriviallyCopyAssignable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivCopyAssignVar>::value); - EXPECT_TRUE( - absl::is_trivially_copy_constructible<TrivCopyAssignVar>::value); - EXPECT_TRUE(is_trivially_move_assignable<TrivCopyAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivCopyAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyAssignVar>::value); - } -} -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - -// To verify that absl::variant correctly use the nontrivial move ctor of its -// member rather than use the trivial copy constructor. -TEST(VariantTest, MoveCtorBug) { - // To simulate std::tuple in libstdc++. - struct TrivialCopyNontrivialMove { - TrivialCopyNontrivialMove() = default; - TrivialCopyNontrivialMove(const TrivialCopyNontrivialMove&) = default; - TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) { called = true; } - bool called = false; - }; - { - using V = absl::variant<TrivialCopyNontrivialMove, int>; - V v1(absl::in_place_index<0>); - // this should invoke the move ctor, rather than the trivial copy ctor. - V v2(std::move(v1)); - EXPECT_TRUE(absl::get<0>(v2).called); - } - { - // this case failed to compile before our fix due to a GCC bug. - using V = absl::variant<int, TrivialCopyNontrivialMove>; - V v1(absl::in_place_index<1>); - // this should invoke the move ctor, rather than the trivial copy ctor. - V v2(std::move(v1)); - EXPECT_TRUE(absl::get<1>(v2).called); - } -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // #if !defined(ABSL_USES_STD_VARIANT) diff --git a/third_party/abseil_cpp/absl/utility/BUILD.bazel b/third_party/abseil_cpp/absl/utility/BUILD.bazel deleted file mode 100644 index 02b2c407f847..000000000000 --- a/third_party/abseil_cpp/absl/utility/BUILD.bazel +++ /dev/null @@ -1,55 +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. -# - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "utility", - hdrs = [ - "utility.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:base_internal", - "//absl/base:config", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "utility_test", - srcs = ["utility_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":utility", - "//absl/base:core_headers", - "//absl/memory", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/utility/CMakeLists.txt b/third_party/abseil_cpp/absl/utility/CMakeLists.txt deleted file mode 100644 index e1edd19aa013..000000000000 --- a/third_party/abseil_cpp/absl/utility/CMakeLists.txt +++ /dev/null @@ -1,44 +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. -# - -absl_cc_library( - NAME - utility - HDRS - "utility.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::base_internal - absl::config - absl::type_traits - PUBLIC -) - -absl_cc_test( - NAME - utility_test - SRCS - "utility_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::utility - absl::core_headers - absl::memory - absl::strings - gmock_main -) diff --git a/third_party/abseil_cpp/absl/utility/utility.h b/third_party/abseil_cpp/absl/utility/utility.h deleted file mode 100644 index bf9232209a9b..000000000000 --- a/third_party/abseil_cpp/absl/utility/utility.h +++ /dev/null @@ -1,350 +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 header file contains C++11 versions of standard <utility> header -// abstractions available within C++14 and C++17, and are designed to be drop-in -// replacement for code compliant with C++14 and C++17. -// -// The following abstractions are defined: -// -// * integer_sequence<T, Ints...> == std::integer_sequence<T, Ints...> -// * index_sequence<Ints...> == std::index_sequence<Ints...> -// * make_integer_sequence<T, N> == std::make_integer_sequence<T, N> -// * make_index_sequence<N> == std::make_index_sequence<N> -// * index_sequence_for<Ts...> == std::index_sequence_for<Ts...> -// * apply<Functor, Tuple> == std::apply<Functor, Tuple> -// * exchange<T> == std::exchange<T> -// * make_from_tuple<T> == std::make_from_tuple<T> -// -// This header file also provides the tag types `in_place_t`, `in_place_type_t`, -// and `in_place_index_t`, as well as the constant `in_place`, and -// `constexpr` `std::move()` and `std::forward()` implementations in C++11. -// -// References: -// -// https://en.cppreference.com/w/cpp/utility/integer_sequence -// https://en.cppreference.com/w/cpp/utility/apply -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html - -#ifndef ABSL_UTILITY_UTILITY_H_ -#define ABSL_UTILITY_UTILITY_H_ - -#include <cstddef> -#include <cstdlib> -#include <tuple> -#include <utility> - -#include "absl/base/config.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/base/internal/invoke.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence<T, Ints...>); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence<int, 5>()); -// } -template <typename T, T... Ints> -struct integer_sequence { - using value_type = T; - static constexpr size_t size() noexcept { return sizeof...(Ints); } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template <size_t... Ints> -using index_sequence = integer_sequence<size_t, Ints...>; - -namespace utility_internal { - -template <typename Seq, size_t SeqSize, size_t Rem> -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template <typename T, T... Ints, size_t SeqSize> -struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> { - using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>; -}; - -template <typename T, T... Ints, size_t SeqSize> -struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> { - using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>; -}; - -// Recursion helper for 'make_integer_sequence<T, N>'. -// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. -template <typename T, size_t N> -struct Gen { - using type = - typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type; -}; - -template <typename T> -struct Gen<T, 0> { - using type = integer_sequence<T>; -}; - -template <typename T> -struct InPlaceTypeTag { - explicit InPlaceTypeTag() = delete; - InPlaceTypeTag(const InPlaceTypeTag&) = delete; - InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete; -}; - -template <size_t I> -struct InPlaceIndexTag { - explicit InPlaceIndexTag() = delete; - InPlaceIndexTag(const InPlaceIndexTag&) = delete; - InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template <typename T, T N> -using make_integer_sequence = typename utility_internal::Gen<T, N>::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template <size_t N> -using make_index_sequence = make_integer_sequence<size_t, N>; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template <typename... Ts> -using index_sequence_for = make_index_sequence<sizeof...(Ts)>; - -// Tag types - -#ifdef ABSL_USES_STD_OPTIONAL - -using std::in_place_t; -using std::in_place; - -#else // ABSL_USES_STD_OPTIONAL - -// in_place_t -// -// Tag type used to specify in-place construction, such as with -// `absl::optional`, designed to be a drop-in replacement for C++17's -// `std::in_place_t`. -struct in_place_t {}; - -ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {}); - -#endif // ABSL_USES_STD_OPTIONAL - -#if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT) -using std::in_place_type; -using std::in_place_type_t; -#else - -// in_place_type_t -// -// Tag type used for in-place construction when the type to construct needs to -// be specified, such as with `absl::any`, designed to be a drop-in replacement -// for C++17's `std::in_place_type_t`. -template <typename T> -using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>); - -template <typename T> -void in_place_type(utility_internal::InPlaceTypeTag<T>) {} -#endif // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT - -#ifdef ABSL_USES_STD_VARIANT -using std::in_place_index; -using std::in_place_index_t; -#else - -// in_place_index_t -// -// Tag type used for in-place construction when the type to construct needs to -// be specified, such as with `absl::any`, designed to be a drop-in replacement -// for C++17's `std::in_place_index_t`. -template <size_t I> -using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>); - -template <size_t I> -void in_place_index(utility_internal::InPlaceIndexTag<I>) {} -#endif // ABSL_USES_STD_VARIANT - -// Constexpr move and forward - -// move() -// -// A constexpr version of `std::move()`, designed to be a drop-in replacement -// for C++14's `std::move()`. -template <typename T> -constexpr absl::remove_reference_t<T>&& move(T&& t) noexcept { - return static_cast<absl::remove_reference_t<T>&&>(t); -} - -// forward() -// -// A constexpr version of `std::forward()`, designed to be a drop-in replacement -// for C++14's `std::forward()`. -template <typename T> -constexpr T&& forward( - absl::remove_reference_t<T>& t) noexcept { // NOLINT(runtime/references) - return static_cast<T&&>(t); -} - -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( - absl::forward<Functor>(functor), - std::get<Indexes>(absl::forward<Tuple>(t))...)) { - return absl::base_internal::invoke( - absl::forward<Functor>(functor), - std::get<Indexes>(absl::forward<Tuple>(t))...); -} - -} // namespace utility_internal - -// apply -// -// Invokes a Callable using elements of a tuple as its arguments. -// Each element of the tuple corresponds to an argument of the call (in order). -// Both the Callable argument and the tuple argument are perfect-forwarded. -// For member-function Callables, the first tuple element acts as the `this` -// pointer. `absl::apply` is designed to be a drop-in replacement for C++17's -// `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`. -// -// Example: -// -// class Foo { -// public: -// void Bar(int); -// }; -// void user_function1(int, std::string); -// void user_function2(std::unique_ptr<Foo>); -// auto user_lambda = [](int, int) {}; -// -// int main() -// { -// std::tuple<int, std::string> tuple1(42, "bar"); -// // Invokes the first user function on int, std::string. -// absl::apply(&user_function1, tuple1); -// -// std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>()); -// // Invokes the user function that takes ownership of the unique -// // pointer. -// absl::apply(&user_function2, std::move(tuple2)); -// -// auto foo = absl::make_unique<Foo>(); -// std::tuple<Foo*, int> tuple3(foo.get(), 42); -// // Invokes the method Bar on foo with one argument, 42. -// absl::apply(&Foo::Bar, tuple3); -// -// std::tuple<int, int> tuple4(8, 9); -// // Invokes a lambda. -// absl::apply(user_lambda, tuple4); -// } -template <typename Functor, typename Tuple> -auto apply(Functor&& functor, Tuple&& t) - -> decltype(utility_internal::apply_helper( - absl::forward<Functor>(functor), absl::forward<Tuple>(t), - absl::make_index_sequence<std::tuple_size< - typename std::remove_reference<Tuple>::type>::value>{})) { - return utility_internal::apply_helper( - absl::forward<Functor>(functor), absl::forward<Tuple>(t), - absl::make_index_sequence<std::tuple_size< - typename std::remove_reference<Tuple>::type>::value>{}); -} - -// exchange -// -// Replaces the value of `obj` with `new_value` and returns the old value of -// `obj`. `absl::exchange` is designed to be a drop-in replacement for C++14's -// `std::exchange`. -// -// Example: -// -// Foo& operator=(Foo&& other) { -// ptr1_ = absl::exchange(other.ptr1_, nullptr); -// int1_ = absl::exchange(other.int1_, -1); -// return *this; -// } -template <typename T, typename U = T> -T exchange(T& obj, U&& new_value) { - T old_value = absl::move(obj); - obj = absl::forward<U>(new_value); - return old_value; -} - -namespace utility_internal { -template <typename T, typename Tuple, size_t... I> -T make_from_tuple_impl(Tuple&& tup, absl::index_sequence<I...>) { - return T(std::get<I>(std::forward<Tuple>(tup))...); -} -} // namespace utility_internal - -// make_from_tuple -// -// Given the template parameter type `T` and a tuple of arguments -// `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by -// calling `T(arg0, arg1, ..., argN)`. -// -// Example: -// -// std::tuple<const char*, size_t> args("hello world", 5); -// auto s = absl::make_from_tuple<std::string>(args); -// assert(s == "hello"); -// -template <typename T, typename Tuple> -constexpr T make_from_tuple(Tuple&& tup) { - return utility_internal::make_from_tuple_impl<T>( - std::forward<Tuple>(tup), - absl::make_index_sequence< - std::tuple_size<absl::decay_t<Tuple>>::value>{}); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_UTILITY_UTILITY_H_ diff --git a/third_party/abseil_cpp/absl/utility/utility_test.cc b/third_party/abseil_cpp/absl/utility/utility_test.cc deleted file mode 100644 index f044ad644a4d..000000000000 --- a/third_party/abseil_cpp/absl/utility/utility_test.cc +++ /dev/null @@ -1,376 +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/utility/utility.h" - -#include <sstream> -#include <string> -#include <tuple> -#include <type_traits> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" - -namespace { - -#ifdef _MSC_VER -// Warnings for unused variables in this test are false positives. On other -// platforms, they are suppressed by ABSL_ATTRIBUTE_UNUSED, but that doesn't -// work on MSVC. -// Both the unused variables and the name length warnings are due to calls -// to absl::make_index_sequence with very large values, creating very long type -// names. The resulting warnings are so long they make build output unreadable. -#pragma warning( push ) -#pragma warning( disable : 4503 ) // decorated name length exceeded -#pragma warning( disable : 4101 ) // unreferenced local variable -#endif // _MSC_VER - -using ::testing::ElementsAre; -using ::testing::Pointee; -using ::testing::StaticAssertTypeEq; - -TEST(IntegerSequenceTest, ValueType) { - StaticAssertTypeEq<int, absl::integer_sequence<int>::value_type>(); - StaticAssertTypeEq<char, absl::integer_sequence<char>::value_type>(); -} - -TEST(IntegerSequenceTest, Size) { - EXPECT_EQ(0, (absl::integer_sequence<int>::size())); - EXPECT_EQ(1, (absl::integer_sequence<int, 0>::size())); - EXPECT_EQ(1, (absl::integer_sequence<int, 1>::size())); - EXPECT_EQ(2, (absl::integer_sequence<int, 1, 2>::size())); - EXPECT_EQ(3, (absl::integer_sequence<int, 0, 1, 2>::size())); - EXPECT_EQ(3, (absl::integer_sequence<int, -123, 123, 456>::size())); - constexpr size_t sz = absl::integer_sequence<int, 0, 1>::size(); - EXPECT_EQ(2, sz); -} - -TEST(IntegerSequenceTest, MakeIndexSequence) { - StaticAssertTypeEq<absl::index_sequence<>, absl::make_index_sequence<0>>(); - StaticAssertTypeEq<absl::index_sequence<0>, absl::make_index_sequence<1>>(); - StaticAssertTypeEq<absl::index_sequence<0, 1>, - absl::make_index_sequence<2>>(); - StaticAssertTypeEq<absl::index_sequence<0, 1, 2>, - absl::make_index_sequence<3>>(); -} - -TEST(IntegerSequenceTest, MakeIntegerSequence) { - StaticAssertTypeEq<absl::integer_sequence<int>, - absl::make_integer_sequence<int, 0>>(); - StaticAssertTypeEq<absl::integer_sequence<int, 0>, - absl::make_integer_sequence<int, 1>>(); - StaticAssertTypeEq<absl::integer_sequence<int, 0, 1>, - absl::make_integer_sequence<int, 2>>(); - StaticAssertTypeEq<absl::integer_sequence<int, 0, 1, 2>, - absl::make_integer_sequence<int, 3>>(); -} - -template <typename... Ts> -class Counter {}; - -template <size_t... Is> -void CountAll(absl::index_sequence<Is...>) { - // We only need an alias here, but instantiate a variable to silence warnings - // for unused typedefs in some compilers. - ABSL_ATTRIBUTE_UNUSED Counter<absl::make_index_sequence<Is>...> seq; -} - -// This test verifies that absl::make_index_sequence can handle large arguments -// without blowing up template instantiation stack, going OOM or taking forever -// to compile (there is hard 15 minutes limit imposed by forge). -TEST(IntegerSequenceTest, MakeIndexSequencePerformance) { - // O(log N) template instantiations. - // We only need an alias here, but instantiate a variable to silence warnings - // for unused typedefs in some compilers. - ABSL_ATTRIBUTE_UNUSED absl::make_index_sequence<(1 << 16) - 1> seq; - // O(N) template instantiations. - CountAll(absl::make_index_sequence<(1 << 8) - 1>()); -} - -template <typename F, typename Tup, size_t... Is> -auto ApplyFromTupleImpl(F f, const Tup& tup, absl::index_sequence<Is...>) - -> decltype(f(std::get<Is>(tup)...)) { - return f(std::get<Is>(tup)...); -} - -template <typename Tup> -using TupIdxSeq = absl::make_index_sequence<std::tuple_size<Tup>::value>; - -template <typename F, typename Tup> -auto ApplyFromTuple(F f, const Tup& tup) - -> decltype(ApplyFromTupleImpl(f, tup, TupIdxSeq<Tup>{})) { - return ApplyFromTupleImpl(f, tup, TupIdxSeq<Tup>{}); -} - -template <typename T> -std::string Fmt(const T& x) { - std::ostringstream os; - os << x; - return os.str(); -} - -struct PoorStrCat { - template <typename... Args> - std::string operator()(const Args&... args) const { - std::string r; - for (const auto& e : {Fmt(args)...}) r += e; - return r; - } -}; - -template <typename Tup, size_t... Is> -std::vector<std::string> TupStringVecImpl(const Tup& tup, - absl::index_sequence<Is...>) { - return {Fmt(std::get<Is>(tup))...}; -} - -template <typename... Ts> -std::vector<std::string> TupStringVec(const std::tuple<Ts...>& tup) { - return TupStringVecImpl(tup, absl::index_sequence_for<Ts...>()); -} - -TEST(MakeIndexSequenceTest, ApplyFromTupleExample) { - PoorStrCat f{}; - EXPECT_EQ("12abc3.14", f(12, "abc", 3.14)); - EXPECT_EQ("12abc3.14", ApplyFromTuple(f, std::make_tuple(12, "abc", 3.14))); -} - -TEST(IndexSequenceForTest, Basic) { - StaticAssertTypeEq<absl::index_sequence<>, absl::index_sequence_for<>>(); - StaticAssertTypeEq<absl::index_sequence<0>, absl::index_sequence_for<int>>(); - StaticAssertTypeEq<absl::index_sequence<0, 1, 2, 3>, - absl::index_sequence_for<int, void, char, int>>(); -} - -TEST(IndexSequenceForTest, Example) { - EXPECT_THAT(TupStringVec(std::make_tuple(12, "abc", 3.14)), - ElementsAre("12", "abc", "3.14")); -} - -int Function(int a, int b) { return a - b; } - -int Sink(std::unique_ptr<int> p) { return *p; } - -std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); } - -void NoOp() {} - -struct ConstFunctor { - int operator()(int a, int b) const { return a - b; } -}; - -struct MutableFunctor { - int operator()(int a, int b) { return a - b; } -}; - -struct EphemeralFunctor { - EphemeralFunctor() {} - EphemeralFunctor(const EphemeralFunctor&) {} - EphemeralFunctor(EphemeralFunctor&&) {} - int operator()(int a, int b) && { return a - b; } -}; - -struct OverloadedFunctor { - OverloadedFunctor() {} - OverloadedFunctor(const OverloadedFunctor&) {} - OverloadedFunctor(OverloadedFunctor&&) {} - template <typename... Args> - std::string operator()(const Args&... args) & { - return absl::StrCat("&", args...); - } - template <typename... Args> - std::string operator()(const Args&... args) const& { - return absl::StrCat("const&", args...); - } - template <typename... Args> - std::string operator()(const Args&... args) && { - return absl::StrCat("&&", args...); - } -}; - -struct Class { - int Method(int a, int b) { return a - b; } - int ConstMethod(int a, int b) const { return a - b; } - - int member; -}; - -struct FlipFlop { - int ConstMethod() const { return member; } - FlipFlop operator*() const { return {-member}; } - - int member; -}; - -TEST(ApplyTest, Function) { - EXPECT_EQ(1, absl::apply(Function, std::make_tuple(3, 2))); - EXPECT_EQ(1, absl::apply(&Function, std::make_tuple(3, 2))); -} - -TEST(ApplyTest, NonCopyableArgument) { - EXPECT_EQ(42, absl::apply(Sink, std::make_tuple(absl::make_unique<int>(42)))); -} - -TEST(ApplyTest, NonCopyableResult) { - EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)), - ::testing::Pointee(42)); -} - -TEST(ApplyTest, VoidResult) { absl::apply(NoOp, std::tuple<>()); } - -TEST(ApplyTest, ConstFunctor) { - EXPECT_EQ(1, absl::apply(ConstFunctor(), std::make_tuple(3, 2))); -} - -TEST(ApplyTest, MutableFunctor) { - MutableFunctor f; - EXPECT_EQ(1, absl::apply(f, std::make_tuple(3, 2))); - EXPECT_EQ(1, absl::apply(MutableFunctor(), std::make_tuple(3, 2))); -} -TEST(ApplyTest, EphemeralFunctor) { - EphemeralFunctor f; - EXPECT_EQ(1, absl::apply(std::move(f), std::make_tuple(3, 2))); - EXPECT_EQ(1, absl::apply(EphemeralFunctor(), std::make_tuple(3, 2))); -} -TEST(ApplyTest, OverloadedFunctor) { - OverloadedFunctor f; - const OverloadedFunctor& cf = f; - - EXPECT_EQ("&", absl::apply(f, std::tuple<>{})); - EXPECT_EQ("& 42", absl::apply(f, std::make_tuple(" 42"))); - - EXPECT_EQ("const&", absl::apply(cf, std::tuple<>{})); - EXPECT_EQ("const& 42", absl::apply(cf, std::make_tuple(" 42"))); - - EXPECT_EQ("&&", absl::apply(std::move(f), std::tuple<>{})); - OverloadedFunctor f2; - EXPECT_EQ("&& 42", absl::apply(std::move(f2), std::make_tuple(" 42"))); -} - -TEST(ApplyTest, ReferenceWrapper) { - ConstFunctor cf; - MutableFunctor mf; - EXPECT_EQ(1, absl::apply(std::cref(cf), std::make_tuple(3, 2))); - EXPECT_EQ(1, absl::apply(std::ref(cf), std::make_tuple(3, 2))); - EXPECT_EQ(1, absl::apply(std::ref(mf), std::make_tuple(3, 2))); -} - -TEST(ApplyTest, MemberFunction) { - std::unique_ptr<Class> p(new Class); - std::unique_ptr<const Class> cp(new Class); - EXPECT_EQ( - 1, absl::apply(&Class::Method, - std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::Method, - std::tuple<Class*, int, int>(p.get(), 3, 2))); - EXPECT_EQ( - 1, absl::apply(&Class::Method, std::tuple<Class&, int, int>(*p, 3, 2))); - - EXPECT_EQ( - 1, absl::apply(&Class::ConstMethod, - std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::tuple<Class*, int, int>(p.get(), 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::tuple<Class&, int, int>(*p, 3, 2))); - - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::tuple<std::unique_ptr<const Class>&, int, int>( - cp, 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::tuple<const Class*, int, int>(cp.get(), 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::tuple<const Class&, int, int>(*cp, 3, 2))); - - EXPECT_EQ(1, absl::apply(&Class::Method, - std::make_tuple(absl::make_unique<Class>(), 3, 2))); - EXPECT_EQ(1, absl::apply(&Class::ConstMethod, - std::make_tuple(absl::make_unique<Class>(), 3, 2))); - EXPECT_EQ( - 1, absl::apply(&Class::ConstMethod, - std::make_tuple(absl::make_unique<const Class>(), 3, 2))); -} - -TEST(ApplyTest, DataMember) { - std::unique_ptr<Class> p(new Class{42}); - std::unique_ptr<const Class> cp(new Class{42}); - EXPECT_EQ( - 42, absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p))); - EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class&>(*p))); - EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class*>(p.get()))); - - absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)) = 42; - absl::apply(&Class::member, std::tuple<Class*>(p.get())) = 42; - absl::apply(&Class::member, std::tuple<Class&>(*p)) = 42; - - EXPECT_EQ(42, absl::apply(&Class::member, - std::tuple<std::unique_ptr<const Class>&>(cp))); - EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<const Class&>(*cp))); - EXPECT_EQ(42, - absl::apply(&Class::member, std::tuple<const Class*>(cp.get()))); -} - -TEST(ApplyTest, 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, absl::apply(&FlipFlop::ConstMethod, std::make_tuple(obj))); - EXPECT_EQ(42, absl::apply(&FlipFlop::member, std::make_tuple(obj))); -} - -TEST(ExchangeTest, MoveOnly) { - auto a = Factory(1); - EXPECT_EQ(1, *a); - auto b = absl::exchange(a, Factory(2)); - EXPECT_EQ(2, *a); - EXPECT_EQ(1, *b); -} - -TEST(MakeFromTupleTest, String) { - EXPECT_EQ( - absl::make_from_tuple<std::string>(std::make_tuple("hello world", 5)), - "hello"); -} - -TEST(MakeFromTupleTest, MoveOnlyParameter) { - struct S { - S(std::unique_ptr<int> n, std::unique_ptr<int> m) : value(*n + *m) {} - int value = 0; - }; - auto tup = - std::make_tuple(absl::make_unique<int>(3), absl::make_unique<int>(4)); - auto s = absl::make_from_tuple<S>(std::move(tup)); - EXPECT_EQ(s.value, 7); -} - -TEST(MakeFromTupleTest, NoParameters) { - struct S { - S() : value(1) {} - int value = 2; - }; - EXPECT_EQ(absl::make_from_tuple<S>(std::make_tuple()).value, 1); -} - -TEST(MakeFromTupleTest, Pair) { - EXPECT_EQ( - (absl::make_from_tuple<std::pair<bool, int>>(std::make_tuple(true, 17))), - std::make_pair(true, 17)); -} - -} // namespace - diff --git a/third_party/abseil_cpp/ci/absl_alternate_options.h b/third_party/abseil_cpp/ci/absl_alternate_options.h deleted file mode 100644 index 29b020d9fa65..000000000000 --- a/third_party/abseil_cpp/ci/absl_alternate_options.h +++ /dev/null @@ -1,29 +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. - -// 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 aec8a117174e..000000000000 --- 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="8567b09290fe402cf01923e2131c5635b8ed851b" - -# Avoid depending on GitHub by looking for a cached copy of the commit first. -if [[ -r "${KOKORO_GFILE_DIR:-}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - ABSL_GOOGLETEST_DOWNLOAD_URL="file:///distdir/${ABSL_GOOGLETEST_COMMIT}.zip" -else - ABSL_GOOGLETEST_DOWNLOAD_URL="https://github.com/google/googletest/archive/${ABSL_GOOGLETEST_COMMIT}.zip" -fi diff --git a/third_party/abseil_cpp/ci/cmake_install_test.sh b/third_party/abseil_cpp/ci/cmake_install_test.sh deleted file mode 100755 index 5bf540c53828..000000000000 --- a/third_party/abseil_cpp/ci/cmake_install_test.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -source "${ABSEIL_ROOT}/ci/cmake_common.sh" - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} - -time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --workdir=/abseil-cpp \ - --tmpfs=/buildfs:exec \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CFLAGS="-Werror" \ - -e CXXFLAGS="-Werror" \ - ${DOCKER_CONTAINER} \ - /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 deleted file mode 100755 index ffbb8327e731..000000000000 --- a/third_party/abseil_cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/opt/llvm/clang/bin/clang" \ - -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ - -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ - -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt="-fsanitize=address" \ - --copt="-fsanitize=float-divide-by-zero" \ - --copt="-fsanitize=nullability" \ - --copt="-fsanitize=undefined" \ - --copt="-fno-sanitize-blacklist" \ - --copt=-Werror \ - --keep_going \ - --linkopt="-fsanitize=address" \ - --linkopt="-fsanitize-link-c++-runtime" \ - --show_timestamps \ - --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_env="UBSAN_OPTIONS=print_stacktrace=1" \ - --test_env="UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_output=errors \ - --test_tag_filters="-benchmark,-noasan" \ - ${BAZEL_EXTRA_ARGS:-} - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_clang-latest_libcxx_bazel.sh b/third_party/abseil_cpp/ci/linux_clang-latest_libcxx_bazel.sh deleted file mode 100755 index f6a2221e8a00..000000000000 --- a/third_party/abseil_cpp/ci/linux_clang-latest_libcxx_bazel.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \ - --tmpfs=/abseil-cpp \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/opt/llvm/clang/bin/clang" \ - -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ - -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ - -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /bin/sh -c " - cp -r /abseil-cpp-ro/* /abseil-cpp/ - if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then - cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 - fi - /usr/local/bin/bazel test ... \ - --compilation_mode=\"${compilation_mode}\" \ - --copt=\"${exceptions_mode}\" \ - --copt=-Werror \ - --define=\"absl=1\" \ - --keep_going \ - --show_timestamps \ - --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \ - --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ - --test_output=errors \ - --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-}" - done - done -done diff --git a/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 deleted file mode 100755 index e70e8214cd10..000000000000 --- a/third_party/abseil_cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/opt/llvm/clang/bin/clang" \ - -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ - -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \ - -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --build_tag_filters="-notsan" \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt="-fsanitize=thread" \ - --copt="-fno-sanitize-blacklist" \ - --copt=-Werror \ - --keep_going \ - --linkopt="-fsanitize=thread" \ - --show_timestamps \ - --test_env="TSAN_OPTIONS=report_atomic_races=0" \ - --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_output=errors \ - --test_tag_filters="-benchmark,-notsan" \ - ${BAZEL_EXTRA_ARGS:-} - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_clang-latest_libstdcxx_bazel.sh b/third_party/abseil_cpp/ci/linux_clang-latest_libstdcxx_bazel.sh deleted file mode 100755 index 0986ff40ccf9..000000000000 --- a/third_party/abseil_cpp/ci/linux_clang-latest_libstdcxx_bazel.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/opt/llvm/clang/bin/clang" \ - -e BAZEL_CXXOPTS="-std=${std}" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --compilation_mode="${compilation_mode}" \ - --copt="--gcc-toolchain=/usr/local" \ - --copt="${exceptions_mode}" \ - --copt=-Werror \ - --define="absl=1" \ - --keep_going \ - --linkopt="--gcc-toolchain=/usr/local" \ - --show_timestamps \ - --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_output=errors \ - --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-} - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_docker_containers.sh b/third_party/abseil_cpp/ci/linux_docker_containers.sh deleted file mode 100644 index 1c29d9a1f17f..000000000000 --- 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:20201008" -readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008" -readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015" diff --git a/third_party/abseil_cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh b/third_party/abseil_cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh deleted file mode 100755 index 224aef81cbe7..000000000000 --- a/third_party/abseil_cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# -# Copyright 2020 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_GCC_FLOOR_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/usr/local/bin/gcc" \ - -e BAZEL_CXXOPTS="-std=${std}" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /usr/local/bin/bazel test ... \ - --compilation_mode="${compilation_mode}" \ - --copt="${exceptions_mode}" \ - --copt=-Werror \ - --define="absl=1" \ - --keep_going \ - --show_timestamps \ - --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ - --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_output=errors \ - --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-} - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh b/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh deleted file mode 100755 index 37d89d9f829c..000000000000 --- a/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script that can be invoked to test abseil-cpp in a hermetic environment -# using a Docker image on Linux. You must have Docker installed to use this -# script. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" -fi - -if [[ -z ${COMPILATION_MODE:-} ]]; then - COMPILATION_MODE="fastbuild opt" -fi - -if [[ -z ${EXCEPTIONS_MODE:-} ]]; then - EXCEPTIONS_MODE="-fno-exceptions -fexceptions" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} - -# USE_BAZEL_CACHE=1 only works on Kokoro. -# Without access to the credentials this won't work. -if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}" - # Bazel doesn't track changes to tools outside of the workspace - # (e.g. /usr/bin/gcc), so by appending the docker container to the - # remote_http_cache url, we make changes to the container part of - # the cache key. Hashing the key is to make it shorter and url-safe. - container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16) - BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}" -fi - -# Avoid depending on external sites like GitHub by checking --distdir for -# external dependencies first. -# https://docs.bazel.build/versions/master/guide.html#distdir -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then - DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}" - BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" -fi - -for std in ${STD}; do - for compilation_mode in ${COMPILATION_MODE}; do - for exceptions_mode in ${EXCEPTIONS_MODE}; do - echo "--------------------------------------------------------------------" - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \ - --tmpfs=/abseil-cpp \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/usr/local/bin/gcc" \ - -e BAZEL_CXXOPTS="-std=${std}" \ - ${DOCKER_EXTRA_ARGS:-} \ - ${DOCKER_CONTAINER} \ - /bin/sh -c " - cp -r /abseil-cpp-ro/* /abseil-cpp/ - if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then - cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 - fi - /usr/local/bin/bazel test ... \ - --compilation_mode=\"${compilation_mode}\" \ - --copt=\"${exceptions_mode}\" \ - --copt=-Werror \ - --define=\"absl=1\" \ - --keep_going \ - --show_timestamps \ - --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \ - --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \ - --test_output=errors \ - --test_tag_filters=-benchmark \ - ${BAZEL_EXTRA_ARGS:-}" - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh b/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh deleted file mode 100755 index ed9cfa385251..000000000000 --- a/third_party/abseil_cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -source "${ABSEIL_ROOT}/ci/cmake_common.sh" - -if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then - ABSL_CMAKE_CXX_STANDARDS="11 14 17 20" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then - ABSL_CMAKE_BUILD_TYPES="Debug Release" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then - ABSL_CMAKE_BUILD_SHARED="OFF ON" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER} - -for std in ${ABSL_CMAKE_CXX_STANDARDS}; do - for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do - for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --tmpfs=/buildfs:exec \ - --workdir=/buildfs \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CFLAGS="-Werror" \ - -e CXXFLAGS="-Werror" \ - ${DOCKER_EXTRA_ARGS:-} \ - "${DOCKER_CONTAINER}" \ - /bin/bash -c " - cmake /abseil-cpp \ - -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \ - -DABSL_RUN_TESTS=ON \ - -DBUILD_SHARED_LIBS=${build_shared} \ - -DCMAKE_BUILD_TYPE=${compilation_mode} \ - -DCMAKE_CXX_STANDARD=${std} \ - -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \ - make -j$(nproc) && \ - ctest -j$(nproc) --output-on-failure" - done - done -done diff --git a/third_party/abseil_cpp/ci/linux_gcc_alpine_cmake.sh b/third_party/abseil_cpp/ci/linux_gcc_alpine_cmake.sh deleted file mode 100755 index 31310ac791ec..000000000000 --- a/third_party/abseil_cpp/ci/linux_gcc_alpine_cmake.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -source "${ABSEIL_ROOT}/ci/cmake_common.sh" - -if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then - ABSL_CMAKE_CXX_STANDARDS="11 14 17" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then - ABSL_CMAKE_BUILD_TYPES="Debug Release" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then - ABSL_CMAKE_BUILD_SHARED="OFF ON" -fi - -source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh" -readonly DOCKER_CONTAINER=${LINUX_ALPINE_CONTAINER} - -for std in ${ABSL_CMAKE_CXX_STANDARDS}; do - for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do - for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do - time docker run \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --tmpfs=/buildfs:exec \ - --workdir=/buildfs \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CFLAGS="-Werror" \ - -e CXXFLAGS="-Werror" \ - ${DOCKER_EXTRA_ARGS:-} \ - "${DOCKER_CONTAINER}" \ - /bin/sh -c " - cmake /abseil-cpp \ - -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \ - -DABSL_RUN_TESTS=ON \ - -DCMAKE_BUILD_TYPE=${compilation_mode} \ - -DCMAKE_CXX_STANDARD=${std} \ - -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \ - make -j$(nproc) && \ - ctest -j$(nproc) --output-on-failure" - done - done -done diff --git a/third_party/abseil_cpp/ci/macos_xcode_bazel.sh b/third_party/abseil_cpp/ci/macos_xcode_bazel.sh deleted file mode 100755 index 738adf947655..000000000000 --- a/third_party/abseil_cpp/ci/macos_xcode_bazel.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script is invoked on Kokoro to test Abseil on macOS. -# It is not hermetic and may break when Kokoro is updated. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" -fi - -# If we are running on Kokoro, check for a versioned Bazel binary. -KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64" -if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then - BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" - chmod +x ${BAZEL_BIN} -else - BAZEL_BIN="bazel" -fi - -# Print the compiler and Bazel versions. -echo "---------------" -gcc -v -echo "---------------" -${BAZEL_BIN} version -echo "---------------" - -cd ${ABSEIL_ROOT} - -if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then - cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 -fi - -${BAZEL_BIN} test ... \ - --copt=-Werror \ - --keep_going \ - --show_timestamps \ - --test_env="TZDIR=${ABSEIL_ROOT}/absl/time/internal/cctz/testdata/zoneinfo" \ - --test_output=errors \ - --test_tag_filters=-benchmark diff --git a/third_party/abseil_cpp/ci/macos_xcode_cmake.sh b/third_party/abseil_cpp/ci/macos_xcode_cmake.sh deleted file mode 100755 index 0847b3ea78a9..000000000000 --- a/third_party/abseil_cpp/ci/macos_xcode_cmake.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 The Abseil Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -euox pipefail - -if [[ -z ${ABSEIL_ROOT:-} ]]; then - ABSEIL_ROOT="$(dirname ${0})/.." -fi -ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT}) - -source "${ABSEIL_ROOT}/ci/cmake_common.sh" - -# The MacOS build doesn't run in a docker container, so we have to override ABSL_GOOGLETEST_DOWNLOAD_URL. -if [[ -r "${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then - ABSL_GOOGLETEST_DOWNLOAD_URL="file://${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then - ABSL_CMAKE_BUILD_TYPES="Debug" -fi - -if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then - ABSL_CMAKE_BUILD_SHARED="OFF ON" -fi - -for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do - for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do - BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX) - cd ${BUILD_DIR} - - # TODO(absl-team): Enable -Werror once all warnings are fixed. - time cmake ${ABSEIL_ROOT} \ - -GXcode \ - -DBUILD_SHARED_LIBS=${build_shared} \ - -DCMAKE_BUILD_TYPE=${compilation_mode} \ - -DCMAKE_CXX_STANDARD=11 \ - -DCMAKE_MODULE_LINKER_FLAGS="-Wl,--no-undefined" \ - -DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}" \ - -DABSL_RUN_TESTS=ON - time cmake --build . - time ctest -C ${compilation_mode} --output-on-failure - done -done diff --git a/third_party/abseil_cpp/conanfile.py b/third_party/abseil_cpp/conanfile.py deleted file mode 100755 index 926ec5ccd64b..000000000000 --- a/third_party/abseil_cpp/conanfile.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Note: Conan is supported on a best-effort basis. Abseil doesn't use Conan -# internally, so we won't know if it stops working. We may ask community -# members to help us debug any problems that arise. - -from conans import ConanFile, CMake, tools -from conans.errors import ConanInvalidConfiguration -from conans.model.version import Version - - -class AbseilConan(ConanFile): - name = "abseil" - url = "https://github.com/abseil/abseil-cpp" - homepage = url - author = "Abseil <abseil-io@googlegroups.com>" - description = "Abseil Common Libraries (C++) from Google" - license = "Apache-2.0" - topics = ("conan", "abseil", "abseil-cpp", "google", "common-libraries") - exports = ["LICENSE"] - exports_sources = ["CMakeLists.txt", "CMake/*", "absl/*"] - generators = "cmake" - settings = "os", "arch", "compiler", "build_type" - - def configure(self): - if self.settings.os == "Windows" and \ - self.settings.compiler == "Visual Studio" and \ - Version(self.settings.compiler.version.value) < "14": - raise ConanInvalidConfiguration("Abseil does not support MSVC < 14") - - def build(self): - tools.replace_in_file("CMakeLists.txt", "project(absl CXX)", "project(absl CXX)\ninclude(conanbuildinfo.cmake)\nconan_basic_setup()") - cmake = CMake(self) - cmake.definitions["BUILD_TESTING"] = False - cmake.configure() - cmake.build() - - def package(self): - self.copy("LICENSE", dst="licenses") - self.copy("*.h", dst="include", src=".") - self.copy("*.inc", dst="include", src=".") - self.copy("*.a", dst="lib", src=".", keep_path=False) - self.copy("*.lib", dst="lib", src=".", keep_path=False) - - def package_info(self): - if self.settings.os == "Linux": - self.cpp_info.libs = ["-Wl,--start-group"] - self.cpp_info.libs.extend(tools.collect_libs(self)) - if self.settings.os == "Linux": - self.cpp_info.libs.extend(["-Wl,--end-group", "pthread"]) diff --git a/third_party/abseil_cpp/default.nix b/third_party/abseil_cpp/default.nix index dd3ca9de9de1..bfc83831171a 100644 --- a/third_party/abseil_cpp/default.nix +++ b/third_party/abseil_cpp/default.nix @@ -5,27 +5,3 @@ in pkgs.abseil-cpp.override { stdenv = fullLlvm11Stdenv; cxxStandard = "17"; } - -/* TODO(tazjin): update abseil subtree - - fullLlvm11Stdenv.mkDerivation rec { - pname = "abseil-cpp"; - version = "20200519-768eb2ca+tvl-1"; - src = ./.; - nativeBuildInputs = [ cmake ]; - # TODO: run tests - # doCheck = true; - - cmakeFlags = [ - "-DCMAKE_CXX_STANDARD=17" - #"-DABSL_RUN_TESTS=1" - ]; - - meta = with lib; { - description = "An open-source collection of C++ code designed to augment the C++ standard library"; - homepage = https://abseil.io/; - license = licenses.asl20; - maintainers = [ maintainers.andersk ]; - }; - } -*/ |